]>
Commit | Line | Data |
---|---|---|
1 | import CoreData | |
2 | import SwiftUI | |
3 | ||
4 | struct MapEditorWindow: View { | |
5 | @Environment(\.managedObjectContext) private var viewContext | |
6 | ||
7 | @EnvironmentObject var store: AppStore | |
8 | ||
9 | @FetchRequest( | |
10 | sortDescriptors: [NSSortDescriptor(keyPath: \Map.createdAt, ascending: true)], | |
11 | animation: .default) | |
12 | private var maps: FetchedResults<Map> | |
13 | ||
14 | var body: some View { | |
15 | NavigationView { | |
16 | List { | |
17 | if maps.count == 0 { | |
18 | EmptyMapDetailScreen() | |
19 | } | |
20 | ForEach(maps) { map in | |
21 | NavigationLink( | |
22 | destination: MapDetailScreen(map: map, title: map.title ?? "", content: map.content ?? "") | |
23 | ) { | |
24 | HStack { | |
25 | Text(map.title ?? "Untitled Map") | |
26 | Spacer() | |
27 | Text(mapFormatter.string(from: (map.createdAt ?? Date()))) | |
28 | .font(.caption) | |
29 | .padding(.vertical, 2.0) | |
30 | .padding(.horizontal, 4.0) | |
31 | .background(Color.accentColor) | |
32 | .foregroundColor(Color.black) | |
33 | .cornerRadius(2.0) | |
34 | }.padding(.leading, 8.0) | |
35 | }.contextMenu { | |
36 | Button( | |
37 | action: { store.send(.deleteMap(map: map)) }, | |
38 | label: { | |
39 | Image(systemName: "trash") | |
40 | Text("Delete") | |
41 | }) | |
42 | } | |
43 | } | |
44 | .onDelete(perform: deleteMaps) | |
45 | }.frame(minWidth: 250.0, alignment: .leading) | |
46 | .toolbar { | |
47 | HStack { | |
48 | Button(action: toggleSidebar) { | |
49 | Label("Toggle Sidebar", systemImage: "sidebar.left") | |
50 | } | |
51 | Button(action: addMap) { | |
52 | Label("Add Map", systemImage: "plus") | |
53 | } | |
54 | } | |
55 | } | |
56 | EmptyMapDetailScreen() | |
57 | } | |
58 | } | |
59 | ||
60 | private func toggleSidebar() { | |
61 | NSApp.keyWindow?.firstResponder?.tryToPerform( | |
62 | #selector(NSSplitViewController.toggleSidebar(_:)), with: nil) | |
63 | } | |
64 | ||
65 | private func addMap() { | |
66 | withAnimation { | |
67 | let newMap = Map(context: viewContext) | |
68 | newMap.uuid = UUID() | |
69 | newMap.createdAt = Date() | |
70 | newMap.title = "Map \(newMap.createdAt!.format())" | |
71 | newMap.content = "" | |
72 | ||
73 | do { | |
74 | try viewContext.save() | |
75 | } catch { | |
76 | let nsError = error as NSError | |
77 | fatalError("Unresolved error \(nsError), \(nsError.userInfo)") | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | private func deleteMaps(offsets: IndexSet) { | |
83 | ||
84 | withAnimation { | |
85 | offsets.map { maps[$0] }.forEach(viewContext.delete) | |
86 | ||
87 | do { | |
88 | try viewContext.save() | |
89 | } catch { | |
90 | let nsError = error as NSError | |
91 | fatalError("Unresolved error \(nsError), \(nsError.userInfo)") | |
92 | } | |
93 | } | |
94 | } | |
95 | } | |
96 | ||
97 | private let mapFormatter: DateFormatter = { | |
98 | let formatter = DateFormatter() | |
99 | formatter.dateStyle = .short | |
100 | formatter.timeStyle = .none | |
101 | return formatter | |
102 | }() | |
103 | ||
104 | struct ContentView_Previews: PreviewProvider { | |
105 | static var previews: some View { | |
106 | MapEditorWindow().environment( | |
107 | \.managedObjectContext, PersistenceController.preview.container.viewContext) | |
108 | } | |
109 | } |