@lattices/cli 0.4.2 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/app/Info.plist +2 -2
- package/app/Lattices.app/Contents/Info.plist +2 -2
- package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/app/Package.swift +6 -0
- package/app/Sources/AppShell/App.swift +20 -0
- package/app/Sources/{AppDelegate.swift → AppShell/AppDelegate.swift} +94 -34
- package/app/Sources/{AppShellView.swift → AppShell/AppShellView.swift} +12 -1
- package/app/Sources/AppShell/AppUpdater.swift +92 -0
- package/app/Sources/AppShell/CliActionLauncher.swift +50 -0
- package/app/Sources/{HomeDashboardView.swift → AppShell/HomeDashboardView.swift} +18 -10
- package/app/Sources/AppShell/LatticesRuntime.swift +61 -0
- package/app/Sources/{MainView.swift → AppShell/MainView.swift} +351 -191
- package/app/Sources/{OnboardingView.swift → AppShell/OnboardingView.swift} +30 -16
- package/app/Sources/{Preferences.swift → AppShell/Preferences.swift} +78 -0
- package/app/Sources/{SettingsView.swift → AppShell/SettingsView.swift} +869 -152
- package/app/Sources/{HotkeyStore.swift → Core/Actions/HotkeyStore.swift} +9 -5
- package/app/Sources/{IntentEngine.swift → Core/Actions/IntentEngine.swift} +51 -27
- package/app/Sources/Core/Actions/IntentSchema.swift +94 -0
- package/app/Sources/{Intents → Core/Actions/Intents}/LatticeIntent.swift +0 -25
- package/app/Sources/{PaletteCommand.swift → Core/Actions/PaletteCommand.swift} +26 -6
- package/app/Sources/{VoiceIntentResolver.swift → Core/Actions/VoiceIntentResolver.swift} +46 -4
- package/app/Sources/Core/Companion/CompanionActivityLog.swift +70 -0
- package/app/Sources/Core/Companion/CompanionKeyboardController.swift +141 -0
- package/app/Sources/Core/Companion/LatticesCompanionBridgeServer.swift +438 -0
- package/app/Sources/Core/Companion/LatticesCompanionCockpit.swift +555 -0
- package/app/Sources/Core/Companion/LatticesCompanionSecurityCoordinator.swift +594 -0
- package/app/Sources/Core/Companion/LatticesCompanionTrackpadController.swift +204 -0
- package/app/Sources/Core/Companion/LatticesDeckHost.swift +1463 -0
- package/app/Sources/{LatticesApi.swift → Core/Daemon/LatticesApi.swift} +125 -4
- package/app/Sources/{AppTypeClassifier.swift → Core/Desktop/AppTypeClassifier.swift} +36 -0
- package/app/Sources/{DesktopModel.swift → Core/Desktop/DesktopModel.swift} +6 -8
- package/app/Sources/Core/Desktop/MouseFinder.swift +527 -0
- package/app/Sources/Core/Desktop/SessionWindowLocator.swift +139 -0
- package/app/Sources/Core/Desktop/WindowDragSnapController.swift +628 -0
- package/app/Sources/Core/Desktop/WindowPreviewCard.swift +100 -0
- package/app/Sources/Core/Desktop/WindowPreviewStore.swift +113 -0
- package/app/Sources/Core/Desktop/WindowSelectionStore.swift +76 -0
- package/app/Sources/{WindowTiler.swift → Core/Desktop/WindowTiler.swift} +351 -172
- package/app/Sources/Core/Input/MouseGestureConfig.swift +364 -0
- package/app/Sources/Core/Input/MouseGestureController.swift +1203 -0
- package/app/Sources/Core/Input/MouseInputDeviceStore.swift +98 -0
- package/app/Sources/Core/Input/MouseInputEventViewer.swift +272 -0
- package/app/Sources/Core/Input/MouseShortcutStore.swift +107 -0
- package/app/Sources/{CommandModeState.swift → Core/Overlays/CommandMode/CommandModeState.swift} +127 -24
- package/app/Sources/{CommandModeView.swift → Core/Overlays/CommandMode/CommandModeView.swift} +492 -79
- package/app/Sources/Core/Overlays/CommandPalette/CommandPaletteWindow.swift +67 -0
- package/app/Sources/{CheatSheetHUD.swift → Core/Overlays/HUD/CheatSheetHUD.swift} +1 -0
- package/app/Sources/{HUDRightBar.swift → Core/Overlays/HUD/HUDRightBar.swift} +23 -201
- package/app/Sources/{LauncherHUD.swift → Core/Overlays/HUD/LauncherHUD.swift} +12 -26
- package/app/Sources/{OmniSearchView.swift → Core/Overlays/OmniSearch/OmniSearchView.swift} +136 -2
- package/app/Sources/{OmniSearchWindow.swift → Core/Overlays/OmniSearch/OmniSearchWindow.swift} +21 -32
- package/app/Sources/Core/Overlays/OverlayPanelShell.swift +241 -0
- package/app/Sources/{ScreenMapState.swift → Core/Overlays/ScreenMap/ScreenMapState.swift} +116 -32
- package/app/Sources/{ScreenMapView.swift → Core/Overlays/ScreenMap/ScreenMapView.swift} +510 -524
- package/app/Sources/{ScreenMapWindowController.swift → Core/Overlays/ScreenMap/ScreenMapWindowController.swift} +12 -4
- package/app/Sources/{VoiceCommandWindow.swift → Core/Overlays/Voice/VoiceCommandWindow.swift} +46 -53
- package/app/Sources/Core/Pi/PiAuthNextStepCard.swift +148 -0
- package/app/Sources/Core/Pi/PiAuthPromptCard.swift +90 -0
- package/app/Sources/{PiChatDock.swift → Core/Pi/PiChatDock.swift} +137 -74
- package/app/Sources/{PiChatSession.swift → Core/Pi/PiChatSession.swift} +608 -108
- package/app/Sources/Core/Pi/PiInstallCallout.swift +86 -0
- package/app/Sources/Core/Pi/PiProviderSetupCallout.swift +99 -0
- package/app/Sources/{PiWorkspaceView.swift → Core/Pi/PiWorkspaceView.swift} +174 -77
- package/app/Sources/{PermissionChecker.swift → Core/System/PermissionChecker.swift} +76 -2
- package/app/Sources/Core/System/SystemTelemetryMonitor.swift +273 -0
- package/app/Sources/{HandsOffSession.swift → Core/Voice/HandsOffSession.swift} +15 -4
- package/app/Sources/{WorkspaceManager.swift → Core/Workspace/WorkspaceManager.swift} +288 -0
- package/bin/assistant-intelligence.ts +874 -0
- package/bin/handsoff-infer.ts +16 -209
- package/bin/handsoff-worker.ts +45 -258
- package/bin/lattices-app.ts +62 -0
- package/bin/lattices-dev +4 -0
- package/bin/lattices.ts +125 -14
- package/docs/agents.md +14 -0
- package/docs/api.md +55 -0
- package/docs/app.md +3 -0
- package/docs/companion-deck.md +180 -0
- package/docs/component-extraction-roadmap.md +392 -0
- package/docs/config.md +25 -0
- package/docs/tiling-reference.md +55 -0
- package/docs/voice-error-model.md +73 -0
- package/package.json +4 -1
- package/app/Sources/App.swift +0 -10
- package/app/Sources/CommandPaletteWindow.swift +0 -134
- package/app/Sources/MouseFinder.swift +0 -222
- /package/app/Sources/{KeyRecorderView.swift → AppShell/KeyRecorderView.swift} +0 -0
- /package/app/Sources/{MainWindow.swift → AppShell/MainWindow.swift} +0 -0
- /package/app/Sources/{SettingsWindow.swift → AppShell/SettingsWindow.swift} +0 -0
- /package/app/Sources/{HotkeyManager.swift → Core/Actions/HotkeyManager.swift} +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/CreateLayerIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/DistributeIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/FocusIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/HelpIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/KillIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/LaunchIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/ListSessionsIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/ListWindowsIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/ScanIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/SearchIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/SwitchLayerIntent.swift +0 -0
- /package/app/Sources/{Intents → Core/Actions/Intents}/TileIntent.swift +0 -0
- /package/app/Sources/{DaemonProtocol.swift → Core/Daemon/DaemonProtocol.swift} +0 -0
- /package/app/Sources/{DaemonServer.swift → Core/Daemon/DaemonServer.swift} +0 -0
- /package/app/Sources/{AccessibilityTextExtractor.swift → Core/Desktop/AccessibilityTextExtractor.swift} +0 -0
- /package/app/Sources/{DesktopModelTypes.swift → Core/Desktop/DesktopModelTypes.swift} +0 -0
- /package/app/Sources/{InventoryManager.swift → Core/Desktop/InventoryManager.swift} +0 -0
- /package/app/Sources/{InventoryPath.swift → Core/Desktop/InventoryPath.swift} +0 -0
- /package/app/Sources/{OcrModel.swift → Core/Desktop/OcrModel.swift} +0 -0
- /package/app/Sources/{OcrStore.swift → Core/Desktop/OcrStore.swift} +0 -0
- /package/app/Sources/{PlacementSpec.swift → Core/Desktop/PlacementSpec.swift} +0 -0
- /package/app/Sources/{TilePickerView.swift → Core/Desktop/TilePickerView.swift} +0 -0
- /package/app/Sources/{AppWindowShell.swift → Core/Overlays/AppWindowShell.swift} +0 -0
- /package/app/Sources/{CommandModeWindow.swift → Core/Overlays/CommandMode/CommandModeWindow.swift} +0 -0
- /package/app/Sources/{CommandPaletteView.swift → Core/Overlays/CommandPalette/CommandPaletteView.swift} +0 -0
- /package/app/Sources/{HUDBottomBar.swift → Core/Overlays/HUD/HUDBottomBar.swift} +0 -0
- /package/app/Sources/{HUDController.swift → Core/Overlays/HUD/HUDController.swift} +0 -0
- /package/app/Sources/{HUDLeftBar.swift → Core/Overlays/HUD/HUDLeftBar.swift} +0 -0
- /package/app/Sources/{HUDMinimap.swift → Core/Overlays/HUD/HUDMinimap.swift} +0 -0
- /package/app/Sources/{HUDState.swift → Core/Overlays/HUD/HUDState.swift} +0 -0
- /package/app/Sources/{HUDTopBar.swift → Core/Overlays/HUD/HUDTopBar.swift} +0 -0
- /package/app/Sources/{LayerBezel.swift → Core/Overlays/HUD/LayerBezel.swift} +0 -0
- /package/app/Sources/{OmniSearchState.swift → Core/Overlays/OmniSearch/OmniSearchState.swift} +0 -0
- /package/app/Sources/{DiagnosticLog.swift → Core/System/DiagnosticLog.swift} +0 -0
- /package/app/Sources/{EventBus.swift → Core/System/EventBus.swift} +0 -0
- /package/app/Sources/{ProcessModel.swift → Core/System/ProcessModel.swift} +0 -0
- /package/app/Sources/{ProcessQuery.swift → Core/System/ProcessQuery.swift} +0 -0
- /package/app/Sources/{AdvisorLearningStore.swift → Core/Voice/AdvisorLearningStore.swift} +0 -0
- /package/app/Sources/{AgentSession.swift → Core/Voice/AgentSession.swift} +0 -0
- /package/app/Sources/{AudioProvider.swift → Core/Voice/AudioProvider.swift} +0 -0
- /package/app/Sources/{VoiceChatView.swift → Core/Voice/VoiceChatView.swift} +0 -0
- /package/app/Sources/{VoxClient.swift → Core/Voice/VoxClient.swift} +0 -0
- /package/app/Sources/{Project.swift → Core/Workspace/Project.swift} +0 -0
- /package/app/Sources/{ProjectScanner.swift → Core/Workspace/ProjectScanner.swift} +0 -0
- /package/app/Sources/{SessionLayerStore.swift → Core/Workspace/SessionLayerStore.swift} +0 -0
- /package/app/Sources/{SessionManager.swift → Core/Workspace/SessionManager.swift} +0 -0
- /package/app/Sources/{Terminal.swift → Core/Workspace/Terminal/Terminal.swift} +0 -0
- /package/app/Sources/{TerminalQuery.swift → Core/Workspace/Terminal/TerminalQuery.swift} +0 -0
- /package/app/Sources/{TerminalSynthesizer.swift → Core/Workspace/Terminal/TerminalSynthesizer.swift} +0 -0
- /package/app/Sources/{TmuxModel.swift → Core/Workspace/Tmux/TmuxModel.swift} +0 -0
- /package/app/Sources/{TmuxQuery.swift → Core/Workspace/Tmux/TmuxQuery.swift} +0 -0
- /package/app/Sources/{ActionRow.swift → UI/ActionRow.swift} +0 -0
- /package/app/Sources/{OrphanRow.swift → UI/OrphanRow.swift} +0 -0
- /package/app/Sources/{ProjectRow.swift → UI/ProjectRow.swift} +0 -0
- /package/app/Sources/{TabGroupRow.swift → UI/TabGroupRow.swift} +0 -0
- /package/app/Sources/{Theme.swift → UI/Theme.swift} +0 -0
|
@@ -77,7 +77,7 @@ struct OnboardingView: View {
|
|
|
77
77
|
.padding(.horizontal, 40)
|
|
78
78
|
.padding(.bottom, 28)
|
|
79
79
|
}
|
|
80
|
-
.frame(width: 480, height:
|
|
80
|
+
.frame(width: 480, height: 470)
|
|
81
81
|
.background(Palette.bg)
|
|
82
82
|
.preferredColorScheme(.dark)
|
|
83
83
|
}
|
|
@@ -111,8 +111,8 @@ struct OnboardingView: View {
|
|
|
111
111
|
private var screenRecordingStep: some View {
|
|
112
112
|
permissionStep(
|
|
113
113
|
icon: "rectangle.dashed.badge.record",
|
|
114
|
-
title: "Screen
|
|
115
|
-
description: "Allows Lattices to index on-screen text with OCR so you can search across all your windows.",
|
|
114
|
+
title: "Screen Capture",
|
|
115
|
+
description: "Allows Lattices to index on-screen text with OCR so you can search across all your windows. On newer macOS versions this finishes in System Settings under Screen & System Audio Recording.",
|
|
116
116
|
granted: permChecker.screenRecording,
|
|
117
117
|
action: { permChecker.requestScreenRecording() }
|
|
118
118
|
)
|
|
@@ -220,18 +220,11 @@ struct OnboardingView: View {
|
|
|
220
220
|
.multilineTextAlignment(.center)
|
|
221
221
|
.lineSpacing(3)
|
|
222
222
|
|
|
223
|
-
Button(action: {
|
|
224
|
-
let task = Process()
|
|
225
|
-
task.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
|
226
|
-
task.arguments = ["-lc", "brew install tmux"]
|
|
227
|
-
task.standardOutput = FileHandle.nullDevice
|
|
228
|
-
task.standardError = FileHandle.nullDevice
|
|
229
|
-
try? task.run()
|
|
230
|
-
}) {
|
|
223
|
+
Button(action: CliActionLauncher.installTmuxInTerminal) {
|
|
231
224
|
HStack(spacing: 6) {
|
|
232
225
|
Image(systemName: "arrow.down.circle")
|
|
233
226
|
.font(.system(size: 11))
|
|
234
|
-
Text("
|
|
227
|
+
Text("Install tmux in Terminal")
|
|
235
228
|
.font(Typo.monoBold(11))
|
|
236
229
|
}
|
|
237
230
|
.angularButton(.white, filled: false)
|
|
@@ -274,6 +267,27 @@ struct OnboardingView: View {
|
|
|
274
267
|
.strokeBorder(Palette.border, lineWidth: 0.5)
|
|
275
268
|
)
|
|
276
269
|
)
|
|
270
|
+
|
|
271
|
+
VStack(spacing: 10) {
|
|
272
|
+
Text("Pick a repo and let the CLI do the setup in your terminal.")
|
|
273
|
+
.font(Typo.mono(10))
|
|
274
|
+
.foregroundColor(Palette.textMuted)
|
|
275
|
+
.multilineTextAlignment(.center)
|
|
276
|
+
|
|
277
|
+
HStack(spacing: 10) {
|
|
278
|
+
Button(action: CliActionLauncher.initializeProjectInTerminal) {
|
|
279
|
+
Text("Initialize Project")
|
|
280
|
+
.angularButton(Palette.running)
|
|
281
|
+
}
|
|
282
|
+
.buttonStyle(.plain)
|
|
283
|
+
|
|
284
|
+
Button(action: CliActionLauncher.launchProjectInTerminal) {
|
|
285
|
+
Text("Launch Project")
|
|
286
|
+
.angularButton(.white, filled: false)
|
|
287
|
+
}
|
|
288
|
+
.buttonStyle(.plain)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
277
291
|
}
|
|
278
292
|
}
|
|
279
293
|
|
|
@@ -310,7 +324,7 @@ struct OnboardingView: View {
|
|
|
310
324
|
}
|
|
311
325
|
.buttonStyle(.plain)
|
|
312
326
|
|
|
313
|
-
Text("macOS
|
|
327
|
+
Text("macOS may send you to System Settings to finish this step.")
|
|
314
328
|
.font(Typo.mono(10))
|
|
315
329
|
.foregroundColor(Palette.textMuted)
|
|
316
330
|
.multilineTextAlignment(.center)
|
|
@@ -431,9 +445,9 @@ final class OnboardingWindowController {
|
|
|
431
445
|
config: .init(
|
|
432
446
|
title: "Welcome to Lattices",
|
|
433
447
|
titleVisible: false,
|
|
434
|
-
initialSize: NSSize(width: 480, height:
|
|
435
|
-
minSize: NSSize(width: 480, height:
|
|
436
|
-
maxSize: NSSize(width: 480, height:
|
|
448
|
+
initialSize: NSSize(width: 480, height: 470),
|
|
449
|
+
minSize: NSSize(width: 480, height: 470),
|
|
450
|
+
maxSize: NSSize(width: 480, height: 470),
|
|
437
451
|
miniaturizable: false
|
|
438
452
|
),
|
|
439
453
|
rootView: view
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import DeckKit
|
|
1
2
|
import Foundation
|
|
2
3
|
|
|
3
4
|
enum InteractionMode: String {
|
|
@@ -8,6 +9,11 @@ enum InteractionMode: String {
|
|
|
8
9
|
class Preferences: ObservableObject {
|
|
9
10
|
static let shared = Preferences()
|
|
10
11
|
|
|
12
|
+
private enum CompanionDefaultsKey {
|
|
13
|
+
static let trackpadEnabled = "companion.trackpad.enabled"
|
|
14
|
+
static let cockpitLayout = "companion.cockpit.layout"
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
@Published var terminal: Terminal {
|
|
12
18
|
didSet { UserDefaults.standard.set(terminal.rawValue, forKey: "terminal") }
|
|
13
19
|
}
|
|
@@ -20,6 +26,22 @@ class Preferences: ObservableObject {
|
|
|
20
26
|
didSet { UserDefaults.standard.set(mode.rawValue, forKey: "mode") }
|
|
21
27
|
}
|
|
22
28
|
|
|
29
|
+
@Published var dragSnapEnabled: Bool {
|
|
30
|
+
didSet { UserDefaults.standard.set(dragSnapEnabled, forKey: "windowSnap.enabled") }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Published var companionTrackpadEnabled: Bool {
|
|
34
|
+
didSet { UserDefaults.standard.set(companionTrackpadEnabled, forKey: CompanionDefaultsKey.trackpadEnabled) }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Published var companionCockpitLayout: LatticesCompanionCockpitLayout {
|
|
38
|
+
didSet { persistCompanionCockpitLayout() }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Published var mouseGesturesEnabled: Bool {
|
|
42
|
+
didSet { UserDefaults.standard.set(mouseGesturesEnabled, forKey: "mouseGestures.enabled") }
|
|
43
|
+
}
|
|
44
|
+
|
|
23
45
|
// MARK: - AI / Claude
|
|
24
46
|
|
|
25
47
|
@Published var claudePath: String {
|
|
@@ -128,6 +150,25 @@ class Preferences: ObservableObject {
|
|
|
128
150
|
self.mode = .learning
|
|
129
151
|
}
|
|
130
152
|
|
|
153
|
+
if UserDefaults.standard.object(forKey: "windowSnap.enabled") != nil {
|
|
154
|
+
self.dragSnapEnabled = UserDefaults.standard.bool(forKey: "windowSnap.enabled")
|
|
155
|
+
} else {
|
|
156
|
+
self.dragSnapEnabled = true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if UserDefaults.standard.object(forKey: CompanionDefaultsKey.trackpadEnabled) != nil {
|
|
160
|
+
self.companionTrackpadEnabled = UserDefaults.standard.bool(forKey: CompanionDefaultsKey.trackpadEnabled)
|
|
161
|
+
} else {
|
|
162
|
+
self.companionTrackpadEnabled = true
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
self.companionCockpitLayout = Self.loadCompanionCockpitLayout()
|
|
166
|
+
|
|
167
|
+
if UserDefaults.standard.object(forKey: "mouseGestures.enabled") != nil {
|
|
168
|
+
self.mouseGesturesEnabled = UserDefaults.standard.bool(forKey: "mouseGestures.enabled")
|
|
169
|
+
} else {
|
|
170
|
+
self.mouseGesturesEnabled = false
|
|
171
|
+
}
|
|
131
172
|
// AI / Claude
|
|
132
173
|
self.claudePath = UserDefaults.standard.string(forKey: "claude.path") ?? ""
|
|
133
174
|
self.advisorModel = UserDefaults.standard.string(forKey: "claude.advisorModel") ?? "haiku"
|
|
@@ -155,4 +196,41 @@ class Preferences: ObservableObject {
|
|
|
155
196
|
let savedAcc = UserDefaults.standard.string(forKey: "ocr.accuracy") ?? "accurate"
|
|
156
197
|
self.ocrAccuracy = savedAcc
|
|
157
198
|
}
|
|
199
|
+
|
|
200
|
+
func updateCompanionCockpitSlot(
|
|
201
|
+
pageID: String,
|
|
202
|
+
index: Int,
|
|
203
|
+
shortcutID: String
|
|
204
|
+
) {
|
|
205
|
+
var normalized = LatticesCompanionCockpitCatalog.normalized(companionCockpitLayout)
|
|
206
|
+
guard let pageIndex = normalized.pages.firstIndex(where: { $0.id == pageID }),
|
|
207
|
+
normalized.pages[pageIndex].slotIDs.indices.contains(index) else {
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
normalized.pages[pageIndex].slotIDs[index] = shortcutID
|
|
211
|
+
companionCockpitLayout = normalized
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
func resetCompanionCockpitLayout() {
|
|
215
|
+
companionCockpitLayout = LatticesCompanionCockpitCatalog.defaultLayout
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private static func loadCompanionCockpitLayout() -> LatticesCompanionCockpitLayout {
|
|
219
|
+
guard let data = UserDefaults.standard.data(forKey: CompanionDefaultsKey.cockpitLayout),
|
|
220
|
+
let decoded = try? JSONDecoder().decode(LatticesCompanionCockpitLayout.self, from: data) else {
|
|
221
|
+
return LatticesCompanionCockpitCatalog.defaultLayout
|
|
222
|
+
}
|
|
223
|
+
return LatticesCompanionCockpitCatalog.normalized(decoded)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private func persistCompanionCockpitLayout() {
|
|
227
|
+
let normalized = LatticesCompanionCockpitCatalog.normalized(companionCockpitLayout)
|
|
228
|
+
if normalized != companionCockpitLayout {
|
|
229
|
+
companionCockpitLayout = normalized
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
guard let data = try? JSONEncoder().encode(normalized) else { return }
|
|
234
|
+
UserDefaults.standard.set(data, forKey: CompanionDefaultsKey.cockpitLayout)
|
|
235
|
+
}
|
|
158
236
|
}
|