Преглед изворни кода

fix: proper 1-Many relationship in SwiftUI requires inverse to be provided...

Sam Jaffe пре 2 недеља
родитељ
комит
8a499cb3bb

+ 1 - 1
Todos/Model/Project.swift

@@ -13,7 +13,7 @@ final class Project : Codable {
   var timestamp: Date
   var category: String = ""
   var name: String = "New Project"
-  @Relationship(deleteRule: .cascade)
+  @Relationship(deleteRule: .cascade, inverse:\Task.project)
   var tasks: [Task] = []
   
   init(timestamp: Date) {

+ 11 - 5
Todos/Model/Task.swift

@@ -34,11 +34,13 @@ enum Status : String, CaseIterable, Identifiable, Codable {
 @Model
 final class SubTask : Codable {
   var name: String
+  var task: Task?
   var notes: String = ""
   var status: Status = Status.Todo
   
-  init(name: String) {
+  init(name: String, parent: Task? = nil) {
     self.name = name
+    self.task = parent
   }
   
   func yaml(_ indent: Int = 0) -> String {
@@ -71,9 +73,11 @@ final class SubTask : Codable {
 @Model
 final class Tag : Codable {
   var id: String
+  var task: Task?
 
-  init(id: String) {
+  init(id: String, parent: Task? = nil) {
     self.id = id
+    self.task = parent
   }
 
   func like(_ str: String) -> Bool {
@@ -93,15 +97,17 @@ final class Tag : Codable {
 @Model
 final class Task : Codable {
   var name: String
-  @Relationship(deleteRule: .cascade)
+  var project: Project?
+  @Relationship(deleteRule: .cascade, inverse: \Tag.task)
   var tags: [Tag] = []
-  @Relationship(deleteRule: .cascade)
+  @Relationship(deleteRule: .cascade, inverse: \SubTask.task)
   var subtasks: [SubTask] = []
   var notes: String = ""
   var status: Status = Status.Todo
   
-  init(name: String) {
+  init(name: String, parent: Project? = nil) {
     self.name = name
+    self.project = parent
   }
   
   func yaml(_ indent: Int = 0) -> String {

+ 2 - 1
Todos/View/ProjectPanelView.swift

@@ -11,6 +11,7 @@ import SwiftData
 struct ProjectPanelView: View {
   @Environment(\.modelContext) private var modelContext
   @AppStorage(UserDefaultsKeys.Category) var allGroups = CodableArray<Category>()
+
   @Bindable var item: Project
   @State private var empty = Category()
 
@@ -56,7 +57,7 @@ struct ProjectPanelView: View {
   
   private func addItem() {
     withAnimation {
-      let newTask = Task(name: "New Task")
+      let newTask = Task(name: "New Task", parent: item)
       modelContext.insert(newTask)
       item.tasks.append(newTask)
     }

+ 15 - 13
Todos/View/TagBarView.swift

@@ -10,7 +10,7 @@ import SwiftData
 
 struct TagBarView: View {
   @Environment(\.modelContext) private var modelContext
-  @Binding var tags: [Tag]
+  @Binding var task: Task
   @AppStorage(UserDefaultsKeys.UrlHints) var allHints = CodableArray<URLHint>()
 
   @State private var active: String = ""
@@ -18,7 +18,7 @@ struct TagBarView: View {
   
   var body: some View {
     HStack {
-      ForEach($tags) { tag in
+      ForEach($task.tags) { tag in
         let url = allHints.filter({ $0.matches(tag.wrappedValue) })
           .first?.url(tag.wrappedValue)
         if url != nil {
@@ -32,27 +32,29 @@ struct TagBarView: View {
         TextField("", text: tag.id)
           .focused($isFocused)
           .onChange(of: isFocused) {
-            tags.removeAll(where: { $0.id.isEmpty })
+            task.tags.removeAll(where: { $0.id.isEmpty })
           }
       }
       .scaledToFit()
       TextField("Tag", text: $active)
-        .onSubmit {
-          if !active.isEmpty && !tags.contains(where: { $0.like(active) }) {
-            let newTag = Tag(id: active)
-            modelContext.insert(newTag)
-            tags.append(newTag)
-          }
-          active = ""
-        }
+        .onSubmit(addItem)
+    }
+  }
+  
+  private func addItem() {
+    if !active.isEmpty && !task.tags.contains(where: { $0.like(active) }) {
+      let newTag = Tag(id: active, parent: task)
+      modelContext.insert(newTag)
+      task.tags.append(newTag)
     }
+    active = ""
   }
 }
 
 #Preview {
-  @Previewable @State var tags = Array<Tag>()
+  @Previewable @State var task = Task(name: "")
   @Previewable @State var allHints = CodableArray([
     URLHint(prefix: "RPD:", replacement: "http://localhost/")
   ])
-  TagBarView(tags: $tags)
+  TagBarView(task: $task)
 }

+ 2 - 2
Todos/View/TaskView.swift

@@ -47,7 +47,7 @@ struct TaskView: View {
       
       if isFocused || !(hideTags || task.tags.isEmpty) {
         HStack {
-          TagBarView(tags: $task.tags)
+          TagBarView(task: $task)
             .font(.footnote)
             .focused($isFocused)
             .padding(.leading, 30)
@@ -85,7 +85,7 @@ struct TaskView: View {
 
   private func addItem() {
     withAnimation {
-      let newSubtask = SubTask(name: "Subtask")
+      let newSubtask = SubTask(name: "Subtask", parent: task)
       modelContext.insert(newSubtask)
       task.subtasks.append(newSubtask)
     }