TaskView.swift (6276B)
1 // 2 // TaskView.swift 3 // txtodo 4 // 5 // Created by FIGBERT on 7/27/20. 6 // 7 8 import SwiftUI 9 10 struct TaskView: View { 11 @Environment(\.managedObjectContext) var managedObjectContext 12 @Environment(\.layoutDirection) var direction 13 @ObservedObject var task: Task 14 @State var priority: Int 15 @State private var config = TaskViewConfig() 16 17 var body: some View { 18 let priorityIntermediary = Binding<Int>( 19 get: { self.priority }, 20 set: { value in 21 self.priority = value 22 self.managedObjectContext.performAndWait { 23 self.task.priority = Int16(value) 24 try? self.managedObjectContext.save() 25 } 26 self.config.editingPriority = false 27 } 28 ) 29 return VStack { 30 HStack { 31 if task.daily && !task.hasBeenDelayed && !task.completed && config.showingDelay { 32 Image(systemName: "calendar.circle.fill") 33 .font(.system(size: 25)) 34 .foregroundColor(.blue) 35 .onTapGesture { 36 self.managedObjectContext.performAndWait { 37 self.task.date = Calendar.current.date(byAdding: .day, value: 1, to: task.date) ?? Date() 38 self.task.hasBeenDelayed = true 39 try? self.managedObjectContext.save() 40 } 41 config.showingDelay = false 42 } 43 } 44 Image(systemName: task.completed ? "checkmark.square" : "square") 45 .onTapGesture { 46 self.managedObjectContext.performAndWait { 47 self.task.completed.toggle() 48 if !self.task.daily { 49 self.task.date = Date.init() 50 } 51 try? self.managedObjectContext.save() 52 } 53 self.config.showingNotes = false 54 } 55 Spacer() 56 if !config.editingText { 57 Text(task.name) 58 .strikethrough(task.completed) 59 .onTapGesture(count: 2) { 60 if !self.task.completed { 61 self.config.editingText = true 62 } 63 } 64 .onTapGesture { 65 self.config.showingNotes.toggle() 66 } 67 } else { 68 TextField("edit task", text: $task.name, onCommit: { 69 self.config.editingText = false 70 self.managedObjectContext.performAndWait { 71 try? self.managedObjectContext.save() 72 } 73 }) 74 } 75 Spacer() 76 if !config.editingPriority { 77 HStack(alignment: .center, spacing: 2) { 78 ForEach(1 ..< Int(task.priority + 1), id: \.self) {_ in 79 Text("!") 80 } 81 } 82 .font(.system(size: 10, weight: .light)) 83 .onTapGesture(count: 2) { 84 if !self.task.completed { 85 self.config.editingPriority = true 86 } 87 } 88 } else { 89 Picker( 90 selection: priorityIntermediary, 91 label: Text("task priority"), 92 content: { 93 Text("!").tag(1) 94 Text("!!").tag(2) 95 Text("!!!").tag(3) 96 }) 97 .pickerStyle(SegmentedPickerStyle()) 98 .labelsHidden() 99 } 100 if config.showingDelete { 101 Image(systemName: "trash.circle.fill") 102 .font(.system(size: 25)) 103 .foregroundColor(.red) 104 .onTapGesture { 105 self.managedObjectContext.performAndWait { 106 self.managedObjectContext.delete(self.task) 107 try? self.managedObjectContext.save() 108 } 109 } 110 } 111 } 112 .padding(.bottom, 5) 113 .foregroundColor(task.completed ? .secondary : .primary) 114 .multilineTextAlignment(.center) 115 .offset(x: config.offset) 116 .gesture( 117 DragGesture() 118 .onChanged({ value in 119 config.offset = direction == .leftToRight ? value.translation.width : -value.translation.width 120 }) 121 .onEnded({ value in 122 if task.daily && config.offset > 15 { 123 config.showingDelay.toggle() 124 } else if -config.offset > 15 { 125 config.showingDelete.toggle() 126 } 127 config.offset = 0 128 }) 129 ) 130 if config.showingNotes { 131 VStack(spacing: 10) { 132 ForEach(task.notes, id: \.self) { note in 133 NoteView(task: task, note: note, config: NoteViewConfig(editingCache: note)) 134 .environment(\.managedObjectContext, self.managedObjectContext) 135 } 136 AddNoteView(task: task) 137 } 138 .padding(.leading) 139 .padding(.bottom, 5) 140 } 141 } 142 .padding(.horizontal, 14) 143 .cornerRadius(15) 144 .font(.system(size: 18, weight: .light)) 145 } 146 } 147 148 struct TaskViewConfig { 149 var editingText: Bool = false 150 var editingPriority: Bool = false 151 var showingNotes: Bool = false 152 var showingDelete: Bool = false 153 var showingDelay: Bool = false 154 var offset: CGFloat = 0 155 }