txtodo

[DORMANT] a minimalist todo list app inspired by jeff huang
git clone git://git.figbert.com/txtodo.git
Log | Files | Refs | README

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 }