Jelajahi Sumber

refactor: change from using @EnvironmentObject to @AppStorage, which has lower dev overhead

Sam Jaffe 3 minggu lalu
induk
melakukan
8769f9a5ad

+ 1 - 1
Todos/Model/URLHint.swift

@@ -8,7 +8,7 @@
 import Foundation
 import Foundation
 import SwiftData
 import SwiftData
 
 
-final class URLHint : Identifiable {
+final class URLHint : Identifiable, Codable {
   var prefix: String = ""
   var prefix: String = ""
   var replacement: String = ""
   var replacement: String = ""
   
   

+ 0 - 5
Todos/TodosApp.swift

@@ -29,20 +29,15 @@ struct TodosApp: App {
   }()
   }()
 
 
   var body: some Scene {
   var body: some Scene {
-    let urlHints = URLHintArray(
-      fromSerial: UserDefaults.standard.array(forKey: UserDefaultsKeys.UrlHints)
-      as? URLHintArray.Serial)
     WindowGroup {
     WindowGroup {
         ContentView()
         ContentView()
     }
     }
     .modelContainer(sharedModelContainer)
     .modelContainer(sharedModelContainer)
-    .environmentObject(urlHints)
     
     
     #if os(macOS)
     #if os(macOS)
     Settings {
     Settings {
         SettingsView()
         SettingsView()
     }
     }
-    .environmentObject(urlHints)
     #endif
     #endif
   }
   }
 }
 }

+ 0 - 1
Todos/View/CategoryPanelView.swift

@@ -43,5 +43,4 @@ struct CategoryPanelView: View {
 #Preview {
 #Preview {
   @Previewable @State var item = Category(timestamp: Date())
   @Previewable @State var item = Category(timestamp: Date())
   CategoryPanelView(item: item)
   CategoryPanelView(item: item)
-    .environmentObject(URLHintArray())
 }
 }

+ 0 - 1
Todos/View/ContentView.swift

@@ -74,5 +74,4 @@ struct ContentView: View {
 #Preview {
 #Preview {
   ContentView()
   ContentView()
       .modelContainer(for: Category.self, inMemory: true)
       .modelContainer(for: Category.self, inMemory: true)
-      .environmentObject(URLHintArray())
 }
 }

+ 4 - 9
Todos/View/SettingsView.swift

@@ -8,7 +8,7 @@
 import SwiftUI
 import SwiftUI
 
 
 struct SettingsView: View {
 struct SettingsView: View {
-  @EnvironmentObject var allHints: URLHintArray
+  @AppStorage(UserDefaultsKeys.UrlHints) var allHints = URLHintArray()
   @State var active = URLHint()
   @State var active = URLHint()
   
   
   var body: some View {
   var body: some View {
@@ -27,16 +27,14 @@ struct SettingsView: View {
           TableColumn("") { hint in
           TableColumn("") { hint in
             if hint.id != active.id {
             if hint.id != active.id {
               Button() {
               Button() {
-                allHints.array.removeAll(where: { $0.id == hint.id })
-                UserDefaults.standard.set(allHints.serial,
-                                          forKey: UserDefaultsKeys.UrlHints)
+                allHints.removeAll(where: { $0.id == hint.id })
               } label: {
               } label: {
                 Label("", systemImage: "trash")
                 Label("", systemImage: "trash")
               }
               }
             }
             }
           }.width(max: 20)
           }.width(max: 20)
         } rows: {
         } rows: {
-          ForEach($allHints.array) { hint in
+          ForEach($allHints) { hint in
             TableRow(hint)
             TableRow(hint)
           }
           }
           TableRow($active)
           TableRow($active)
@@ -47,9 +45,7 @@ struct SettingsView: View {
   
   
   private func addHint() {
   private func addHint() {
     if active.valid {
     if active.valid {
-      allHints.array.append(active)
-      UserDefaults.standard.set(allHints.serial,
-                                forKey: UserDefaultsKeys.UrlHints)
+      allHints.append(active)
       active = URLHint()
       active = URLHint()
     }
     }
   }
   }
@@ -57,5 +53,4 @@ struct SettingsView: View {
 
 
 #Preview {
 #Preview {
   SettingsView()
   SettingsView()
-    .environmentObject(URLHintArray())
 }
 }

+ 2 - 3
Todos/View/TagBarView.swift

@@ -10,7 +10,7 @@ import SwiftData
 
 
 struct TagBarView: View {
 struct TagBarView: View {
   @Binding var tags: [Tag]
   @Binding var tags: [Tag]
-  @EnvironmentObject var allHints: URLHintArray
+  @AppStorage(UserDefaultsKeys.UrlHints) var allHints = URLHintArray()
 
 
   @State private var active: String = ""
   @State private var active: String = ""
   @FocusState private var isFocused: Bool
   @FocusState private var isFocused: Bool
@@ -18,7 +18,7 @@ struct TagBarView: View {
   var body: some View {
   var body: some View {
     HStack {
     HStack {
       ForEach($tags) { tag in
       ForEach($tags) { tag in
-        let url = allHints.array.filter({ $0.matches(tag.wrappedValue) })
+        let url = allHints.filter({ $0.matches(tag.wrappedValue) })
           .first?.url(tag.wrappedValue)
           .first?.url(tag.wrappedValue)
         if url != nil {
         if url != nil {
           Link(destination: url!) {
           Link(destination: url!) {
@@ -52,5 +52,4 @@ struct TagBarView: View {
     URLHint(prefix: "RPD:", replacement: "http://localhost/")
     URLHint(prefix: "RPD:", replacement: "http://localhost/")
   ])
   ])
   TagBarView(tags: $tags)
   TagBarView(tags: $tags)
-    .environmentObject(allHints)
 }
 }

+ 0 - 1
Todos/View/TaskView.swift

@@ -80,6 +80,5 @@ struct TaskView: View {
 #Preview {
 #Preview {
   @Previewable @State var task = Task(name: "New Task")
   @Previewable @State var task = Task(name: "New Task")
   TaskView(task: $task)
   TaskView(task: $task)
-      .environmentObject(URLHintArray())
       .frame(minHeight: 100) // Preview does not resize window properly
       .frame(minHeight: 100) // Preview does not resize window properly
 }
 }

+ 16 - 16
Todos/ViewModel/URLHintArray.swift

@@ -9,24 +9,24 @@ import Foundation
 import SwiftData
 import SwiftData
 internal import Combine
 internal import Combine
 
 
-class URLHintArray : ObservableObject {
-  typealias Serial = [[String:String]]
+typealias URLHintArray = [URLHint]
 
 
-  @Published var array: [URLHint] = [URLHint]()
-  
-  init() {}
-  
-  init(_ array: [URLHint]) {
-    self.array = array
+extension URLHintArray : @retroactive RawRepresentable {
+  public init?(rawValue: String) {
+    guard let data = rawValue.data(using: .utf8),
+          let result = try? JSONDecoder().decode(URLHintArray.self, from: data)
+    else {
+      return nil
+    }
+    self = result
   }
   }
   
   
-  init(fromSerial: Serial?) {
-    self.array = fromSerial?.map({
-      URLHint(prefix: $0["prefix"]!, replacement: $0["replacement"]!)
-    }) ?? []
-  }
-
-  var serial: Serial {
-    return array.map({["prefix": $0.prefix, "replacement": $0.replacement]})
+  public var rawValue: String {
+    guard let data = try? JSONEncoder().encode(self),
+          let result = String(data: data, encoding: .utf8)
+    else {
+      return "[]"
+    }
+    return result
   }
   }
 }
 }