AutosaveMenu.swift 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. //
  2. // SaveAndRefreshMenu.swift
  3. // Todos
  4. //
  5. // Created by Sam Jaffe on 3/9/26.
  6. //
  7. import SwiftUI
  8. import SwiftData
  9. internal import Combine
  10. struct AutosaveMenu: View {
  11. @Environment(\.modelContext) private var modelContext
  12. @AppStorage(UserDefaultsKeys.WeekStart) private var weekStart = Date()
  13. let inPreview = ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
  14. @Query private var items: [Project]
  15. @Binding var hasAutosave: Bool
  16. var body: some View {
  17. Button("Save and Cleanup", systemImage: "arrow.3.trianglepath") {
  18. tryAutosave()
  19. }
  20. .keyboardShortcut("R", modifiers: [.command, .shift])
  21. // .disabled(!shouldAutosave)
  22. .onAppear(perform: tryAutosave)
  23. .help("Will save as \(ymd(weekStart)) after \(ymd(nextSunday(weekStart)))")
  24. }
  25. func tryAutosave() {
  26. if shouldAutosave && !inPreview {
  27. saveAndCleanup(weekStart)
  28. weekStart = Date()
  29. hasAutosave = true
  30. }
  31. }
  32. func nextSunday(_ date: Date) -> Date {
  33. Calendar.current.nextDate(after: date,
  34. matching: DateComponents(weekday: 1),
  35. matchingPolicy: .nextTime)!
  36. }
  37. func ymd(_ date: Date) -> String {
  38. date.formatted(.iso8601.year().month().day())
  39. }
  40. var shouldAutosave: Bool {
  41. ymd(Date()) > ymd(nextSunday(weekStart))
  42. }
  43. func saveAndCleanup(_ date: Date) {
  44. SaveController().save(items, onDate: ymd(date))
  45. for item in items {
  46. item.tasks.removeAll(where: { $0.status == .complete })
  47. for task in item.tasks {
  48. if task.status == .inProgress {
  49. task.status = .todo
  50. }
  51. task.subtasks.removeAll(where: { $0.status == .complete })
  52. for subtask in task.subtasks where subtask.status == .inProgress {
  53. subtask.status = .todo
  54. }
  55. }
  56. }
  57. }
  58. }
  59. #Preview {
  60. @Previewable @State var hasAutosave = true
  61. AutosaveMenu(hasAutosave: $hasAutosave)
  62. }