Forráskód Böngészése

feat: implement deleting task/subtask via a toggle menu control instead of context menu... since it mis-aligns

Sam Jaffe 2 hete
szülő
commit
d0f4ba0021

+ 7 - 0
Todos/TodosApp.swift

@@ -17,6 +17,8 @@ struct UserDefaultsKeys {
 
 @main
 struct TodosApp: App {
+  @State private var isMoveMode = false
+
   var sharedModelContainer: ModelContainer = {
     let schema = Schema([
       Project.self,
@@ -56,6 +58,11 @@ struct TodosApp: App {
         ImportMenu()
           .modelContainer(sharedModelContainer)
       }
+      CommandGroup(replacing: .toolbar) {
+        Toggle(isOn: $isMoveMode) {
+          Label("Move/Delete Tasks", systemImage: "pencil")
+        }
+      }
     }
     
     #if os(macOS)

+ 4 - 2
Todos/View/ContentView.swift

@@ -13,6 +13,7 @@ struct ContentView: View {
   @AppStorage(UserDefaultsKeys.WeekStart) private var weekStart = Date()
   let inPreview = ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
   
+  @Binding var isMoveMode: Bool
   @Query private var items: [Project]
   @State private var selection: Project?
 
@@ -40,7 +41,7 @@ struct ContentView: View {
       }
     } detail: {
       if let selection = selection {
-        ProjectPanelView(item: selection)
+        ProjectPanelView(item: selection, isMoveMode: $isMoveMode)
       } else {
         let header = items.isEmpty ? "Create a New Project" : "Select a project from the sidebar"
         ContentUnavailableView(header, systemImage: "doc.text.image.fill")
@@ -118,6 +119,7 @@ struct ContentView: View {
 }
 
 #Preview {
-  ContentView()
+  @Previewable @State var isMoveMode = false
+  ContentView(isMoveMode: $isMoveMode)
       .modelContainer(for: Project.self, inMemory: true)
 }

+ 7 - 18
Todos/View/ProjectPanelView.swift

@@ -15,6 +15,8 @@ struct ProjectPanelView: View {
   @Bindable var item: Project
   @State private var empty = Category()
 
+  @Binding var isMoveMode: Bool
+
   var body: some View {
     let style = Date.FormatStyle(date: .numeric, time: .standard)
     HStack {
@@ -40,20 +42,13 @@ struct ProjectPanelView: View {
       }.help("Default category for new Tasks")
       Text("Created on \(item.timestamp, format: style)")
     }
-    List {
+    VStack {
       ForEach($item.tasks) { task in
-        TaskView(task: task)
-        .contextMenu {
-          Button(action: {
-            deleteItem(item: task.wrappedValue, fromProject: item)
-          }) {
-            Label("Delete", systemImage: "trash")
-          }
-        }
+        TaskView(task: task, isMoveMode: $isMoveMode)
       }
     }
   }
-  
+
   private func addItem() {
     withAnimation {
       let newTask = Task(name: "New Task", parent: item)
@@ -61,16 +56,10 @@ struct ProjectPanelView: View {
       item.tasks.append(newTask)
     }
   }
-
-  private func deleteItem(item: Task, fromProject: Project) {
-    withAnimation {
-      fromProject.tasks.removeAll(where: { $0.id == item.id })
-      modelContext.delete(item)
-    }
-  }
 }
 
 #Preview {
+  @Previewable @State var isMoveMode = false
   @Previewable @State var item = Project(timestamp: Date())
-  ProjectPanelView(item: item)
+  ProjectPanelView(item: item, isMoveMode: $isMoveMode)
 }

+ 34 - 13
Todos/View/TaskView.swift

@@ -17,6 +17,7 @@ struct TaskView: View {
   @State private var hideNotes: Bool = false
   @State private var empty = Category()
 
+  @Binding var isMoveMode: Bool
   @FocusState private var isFocused: Bool
 
   var body: some View {
@@ -44,9 +45,17 @@ struct TaskView: View {
         
         TextField("Task Name", text: $task.name)
           .focused($isFocused)
-        Button(action: addItem) {
-          Image(systemName: "plus")
-            .help("Add a Subtask")
+        if isMoveMode {
+          Button {
+            deleteItem(item: task)
+          } label: {
+            Image(systemName: "trash")
+          }.help("Delete Task '\(task.name)'")
+        } else {
+          Button(action: addItem) {
+            Image(systemName: "plus")
+              .help("Add a Subtask")
+          }
         }
       }
       
@@ -78,17 +87,19 @@ struct TaskView: View {
       }
       
       VStack {
-        ForEach($task.subtasks) { subtask in
-          SubTaskView(task: subtask)
-            .padding(.leading, 5)
-            .contextMenu {
-              Button(action: {
+        ForEach($task.subtasks, id: \.self) { subtask in
+          HStack {
+            SubTaskView(task: subtask)
+              .padding(.leading, 5)
+            if isMoveMode {
+              Button {
                 deleteItem(item: subtask.wrappedValue, fromTask: task)
-              }) {
-                Label("Delete", systemImage: "trash")
-              }
+              } label: {
+                Image(systemName: "trash")
+              }.help("Delete Subtask '\(subtask.name.wrappedValue)'")
             }
-         }
+          }
+        }
       }
     }
   }
@@ -101,6 +112,15 @@ struct TaskView: View {
     }
   }
 
+  private func deleteItem(item: Task) {
+    withAnimation {
+      if let fromProject = item.project {
+        fromProject.tasks.removeAll(where: { $0.id == item.id })
+        modelContext.delete(item)
+      }
+    }
+  }
+
   private func deleteItem(item: SubTask, fromTask: Task) {
     withAnimation {
       fromTask.subtasks.removeAll(where: { $0.id == item.id })
@@ -110,7 +130,8 @@ struct TaskView: View {
 }
 
 #Preview {
+  @Previewable @State var isMoveMode = false
   @Previewable @State var task = Task(name: "New Task")
-  TaskView(task: $task)
+  TaskView(task: $task, isMoveMode: $isMoveMode)
       .frame(minHeight: 100) // Preview does not resize window properly
 }