]> git.r.bdr.sh - rbdr/map/blob - Map/State/AppState.swift
Fix performance and undo
[rbdr/map] / Map / State / AppState.swift
1 import Cocoa
2 import Foundation
3 import SwiftUI
4
5 struct AppState {
6 var selectedEvolution: StageType = .general
7 }
8
9 enum AppAction {
10 case selectEvolution(evolution: StageType)
11 case exportMapAsImage(map: Map)
12 case exportMapAsText(map: Map)
13 case deleteMap(map: Map)
14 }
15
16 func appStateReducer(state: inout AppState, action: AppAction) {
17
18 switch action {
19
20 case .selectEvolution(let evolution):
21 state.selectedEvolution = evolution
22
23 case .exportMapAsImage(let map):
24 let window = NSWindow(
25 contentRect: .init(
26 origin: .zero,
27 size: .init(
28 width: NSScreen.main!.frame.width,
29 height: NSScreen.main!.frame.height)),
30 styleMask: [.closable],
31 backing: .buffered,
32 defer: false)
33
34 window.title = map.title ?? "Untitled Map"
35 window.isOpaque = true
36 window.center()
37 window.isMovableByWindowBackground = true
38 window.makeKeyAndOrderFront(nil)
39
40 let renderView = MapRenderView(
41 content: Binding.constant(map.content ?? ""),
42 evolution: Binding.constant(Stage.stages(state.selectedEvolution)))
43
44 let view = NSHostingView(rootView: renderView)
45 window.contentView = view
46
47 let imageRepresentation = view.bitmapImageRepForCachingDisplay(in: view.bounds)!
48 view.cacheDisplay(in: view.bounds, to: imageRepresentation)
49 let image = NSImage(cgImage: imageRepresentation.cgImage!, size: view.bounds.size)
50
51 let dialog = NSSavePanel()
52
53 dialog.title = "Save Map"
54 dialog.showsResizeIndicator = false
55 dialog.canCreateDirectories = true
56 dialog.showsHiddenFiles = false
57 dialog.allowedFileTypes = ["png"]
58 dialog.nameFieldStringValue = map.title ?? "Untitled Map"
59
60 if dialog.runModal() == NSApplication.ModalResponse.OK {
61 let result = dialog.url
62
63 if result != nil {
64
65 image.writePNG(toURL: result!)
66 print("saved at \(result!)")
67 }
68 } else {
69 print("Cancel")
70 }
71 window.orderOut(nil)
72
73 case .exportMapAsText(let map):
74 let dialog = NSSavePanel()
75
76 dialog.title = "Save Map Text"
77 dialog.showsResizeIndicator = false
78 dialog.canCreateDirectories = true
79 dialog.showsHiddenFiles = false
80 dialog.allowedFileTypes = ["txt"]
81 dialog.nameFieldStringValue = map.title ?? "Untitled Map"
82
83 if let content = map.content {
84
85 if dialog.runModal() == NSApplication.ModalResponse.OK {
86 let result = dialog.url
87
88 if let result = result {
89 try? content.write(to: result, atomically: true, encoding: String.Encoding.utf8)
90 }
91 } else {
92 print("Cancel")
93 }
94 }
95 case .deleteMap(let map):
96 let context = PersistenceController.shared.container.viewContext
97 context.delete(map)
98
99 try? context.save()
100 }
101 }
102
103 typealias AppStore = Store<AppState, AppAction>