ContentView.swift 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //
  2. // ContentView.swift
  3. // Todos
  4. //
  5. // Created by Sam Jaffe on 2/28/26.
  6. //
  7. import SwiftUI
  8. import SwiftData
  9. struct ContentView: View {
  10. @Environment(\.modelContext) private var modelContext
  11. @Query(sort: \Project.sortOrder) private var items: [Project]
  12. @State private var selection: Project?
  13. @Binding var hasAutosave: Bool
  14. var body: some View {
  15. NavigationSplitView {
  16. List(selection: $selection) {
  17. ForEach(items, id: \.id) { item in
  18. NavigationLink(value: item) {
  19. Text(item.name)
  20. }.swipeActions(content: {
  21. Button("Delete", systemImage: "trash", role: .destructive) {
  22. deleteItem(item: item)
  23. }
  24. })
  25. }
  26. .onMove(perform: reOrder)
  27. }
  28. .navigationSplitViewColumnWidth(min: 180, ideal: 200)
  29. .toolbar {
  30. ToolbarItem {
  31. Button(action: addItem) {
  32. Label("New Project", systemImage: "plus")
  33. }
  34. }
  35. }
  36. } detail: {
  37. if let selection = selection {
  38. ProjectPanelView(item: selection)
  39. } else {
  40. let header = items.isEmpty ? "Create a New Project" : "Select a project from the sidebar"
  41. ContentUnavailableView(header, systemImage: "doc.text.image.fill")
  42. }
  43. }
  44. .alert("Autosave", isPresented: $hasAutosave) {
  45. Button("OK") {
  46. hasAutosave = false
  47. }
  48. } message: {
  49. Text("All completed tasks/subtasks have been deleted")
  50. }
  51. }
  52. private func addItem() {
  53. withAnimation {
  54. let newItem = Project(sortOrder: items.count)
  55. modelContext.insert(newItem)
  56. }
  57. }
  58. @MainActor
  59. private func reOrder(fromOffsets: IndexSet, toOffset: Int) {
  60. var tmp = items.sorted(by: Project.less)
  61. tmp.move(fromOffsets: fromOffsets, toOffset: toOffset)
  62. for (index, item) in tmp.enumerated() {
  63. item.sortOrder = index
  64. }
  65. try? self.modelContext.save()
  66. }
  67. private func deleteItem(item: Project) {
  68. if let selection = selection, selection == item {
  69. self.selection = nil
  70. }
  71. withAnimation {
  72. modelContext.delete(item)
  73. }
  74. }
  75. }
  76. #Preview {
  77. @Previewable @State var hasAutosave = false
  78. ContentView(hasAutosave: $hasAutosave)
  79. .modelContainer(for: Project.self, inMemory: true)
  80. }