@lattices/cli 0.4.13 → 0.5.0
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 +5 -7
- package/apps/mac/Info.plist +2 -2
- package/apps/mac/Lattices.app/Contents/Info.plist +4 -12
- package/apps/mac/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/bin/lattices-app.ts +110 -17
- package/bin/lattices-build +125 -0
- package/bin/lattices-dev +89 -16
- package/bin/lattices.ts +977 -16
- package/docs/agents.md +81 -4
- package/docs/ai-chat-ux-review.md +416 -0
- package/docs/api.md +135 -3
- package/docs/app.md +30 -8
- package/docs/config.md +4 -0
- package/docs/mouse-gestures.md +191 -63
- package/docs/proposals/LAT-004-interactive-overlay-actors.md +1 -1
- package/docs/proposals/LAT-005-action-runtime-product-spine.md +914 -0
- package/docs/proposals/LAT-006-mira-in-lattices.md +553 -0
- package/docs/reference/dewey.config.ts +2 -2
- package/docs/release.md +171 -0
- package/docs/repo-structure.md +4 -5
- package/docs/voice.md +11 -27
- package/package.json +9 -10
- package/apps/mac/Package.swift +0 -27
- package/apps/mac/Sources/AppShell/App.swift +0 -26
- package/apps/mac/Sources/AppShell/AppActivationCoordinator.swift +0 -27
- package/apps/mac/Sources/AppShell/AppDelegate.swift +0 -189
- package/apps/mac/Sources/AppShell/AppServicesBootstrap.swift +0 -25
- package/apps/mac/Sources/AppShell/AppShellView.swift +0 -171
- package/apps/mac/Sources/AppShell/AppUpdater.swift +0 -305
- package/apps/mac/Sources/AppShell/CliActionLauncher.swift +0 -50
- package/apps/mac/Sources/AppShell/HomeDashboardView.swift +0 -133
- package/apps/mac/Sources/AppShell/HotkeyBootstrap.swift +0 -87
- package/apps/mac/Sources/AppShell/KeyRecorderView.swift +0 -210
- package/apps/mac/Sources/AppShell/LatticesRuntime.swift +0 -104
- package/apps/mac/Sources/AppShell/MainView.swift +0 -847
- package/apps/mac/Sources/AppShell/MainWindow.swift +0 -83
- package/apps/mac/Sources/AppShell/MenuBarController.swift +0 -177
- package/apps/mac/Sources/AppShell/OnboardingView.swift +0 -483
- package/apps/mac/Sources/AppShell/PermissionsAssistantView.swift +0 -366
- package/apps/mac/Sources/AppShell/PermissionsAssistantWindow.swift +0 -70
- package/apps/mac/Sources/AppShell/Preferences.swift +0 -297
- package/apps/mac/Sources/AppShell/SettingsView.swift +0 -3163
- package/apps/mac/Sources/AppShell/SettingsWindow.swift +0 -34
- package/apps/mac/Sources/AppShell/WorkspaceInspectorPresenter.swift +0 -13
- package/apps/mac/Sources/Core/Actions/HotkeyManager.swift +0 -256
- package/apps/mac/Sources/Core/Actions/HotkeyStore.swift +0 -399
- package/apps/mac/Sources/Core/Actions/IntentEngine.swift +0 -988
- package/apps/mac/Sources/Core/Actions/IntentSchema.swift +0 -94
- package/apps/mac/Sources/Core/Actions/Intents/CreateLayerIntent.swift +0 -54
- package/apps/mac/Sources/Core/Actions/Intents/DistributeIntent.swift +0 -56
- package/apps/mac/Sources/Core/Actions/Intents/FocusIntent.swift +0 -69
- package/apps/mac/Sources/Core/Actions/Intents/HelpIntent.swift +0 -41
- package/apps/mac/Sources/Core/Actions/Intents/KillIntent.swift +0 -47
- package/apps/mac/Sources/Core/Actions/Intents/LatticeIntent.swift +0 -53
- package/apps/mac/Sources/Core/Actions/Intents/LaunchIntent.swift +0 -67
- package/apps/mac/Sources/Core/Actions/Intents/ListSessionsIntent.swift +0 -32
- package/apps/mac/Sources/Core/Actions/Intents/ListWindowsIntent.swift +0 -30
- package/apps/mac/Sources/Core/Actions/Intents/ScanIntent.swift +0 -52
- package/apps/mac/Sources/Core/Actions/Intents/SearchIntent.swift +0 -190
- package/apps/mac/Sources/Core/Actions/Intents/SwitchLayerIntent.swift +0 -50
- package/apps/mac/Sources/Core/Actions/Intents/TileIntent.swift +0 -61
- package/apps/mac/Sources/Core/Actions/PaletteCommand.swift +0 -439
- package/apps/mac/Sources/Core/Actions/VoiceIntentResolver.swift +0 -713
- package/apps/mac/Sources/Core/Companion/CompanionActivityLog.swift +0 -70
- package/apps/mac/Sources/Core/Companion/CompanionKeyboardController.swift +0 -141
- package/apps/mac/Sources/Core/Companion/LatticesCompanionBridgeServer.swift +0 -454
- package/apps/mac/Sources/Core/Companion/LatticesCompanionCockpit.swift +0 -555
- package/apps/mac/Sources/Core/Companion/LatticesCompanionSecurityCoordinator.swift +0 -629
- package/apps/mac/Sources/Core/Companion/LatticesCompanionTrackpadController.swift +0 -204
- package/apps/mac/Sources/Core/Companion/LatticesDeckHost.swift +0 -1463
- package/apps/mac/Sources/Core/Daemon/DaemonProtocol.swift +0 -114
- package/apps/mac/Sources/Core/Daemon/DaemonServer.swift +0 -427
- package/apps/mac/Sources/Core/Daemon/LatticesApi.swift +0 -2965
- package/apps/mac/Sources/Core/Desktop/AccessibilityTextExtractor.swift +0 -111
- package/apps/mac/Sources/Core/Desktop/AppTypeClassifier.swift +0 -106
- package/apps/mac/Sources/Core/Desktop/DesktopModel.swift +0 -331
- package/apps/mac/Sources/Core/Desktop/DesktopModelTypes.swift +0 -73
- package/apps/mac/Sources/Core/Desktop/InventoryManager.swift +0 -35
- package/apps/mac/Sources/Core/Desktop/InventoryPath.swift +0 -43
- package/apps/mac/Sources/Core/Desktop/MouseFinder.swift +0 -527
- package/apps/mac/Sources/Core/Desktop/OcrModel.swift +0 -467
- package/apps/mac/Sources/Core/Desktop/OcrStore.swift +0 -329
- package/apps/mac/Sources/Core/Desktop/PlacementSpec.swift +0 -195
- package/apps/mac/Sources/Core/Desktop/SessionWindowLocator.swift +0 -139
- package/apps/mac/Sources/Core/Desktop/TilePickerView.swift +0 -209
- package/apps/mac/Sources/Core/Desktop/WindowCapture.swift +0 -33
- package/apps/mac/Sources/Core/Desktop/WindowDragSnapController.swift +0 -429
- package/apps/mac/Sources/Core/Desktop/WindowPreviewCard.swift +0 -100
- package/apps/mac/Sources/Core/Desktop/WindowPreviewStore.swift +0 -112
- package/apps/mac/Sources/Core/Desktop/WindowSelectionStore.swift +0 -76
- package/apps/mac/Sources/Core/Desktop/WindowTiler.swift +0 -2222
- package/apps/mac/Sources/Core/Input/EventTapBreaker.swift +0 -124
- package/apps/mac/Sources/Core/Input/EventTapThread.swift +0 -54
- package/apps/mac/Sources/Core/Input/InputCaptureResetCenter.swift +0 -20
- package/apps/mac/Sources/Core/Input/KeyboardRemapConfig.swift +0 -69
- package/apps/mac/Sources/Core/Input/KeyboardRemapController.swift +0 -346
- package/apps/mac/Sources/Core/Input/KeyboardRemapStore.swift +0 -141
- package/apps/mac/Sources/Core/Input/MouseGestureConfig.swift +0 -499
- package/apps/mac/Sources/Core/Input/MouseGestureController.swift +0 -2271
- package/apps/mac/Sources/Core/Input/MouseInputDeviceStore.swift +0 -98
- package/apps/mac/Sources/Core/Input/MouseInputEventViewer.swift +0 -272
- package/apps/mac/Sources/Core/Input/MouseShortcutStore.swift +0 -170
- package/apps/mac/Sources/Core/Input/SecureEventInputMonitor.swift +0 -39
- package/apps/mac/Sources/Core/Input/ShapeRecognizer.swift +0 -624
- package/apps/mac/Sources/Core/Input/TapBudgetMeter.swift +0 -56
- package/apps/mac/Sources/Core/Overlays/AppWindowShell.swift +0 -63
- package/apps/mac/Sources/Core/Overlays/CommandMode/CommandModeState.swift +0 -1566
- package/apps/mac/Sources/Core/Overlays/CommandMode/CommandModeView.swift +0 -1927
- package/apps/mac/Sources/Core/Overlays/CommandMode/CommandModeWindow.swift +0 -196
- package/apps/mac/Sources/Core/Overlays/CommandPalette/CommandPaletteView.swift +0 -307
- package/apps/mac/Sources/Core/Overlays/CommandPalette/CommandPaletteWindow.swift +0 -67
- package/apps/mac/Sources/Core/Overlays/HUD/CheatSheetHUD.swift +0 -576
- package/apps/mac/Sources/Core/Overlays/HUD/HUDBottomBar.swift +0 -279
- package/apps/mac/Sources/Core/Overlays/HUD/HUDController.swift +0 -1158
- package/apps/mac/Sources/Core/Overlays/HUD/HUDLeftBar.swift +0 -849
- package/apps/mac/Sources/Core/Overlays/HUD/HUDMinimap.swift +0 -179
- package/apps/mac/Sources/Core/Overlays/HUD/HUDRightBar.swift +0 -596
- package/apps/mac/Sources/Core/Overlays/HUD/HUDState.swift +0 -367
- package/apps/mac/Sources/Core/Overlays/HUD/HUDTopBar.swift +0 -243
- package/apps/mac/Sources/Core/Overlays/HUD/LauncherHUD.swift +0 -334
- package/apps/mac/Sources/Core/Overlays/HUD/LayerBezel.swift +0 -203
- package/apps/mac/Sources/Core/Overlays/OmniSearch/OmniSearchState.swift +0 -280
- package/apps/mac/Sources/Core/Overlays/OmniSearch/OmniSearchView.swift +0 -422
- package/apps/mac/Sources/Core/Overlays/OmniSearch/OmniSearchWindow.swift +0 -94
- package/apps/mac/Sources/Core/Overlays/OverlayPanelShell.swift +0 -241
- package/apps/mac/Sources/Core/Overlays/ScreenMap/ScreenMapState.swift +0 -3135
- package/apps/mac/Sources/Core/Overlays/ScreenMap/ScreenMapView.swift +0 -3977
- package/apps/mac/Sources/Core/Overlays/ScreenMap/ScreenMapWindowController.swift +0 -119
- package/apps/mac/Sources/Core/Overlays/ScreenOverlayCanvasController.swift +0 -1217
- package/apps/mac/Sources/Core/Overlays/Voice/VoiceCommandWindow.swift +0 -1575
- package/apps/mac/Sources/Core/Pi/PiAuthNextStepCard.swift +0 -148
- package/apps/mac/Sources/Core/Pi/PiAuthPromptCard.swift +0 -90
- package/apps/mac/Sources/Core/Pi/PiChatDock.swift +0 -564
- package/apps/mac/Sources/Core/Pi/PiChatSession.swift +0 -1948
- package/apps/mac/Sources/Core/Pi/PiInstallCallout.swift +0 -86
- package/apps/mac/Sources/Core/Pi/PiProviderSetupCallout.swift +0 -99
- package/apps/mac/Sources/Core/Pi/PiWorkspaceView.swift +0 -510
- package/apps/mac/Sources/Core/System/Capability.swift +0 -79
- package/apps/mac/Sources/Core/System/DiagnosticLog.swift +0 -373
- package/apps/mac/Sources/Core/System/EventBus.swift +0 -31
- package/apps/mac/Sources/Core/System/PermissionChecker.swift +0 -224
- package/apps/mac/Sources/Core/System/ProcessModel.swift +0 -199
- package/apps/mac/Sources/Core/System/ProcessQuery.swift +0 -151
- package/apps/mac/Sources/Core/System/SystemTelemetryMonitor.swift +0 -273
- package/apps/mac/Sources/Core/Voice/AdvisorLearningStore.swift +0 -90
- package/apps/mac/Sources/Core/Voice/AgentSession.swift +0 -377
- package/apps/mac/Sources/Core/Voice/AudioProvider.swift +0 -555
- package/apps/mac/Sources/Core/Voice/HandsOffSession.swift +0 -839
- package/apps/mac/Sources/Core/Voice/VoiceChatView.swift +0 -192
- package/apps/mac/Sources/Core/Voice/VoxClient.swift +0 -454
- package/apps/mac/Sources/Core/Workspace/Project.swift +0 -28
- package/apps/mac/Sources/Core/Workspace/ProjectScanner.swift +0 -141
- package/apps/mac/Sources/Core/Workspace/SessionLayerStore.swift +0 -285
- package/apps/mac/Sources/Core/Workspace/SessionManager.swift +0 -75
- package/apps/mac/Sources/Core/Workspace/Terminal/Terminal.swift +0 -259
- package/apps/mac/Sources/Core/Workspace/Terminal/TerminalQuery.swift +0 -156
- package/apps/mac/Sources/Core/Workspace/Terminal/TerminalSynthesizer.swift +0 -200
- package/apps/mac/Sources/Core/Workspace/Tmux/TmuxModel.swift +0 -60
- package/apps/mac/Sources/Core/Workspace/Tmux/TmuxQuery.swift +0 -105
- package/apps/mac/Sources/Core/Workspace/WorkspaceManager.swift +0 -1027
- package/apps/mac/Sources/UI/ActionRow.swift +0 -78
- package/apps/mac/Sources/UI/OrphanRow.swift +0 -129
- package/apps/mac/Sources/UI/ProjectRow.swift +0 -368
- package/apps/mac/Sources/UI/TabGroupRow.swift +0 -178
- package/apps/mac/Sources/UI/Theme.swift +0 -164
- package/apps/mac/Tests/StageDragTests.swift +0 -333
- package/apps/mac/Tests/StageJoinTests.swift +0 -313
- package/apps/mac/Tests/StageManagerTests.swift +0 -280
- package/apps/mac/Tests/StageTileTests.swift +0 -353
- package/swift/Package.swift +0 -20
- package/swift/Sources/DeckKit/DeckAction.swift +0 -51
- package/swift/Sources/DeckKit/DeckBridgeSecurity.swift +0 -152
- package/swift/Sources/DeckKit/DeckCockpit.swift +0 -82
- package/swift/Sources/DeckKit/DeckHost.swift +0 -7
- package/swift/Sources/DeckKit/DeckManifest.swift +0 -145
- package/swift/Sources/DeckKit/DeckRuntimeSnapshot.swift +0 -533
- package/swift/Sources/DeckKit/DeckTrackpad.swift +0 -63
- package/swift/Sources/DeckKit/DeckValue.swift +0 -93
- package/swift/Sources/DeckKit/DeckVoiceError.swift +0 -88
- package/swift/Tests/DeckKitTests/DeckKitTests.swift +0 -286
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
import XCTest
|
|
2
|
-
import CoreGraphics
|
|
3
|
-
import AppKit
|
|
4
|
-
|
|
5
|
-
// Private APIs (same as WindowTiler uses)
|
|
6
|
-
@_silgen_name("_AXUIElementGetWindow")
|
|
7
|
-
func _AXUIElementGetWindow(_ element: AXUIElement, _ windowID: UnsafeMutablePointer<CGWindowID>) -> AXError
|
|
8
|
-
|
|
9
|
-
private let skyLight: UnsafeMutableRawPointer? = dlopen(
|
|
10
|
-
"/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight", RTLD_NOW)
|
|
11
|
-
|
|
12
|
-
private typealias SLSMainConnectionIDFunc = @convention(c) () -> Int32
|
|
13
|
-
private typealias SLSDisableUpdateFunc = @convention(c) (Int32) -> Int32
|
|
14
|
-
private typealias SLSReenableUpdateFunc = @convention(c) (Int32) -> Int32
|
|
15
|
-
|
|
16
|
-
private let _SLSMainConnectionID: SLSMainConnectionIDFunc? = {
|
|
17
|
-
guard let sl = skyLight, let sym = dlsym(sl, "SLSMainConnectionID") else { return nil }
|
|
18
|
-
return unsafeBitCast(sym, to: SLSMainConnectionIDFunc.self)
|
|
19
|
-
}()
|
|
20
|
-
private let _SLSDisableUpdate: SLSDisableUpdateFunc? = {
|
|
21
|
-
guard let sl = skyLight, let sym = dlsym(sl, "SLSDisableUpdate") else { return nil }
|
|
22
|
-
return unsafeBitCast(sym, to: SLSDisableUpdateFunc.self)
|
|
23
|
-
}()
|
|
24
|
-
private let _SLSReenableUpdate: SLSReenableUpdateFunc? = {
|
|
25
|
-
guard let sl = skyLight, let sym = dlsym(sl, "SLSReenableUpdate") else { return nil }
|
|
26
|
-
return unsafeBitCast(sym, to: SLSReenableUpdateFunc.self)
|
|
27
|
-
}()
|
|
28
|
-
|
|
29
|
-
/// Tile windows within the current Stage Manager stage.
|
|
30
|
-
/// Run ONE test at a time: swift test --filter StageTileTests/testMosaic
|
|
31
|
-
final class StageTileTests: XCTestCase {
|
|
32
|
-
|
|
33
|
-
struct LiveWindow {
|
|
34
|
-
let wid: UInt32
|
|
35
|
-
let app: String
|
|
36
|
-
let pid: Int32
|
|
37
|
-
let title: String
|
|
38
|
-
let bounds: CGRect
|
|
39
|
-
let isOnScreen: Bool
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func getRealWindows() -> [LiveWindow] {
|
|
43
|
-
guard let list = CGWindowListCopyWindowInfo(
|
|
44
|
-
[.optionAll, .excludeDesktopElements],
|
|
45
|
-
kCGNullWindowID
|
|
46
|
-
) as? [[String: Any]] else { return [] }
|
|
47
|
-
|
|
48
|
-
let skip: Set<String> = [
|
|
49
|
-
"Window Server", "Dock", "Control Center", "SystemUIServer",
|
|
50
|
-
"Notification Center", "Spotlight", "WindowManager", "Lattices",
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
return list.compactMap { info in
|
|
54
|
-
guard let wid = info[kCGWindowNumber as String] as? UInt32,
|
|
55
|
-
let owner = info[kCGWindowOwnerName as String] as? String,
|
|
56
|
-
let pid = info[kCGWindowOwnerPID as String] as? Int32,
|
|
57
|
-
let boundsDict = info[kCGWindowBounds as String] as? NSDictionary
|
|
58
|
-
else { return nil }
|
|
59
|
-
|
|
60
|
-
var rect = CGRect.zero
|
|
61
|
-
guard CGRectMakeWithDictionaryRepresentation(boundsDict, &rect) else { return nil }
|
|
62
|
-
let title = info[kCGWindowName as String] as? String ?? ""
|
|
63
|
-
let layer = info[kCGWindowLayer as String] as? Int ?? 0
|
|
64
|
-
let isOnScreen = info[kCGWindowIsOnscreen as String] as? Bool ?? false
|
|
65
|
-
|
|
66
|
-
guard layer == 0, rect.width >= 50, rect.height >= 50 else { return nil }
|
|
67
|
-
guard !skip.contains(owner) else { return nil }
|
|
68
|
-
|
|
69
|
-
return LiveWindow(wid: wid, app: owner, pid: pid, title: title,
|
|
70
|
-
bounds: rect, isOnScreen: isOnScreen)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
func getActiveStage() -> [LiveWindow] {
|
|
75
|
-
getRealWindows().filter { $0.isOnScreen && $0.bounds.width > 250 }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
func detectStripWidth() -> CGFloat {
|
|
79
|
-
let thumbnails = getRealWindows().filter {
|
|
80
|
-
$0.isOnScreen && $0.bounds.width < 250 && $0.bounds.height < 250
|
|
81
|
-
&& $0.bounds.origin.x >= 0 && $0.bounds.origin.x < 300
|
|
82
|
-
}
|
|
83
|
-
if thumbnails.isEmpty { return 0 }
|
|
84
|
-
let maxRight = thumbnails.map { $0.bounds.maxX }.max() ?? 0
|
|
85
|
-
return maxRight + 12
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
func stageArea() -> CGRect {
|
|
89
|
-
guard let screen = NSScreen.main else { return .zero }
|
|
90
|
-
let visible = screen.visibleFrame
|
|
91
|
-
let screenHeight = screen.frame.height
|
|
92
|
-
let cgY = screenHeight - visible.origin.y - visible.height
|
|
93
|
-
let strip = detectStripWidth()
|
|
94
|
-
return CGRect(
|
|
95
|
-
x: visible.origin.x + strip,
|
|
96
|
-
y: cgY,
|
|
97
|
-
width: visible.width - strip,
|
|
98
|
-
height: visible.height
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
func printStageState(label: String) {
|
|
103
|
-
let active = getActiveStage()
|
|
104
|
-
print("\n[\(label)] — \(active.count) windows")
|
|
105
|
-
for w in active {
|
|
106
|
-
print(" \(w.app) [\(w.wid)] \"\(w.title.prefix(40))\" — \(Int(w.bounds.origin.x)),\(Int(w.bounds.origin.y)) \(Int(w.bounds.width))x\(Int(w.bounds.height))")
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// MARK: - Batch tile (no app activation — avoids SM stage switches)
|
|
111
|
-
|
|
112
|
-
func batchTile(_ moves: [(wid: UInt32, pid: Int32, frame: CGRect)]) {
|
|
113
|
-
guard !moves.isEmpty else { return }
|
|
114
|
-
|
|
115
|
-
var byPid: [Int32: [(wid: UInt32, target: CGRect)]] = [:]
|
|
116
|
-
for move in moves {
|
|
117
|
-
byPid[move.pid, default: []].append((wid: move.wid, target: move.frame))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Freeze screen
|
|
121
|
-
let cid = _SLSMainConnectionID?()
|
|
122
|
-
if let cid { _ = _SLSDisableUpdate?(cid) }
|
|
123
|
-
|
|
124
|
-
for (pid, windowMoves) in byPid {
|
|
125
|
-
let appRef = AXUIElementCreateApplication(pid)
|
|
126
|
-
AXUIElementSetAttributeValue(appRef, "AXEnhancedUserInterface" as CFString, false as CFTypeRef)
|
|
127
|
-
|
|
128
|
-
var windowsRef: CFTypeRef?
|
|
129
|
-
guard AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, &windowsRef) == .success,
|
|
130
|
-
let axWindows = windowsRef as? [AXUIElement] else { continue }
|
|
131
|
-
|
|
132
|
-
var axByWid: [UInt32: AXUIElement] = [:]
|
|
133
|
-
for axWin in axWindows {
|
|
134
|
-
var windowId: CGWindowID = 0
|
|
135
|
-
if _AXUIElementGetWindow(axWin, &windowId) == .success {
|
|
136
|
-
axByWid[windowId] = axWin
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
for wm in windowMoves {
|
|
141
|
-
guard let axWin = axByWid[wm.wid] else { continue }
|
|
142
|
-
|
|
143
|
-
var newSize = CGSize(width: wm.target.width, height: wm.target.height)
|
|
144
|
-
var newPos = CGPoint(x: wm.target.origin.x, y: wm.target.origin.y)
|
|
145
|
-
|
|
146
|
-
if let sv = AXValueCreate(.cgSize, &newSize) {
|
|
147
|
-
AXUIElementSetAttributeValue(axWin, kAXSizeAttribute as CFString, sv)
|
|
148
|
-
}
|
|
149
|
-
if let pv = AXValueCreate(.cgPoint, &newPos) {
|
|
150
|
-
AXUIElementSetAttributeValue(axWin, kAXPositionAttribute as CFString, pv)
|
|
151
|
-
}
|
|
152
|
-
if let sv = AXValueCreate(.cgSize, &newSize) {
|
|
153
|
-
AXUIElementSetAttributeValue(axWin, kAXSizeAttribute as CFString, sv)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
AXUIElementPerformAction(axWin, kAXRaiseAction as CFString)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
AXUIElementSetAttributeValue(appRef, "AXEnhancedUserInterface" as CFString, true as CFTypeRef)
|
|
160
|
-
// NO app.activate() — just move windows in place without triggering SM
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if let cid { _ = _SLSReenableUpdate?(cid) }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
func gridShape(for count: Int) -> [Int] {
|
|
167
|
-
switch count {
|
|
168
|
-
case 1: return [1]
|
|
169
|
-
case 2: return [2]
|
|
170
|
-
case 3: return [1, 2]
|
|
171
|
-
case 4: return [2, 2]
|
|
172
|
-
case 5: return [3, 2]
|
|
173
|
-
case 6: return [3, 3]
|
|
174
|
-
default:
|
|
175
|
-
let cols = Int(ceil(sqrt(Double(count) * 1.5)))
|
|
176
|
-
var rows: [Int] = []
|
|
177
|
-
var remaining = count
|
|
178
|
-
while remaining > 0 {
|
|
179
|
-
rows.append(min(cols, remaining))
|
|
180
|
-
remaining -= cols
|
|
181
|
-
}
|
|
182
|
-
return rows
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// MARK: - Layouts (run one at a time)
|
|
187
|
-
|
|
188
|
-
/// swift test --filter StageTileTests/testMosaic
|
|
189
|
-
func testMosaic() throws {
|
|
190
|
-
let smEnabled = UserDefaults(suiteName: "com.apple.WindowManager")?.bool(forKey: "GloballyEnabled") ?? false
|
|
191
|
-
try XCTSkipUnless(smEnabled, "Stage Manager is OFF")
|
|
192
|
-
|
|
193
|
-
let windows = getActiveStage()
|
|
194
|
-
guard windows.count >= 2 else {
|
|
195
|
-
print("Need >= 2 windows in active stage, got \(windows.count)")
|
|
196
|
-
return
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
let area = stageArea()
|
|
200
|
-
let gap: CGFloat = 6
|
|
201
|
-
let shape = gridShape(for: windows.count)
|
|
202
|
-
|
|
203
|
-
print("MOSAIC: \(windows.count) windows → \(shape)")
|
|
204
|
-
printStageState(label: "BEFORE")
|
|
205
|
-
|
|
206
|
-
var moves: [(wid: UInt32, pid: Int32, frame: CGRect)] = []
|
|
207
|
-
var idx = 0
|
|
208
|
-
let rows = shape.count
|
|
209
|
-
let rowH = (area.height - gap * CGFloat(rows + 1)) / CGFloat(rows)
|
|
210
|
-
|
|
211
|
-
for (row, cols) in shape.enumerated() {
|
|
212
|
-
let colW = (area.width - gap * CGFloat(cols + 1)) / CGFloat(cols)
|
|
213
|
-
for col in 0..<cols {
|
|
214
|
-
guard idx < windows.count else { break }
|
|
215
|
-
let win = windows[idx]
|
|
216
|
-
moves.append((wid: win.wid, pid: win.pid, frame: CGRect(
|
|
217
|
-
x: area.origin.x + gap + CGFloat(col) * (colW + gap),
|
|
218
|
-
y: area.origin.y + gap + CGFloat(row) * (rowH + gap),
|
|
219
|
-
width: colW,
|
|
220
|
-
height: rowH
|
|
221
|
-
)))
|
|
222
|
-
idx += 1
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
batchTile(moves)
|
|
227
|
-
Thread.sleep(forTimeInterval: 0.3)
|
|
228
|
-
printStageState(label: "AFTER")
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/// swift test --filter StageTileTests/testMainSidebar
|
|
232
|
-
func testMainSidebar() throws {
|
|
233
|
-
let smEnabled = UserDefaults(suiteName: "com.apple.WindowManager")?.bool(forKey: "GloballyEnabled") ?? false
|
|
234
|
-
try XCTSkipUnless(smEnabled, "Stage Manager is OFF")
|
|
235
|
-
|
|
236
|
-
let windows = getActiveStage()
|
|
237
|
-
guard windows.count >= 2 else { return }
|
|
238
|
-
|
|
239
|
-
let area = stageArea()
|
|
240
|
-
let gap: CGFloat = 6
|
|
241
|
-
let mainW = (area.width - gap * 3) * 0.65
|
|
242
|
-
let sideW = (area.width - gap * 3) * 0.35
|
|
243
|
-
let sideCount = windows.count - 1
|
|
244
|
-
let sideH = (area.height - gap * CGFloat(sideCount + 1)) / CGFloat(sideCount)
|
|
245
|
-
|
|
246
|
-
print("MAIN + SIDEBAR: 1 main (65%) + \(sideCount) stacked")
|
|
247
|
-
printStageState(label: "BEFORE")
|
|
248
|
-
|
|
249
|
-
var moves: [(wid: UInt32, pid: Int32, frame: CGRect)] = []
|
|
250
|
-
|
|
251
|
-
moves.append((wid: windows[0].wid, pid: windows[0].pid, frame: CGRect(
|
|
252
|
-
x: area.origin.x + gap,
|
|
253
|
-
y: area.origin.y + gap,
|
|
254
|
-
width: mainW,
|
|
255
|
-
height: area.height - gap * 2
|
|
256
|
-
)))
|
|
257
|
-
|
|
258
|
-
for i in 0..<sideCount {
|
|
259
|
-
let win = windows[i + 1]
|
|
260
|
-
moves.append((wid: win.wid, pid: win.pid, frame: CGRect(
|
|
261
|
-
x: area.origin.x + gap * 2 + mainW,
|
|
262
|
-
y: area.origin.y + gap + CGFloat(i) * (sideH + gap),
|
|
263
|
-
width: sideW,
|
|
264
|
-
height: sideH
|
|
265
|
-
)))
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
batchTile(moves)
|
|
269
|
-
Thread.sleep(forTimeInterval: 0.3)
|
|
270
|
-
printStageState(label: "AFTER")
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/// swift test --filter StageTileTests/testColumns
|
|
274
|
-
func testColumns() throws {
|
|
275
|
-
let smEnabled = UserDefaults(suiteName: "com.apple.WindowManager")?.bool(forKey: "GloballyEnabled") ?? false
|
|
276
|
-
try XCTSkipUnless(smEnabled, "Stage Manager is OFF")
|
|
277
|
-
|
|
278
|
-
let windows = getActiveStage()
|
|
279
|
-
guard windows.count >= 2 else { return }
|
|
280
|
-
|
|
281
|
-
let area = stageArea()
|
|
282
|
-
let gap: CGFloat = 6
|
|
283
|
-
let colW = (area.width - gap * CGFloat(windows.count + 1)) / CGFloat(windows.count)
|
|
284
|
-
|
|
285
|
-
print("COLUMNS: \(windows.count) equal")
|
|
286
|
-
printStageState(label: "BEFORE")
|
|
287
|
-
|
|
288
|
-
let moves = windows.enumerated().map { (i, win) in
|
|
289
|
-
(wid: win.wid, pid: win.pid, frame: CGRect(
|
|
290
|
-
x: area.origin.x + gap + CGFloat(i) * (colW + gap),
|
|
291
|
-
y: area.origin.y + gap,
|
|
292
|
-
width: colW,
|
|
293
|
-
height: area.height - gap * 2
|
|
294
|
-
))
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
batchTile(moves)
|
|
298
|
-
Thread.sleep(forTimeInterval: 0.3)
|
|
299
|
-
printStageState(label: "AFTER")
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/// swift test --filter StageTileTests/testTallWide
|
|
303
|
-
func testTallWide() throws {
|
|
304
|
-
let smEnabled = UserDefaults(suiteName: "com.apple.WindowManager")?.bool(forKey: "GloballyEnabled") ?? false
|
|
305
|
-
try XCTSkipUnless(smEnabled, "Stage Manager is OFF")
|
|
306
|
-
|
|
307
|
-
let windows = getActiveStage()
|
|
308
|
-
guard windows.count >= 2 else { return }
|
|
309
|
-
|
|
310
|
-
let area = stageArea()
|
|
311
|
-
let gap: CGFloat = 6
|
|
312
|
-
|
|
313
|
-
// Terminal-like apps go tall on the left
|
|
314
|
-
let terminalApps = Set(["iTerm2", "Terminal", "Alacritty", "kitty", "Warp"])
|
|
315
|
-
let sorted = windows.sorted { a, b in
|
|
316
|
-
let aT = terminalApps.contains(a.app)
|
|
317
|
-
let bT = terminalApps.contains(b.app)
|
|
318
|
-
if aT != bT { return aT }
|
|
319
|
-
return a.wid < b.wid
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
let tallW = (area.width - gap * 3) * 0.45
|
|
323
|
-
let wideW = (area.width - gap * 3) * 0.55
|
|
324
|
-
let wideCount = sorted.count - 1
|
|
325
|
-
let wideH = (area.height - gap * CGFloat(wideCount + 1)) / CGFloat(wideCount)
|
|
326
|
-
|
|
327
|
-
print("TALL + WIDE: terminal left (45%), \(wideCount) stacked right (55%)")
|
|
328
|
-
printStageState(label: "BEFORE")
|
|
329
|
-
|
|
330
|
-
var moves: [(wid: UInt32, pid: Int32, frame: CGRect)] = []
|
|
331
|
-
|
|
332
|
-
moves.append((wid: sorted[0].wid, pid: sorted[0].pid, frame: CGRect(
|
|
333
|
-
x: area.origin.x + gap,
|
|
334
|
-
y: area.origin.y + gap,
|
|
335
|
-
width: tallW,
|
|
336
|
-
height: area.height - gap * 2
|
|
337
|
-
)))
|
|
338
|
-
|
|
339
|
-
for i in 0..<wideCount {
|
|
340
|
-
let win = sorted[i + 1]
|
|
341
|
-
moves.append((wid: win.wid, pid: win.pid, frame: CGRect(
|
|
342
|
-
x: area.origin.x + gap * 2 + tallW,
|
|
343
|
-
y: area.origin.y + gap + CGFloat(i) * (wideH + gap),
|
|
344
|
-
width: wideW,
|
|
345
|
-
height: wideH
|
|
346
|
-
)))
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
batchTile(moves)
|
|
350
|
-
Thread.sleep(forTimeInterval: 0.3)
|
|
351
|
-
printStageState(label: "AFTER")
|
|
352
|
-
}
|
|
353
|
-
}
|
package/swift/Package.swift
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// swift-tools-version: 5.9
|
|
2
|
-
import PackageDescription
|
|
3
|
-
|
|
4
|
-
let package = Package(
|
|
5
|
-
name: "DeckKit",
|
|
6
|
-
platforms: [
|
|
7
|
-
.macOS(.v13),
|
|
8
|
-
.iOS(.v17)
|
|
9
|
-
],
|
|
10
|
-
products: [
|
|
11
|
-
.library(name: "DeckKit", targets: ["DeckKit"])
|
|
12
|
-
],
|
|
13
|
-
targets: [
|
|
14
|
-
.target(name: "DeckKit"),
|
|
15
|
-
.testTarget(
|
|
16
|
-
name: "DeckKitTests",
|
|
17
|
-
dependencies: ["DeckKit"]
|
|
18
|
-
)
|
|
19
|
-
]
|
|
20
|
-
)
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
public struct DeckActionRequest: Codable, Equatable, Sendable {
|
|
4
|
-
public var pageID: String?
|
|
5
|
-
public var actionID: String
|
|
6
|
-
public var payload: [String: DeckValue]
|
|
7
|
-
|
|
8
|
-
public init(
|
|
9
|
-
pageID: String? = nil,
|
|
10
|
-
actionID: String,
|
|
11
|
-
payload: [String: DeckValue] = [:]
|
|
12
|
-
) {
|
|
13
|
-
self.pageID = pageID
|
|
14
|
-
self.actionID = actionID
|
|
15
|
-
self.payload = payload
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public struct DeckActionResult: Codable, Equatable, Sendable {
|
|
20
|
-
public var ok: Bool
|
|
21
|
-
public var summary: String
|
|
22
|
-
public var detail: String?
|
|
23
|
-
public var runtimeSnapshot: DeckRuntimeSnapshot?
|
|
24
|
-
public var suggestedActions: [DeckSuggestedAction]
|
|
25
|
-
|
|
26
|
-
public init(
|
|
27
|
-
ok: Bool,
|
|
28
|
-
summary: String,
|
|
29
|
-
detail: String? = nil,
|
|
30
|
-
runtimeSnapshot: DeckRuntimeSnapshot? = nil,
|
|
31
|
-
suggestedActions: [DeckSuggestedAction] = []
|
|
32
|
-
) {
|
|
33
|
-
self.ok = ok
|
|
34
|
-
self.summary = summary
|
|
35
|
-
self.detail = detail
|
|
36
|
-
self.runtimeSnapshot = runtimeSnapshot
|
|
37
|
-
self.suggestedActions = suggestedActions
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public struct DeckSuggestedAction: Codable, Equatable, Identifiable, Sendable {
|
|
42
|
-
public var id: String
|
|
43
|
-
public var title: String
|
|
44
|
-
public var iconSystemName: String?
|
|
45
|
-
|
|
46
|
-
public init(id: String, title: String, iconSystemName: String? = nil) {
|
|
47
|
-
self.id = id
|
|
48
|
-
self.title = title
|
|
49
|
-
self.iconSystemName = iconSystemName
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
public struct DeckPairingRequest: Codable, Equatable, Sendable {
|
|
4
|
-
public var deviceID: String
|
|
5
|
-
public var deviceName: String
|
|
6
|
-
public var devicePublicKey: String
|
|
7
|
-
public var platform: String
|
|
8
|
-
public var appVersion: String?
|
|
9
|
-
public var requestedCapabilities: [String]
|
|
10
|
-
|
|
11
|
-
public init(
|
|
12
|
-
deviceID: String,
|
|
13
|
-
deviceName: String,
|
|
14
|
-
devicePublicKey: String,
|
|
15
|
-
platform: String,
|
|
16
|
-
appVersion: String? = nil,
|
|
17
|
-
requestedCapabilities: [String] = DeckBridgeCapability.defaultCompanionCapabilities
|
|
18
|
-
) {
|
|
19
|
-
self.deviceID = deviceID
|
|
20
|
-
self.deviceName = deviceName
|
|
21
|
-
self.devicePublicKey = devicePublicKey
|
|
22
|
-
self.platform = platform
|
|
23
|
-
self.appVersion = appVersion
|
|
24
|
-
self.requestedCapabilities = requestedCapabilities
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private enum CodingKeys: String, CodingKey {
|
|
28
|
-
case deviceID
|
|
29
|
-
case deviceName
|
|
30
|
-
case devicePublicKey
|
|
31
|
-
case platform
|
|
32
|
-
case appVersion
|
|
33
|
-
case requestedCapabilities
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public init(from decoder: Decoder) throws {
|
|
37
|
-
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
38
|
-
deviceID = try container.decode(String.self, forKey: .deviceID)
|
|
39
|
-
deviceName = try container.decode(String.self, forKey: .deviceName)
|
|
40
|
-
devicePublicKey = try container.decode(String.self, forKey: .devicePublicKey)
|
|
41
|
-
platform = try container.decode(String.self, forKey: .platform)
|
|
42
|
-
appVersion = try container.decodeIfPresent(String.self, forKey: .appVersion)
|
|
43
|
-
requestedCapabilities = try container.decodeIfPresent([String].self, forKey: .requestedCapabilities)
|
|
44
|
-
?? DeckBridgeCapability.defaultCompanionCapabilities
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
public struct DeckPairingResponse: Codable, Equatable, Sendable {
|
|
49
|
-
public var disposition: DeckPairingDisposition
|
|
50
|
-
public var bridgeName: String
|
|
51
|
-
public var bridgePublicKey: String
|
|
52
|
-
public var bridgeFingerprint: String
|
|
53
|
-
public var requestSigningRequired: Bool
|
|
54
|
-
public var payloadEncryptionRequired: Bool
|
|
55
|
-
public var grantedCapabilities: [String]
|
|
56
|
-
public var detail: String?
|
|
57
|
-
|
|
58
|
-
public init(
|
|
59
|
-
disposition: DeckPairingDisposition,
|
|
60
|
-
bridgeName: String,
|
|
61
|
-
bridgePublicKey: String,
|
|
62
|
-
bridgeFingerprint: String,
|
|
63
|
-
requestSigningRequired: Bool,
|
|
64
|
-
payloadEncryptionRequired: Bool,
|
|
65
|
-
grantedCapabilities: [String] = DeckBridgeCapability.defaultCompanionCapabilities,
|
|
66
|
-
detail: String? = nil
|
|
67
|
-
) {
|
|
68
|
-
self.disposition = disposition
|
|
69
|
-
self.bridgeName = bridgeName
|
|
70
|
-
self.bridgePublicKey = bridgePublicKey
|
|
71
|
-
self.bridgeFingerprint = bridgeFingerprint
|
|
72
|
-
self.requestSigningRequired = requestSigningRequired
|
|
73
|
-
self.payloadEncryptionRequired = payloadEncryptionRequired
|
|
74
|
-
self.grantedCapabilities = grantedCapabilities
|
|
75
|
-
self.detail = detail
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private enum CodingKeys: String, CodingKey {
|
|
79
|
-
case disposition
|
|
80
|
-
case bridgeName
|
|
81
|
-
case bridgePublicKey
|
|
82
|
-
case bridgeFingerprint
|
|
83
|
-
case requestSigningRequired
|
|
84
|
-
case payloadEncryptionRequired
|
|
85
|
-
case grantedCapabilities
|
|
86
|
-
case detail
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public init(from decoder: Decoder) throws {
|
|
90
|
-
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
91
|
-
disposition = try container.decode(DeckPairingDisposition.self, forKey: .disposition)
|
|
92
|
-
bridgeName = try container.decode(String.self, forKey: .bridgeName)
|
|
93
|
-
bridgePublicKey = try container.decode(String.self, forKey: .bridgePublicKey)
|
|
94
|
-
bridgeFingerprint = try container.decode(String.self, forKey: .bridgeFingerprint)
|
|
95
|
-
requestSigningRequired = try container.decode(Bool.self, forKey: .requestSigningRequired)
|
|
96
|
-
payloadEncryptionRequired = try container.decode(Bool.self, forKey: .payloadEncryptionRequired)
|
|
97
|
-
grantedCapabilities = try container.decodeIfPresent([String].self, forKey: .grantedCapabilities)
|
|
98
|
-
?? DeckBridgeCapability.defaultCompanionCapabilities
|
|
99
|
-
detail = try container.decodeIfPresent(String.self, forKey: .detail)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public enum DeckPairingDisposition: String, Codable, CaseIterable, Sendable {
|
|
104
|
-
case approved
|
|
105
|
-
case alreadyTrusted
|
|
106
|
-
case denied
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
public struct DeckEncryptedEnvelope: Codable, Equatable, Sendable {
|
|
110
|
-
public var sealedBox: String
|
|
111
|
-
|
|
112
|
-
public init(sealedBox: String) {
|
|
113
|
-
self.sealedBox = sealedBox
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
public struct DeckTrustedDeviceSummary: Codable, Equatable, Identifiable, Sendable {
|
|
118
|
-
public var id: String
|
|
119
|
-
public var name: String
|
|
120
|
-
public var fingerprint: String
|
|
121
|
-
public var capabilities: [String]
|
|
122
|
-
public var pairedAt: Date
|
|
123
|
-
public var lastSeenAt: Date
|
|
124
|
-
|
|
125
|
-
public init(
|
|
126
|
-
id: String,
|
|
127
|
-
name: String,
|
|
128
|
-
fingerprint: String,
|
|
129
|
-
capabilities: [String] = [],
|
|
130
|
-
pairedAt: Date,
|
|
131
|
-
lastSeenAt: Date
|
|
132
|
-
) {
|
|
133
|
-
self.id = id
|
|
134
|
-
self.name = name
|
|
135
|
-
self.fingerprint = fingerprint
|
|
136
|
-
self.capabilities = capabilities
|
|
137
|
-
self.pairedAt = pairedAt
|
|
138
|
-
self.lastSeenAt = lastSeenAt
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
public enum DeckBridgeCapability {
|
|
143
|
-
public static let deckRead = "deck.read"
|
|
144
|
-
public static let deckPerform = "deck.perform"
|
|
145
|
-
public static let inputTrackpad = "input.trackpad"
|
|
146
|
-
|
|
147
|
-
public static let defaultCompanionCapabilities = [
|
|
148
|
-
deckRead,
|
|
149
|
-
deckPerform,
|
|
150
|
-
inputTrackpad,
|
|
151
|
-
]
|
|
152
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
public struct DeckCockpitState: Codable, Equatable, Sendable {
|
|
4
|
-
public var title: String?
|
|
5
|
-
public var detail: String?
|
|
6
|
-
public var pages: [DeckCockpitPage]
|
|
7
|
-
|
|
8
|
-
public init(
|
|
9
|
-
title: String? = nil,
|
|
10
|
-
detail: String? = nil,
|
|
11
|
-
pages: [DeckCockpitPage]
|
|
12
|
-
) {
|
|
13
|
-
self.title = title
|
|
14
|
-
self.detail = detail
|
|
15
|
-
self.pages = pages
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public struct DeckCockpitPage: Codable, Equatable, Identifiable, Sendable {
|
|
20
|
-
public var id: String
|
|
21
|
-
public var title: String
|
|
22
|
-
public var subtitle: String?
|
|
23
|
-
public var columns: Int
|
|
24
|
-
public var tiles: [DeckCockpitTile]
|
|
25
|
-
|
|
26
|
-
public init(
|
|
27
|
-
id: String,
|
|
28
|
-
title: String,
|
|
29
|
-
subtitle: String? = nil,
|
|
30
|
-
columns: Int = 4,
|
|
31
|
-
tiles: [DeckCockpitTile]
|
|
32
|
-
) {
|
|
33
|
-
self.id = id
|
|
34
|
-
self.title = title
|
|
35
|
-
self.subtitle = subtitle
|
|
36
|
-
self.columns = columns
|
|
37
|
-
self.tiles = tiles
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public struct DeckCockpitTile: Codable, Equatable, Identifiable, Sendable {
|
|
42
|
-
public var id: String
|
|
43
|
-
public var shortcutID: String
|
|
44
|
-
public var title: String
|
|
45
|
-
public var subtitle: String?
|
|
46
|
-
public var iconSystemName: String
|
|
47
|
-
public var accentToken: String?
|
|
48
|
-
public var deckID: String?
|
|
49
|
-
public var categoryTint: String?
|
|
50
|
-
public var actionID: String?
|
|
51
|
-
public var payload: [String: DeckValue]
|
|
52
|
-
public var isEnabled: Bool
|
|
53
|
-
public var isActive: Bool
|
|
54
|
-
|
|
55
|
-
public init(
|
|
56
|
-
id: String,
|
|
57
|
-
shortcutID: String,
|
|
58
|
-
title: String,
|
|
59
|
-
subtitle: String? = nil,
|
|
60
|
-
iconSystemName: String,
|
|
61
|
-
accentToken: String? = nil,
|
|
62
|
-
deckID: String? = nil,
|
|
63
|
-
categoryTint: String? = nil,
|
|
64
|
-
actionID: String? = nil,
|
|
65
|
-
payload: [String: DeckValue] = [:],
|
|
66
|
-
isEnabled: Bool = true,
|
|
67
|
-
isActive: Bool = false
|
|
68
|
-
) {
|
|
69
|
-
self.id = id
|
|
70
|
-
self.shortcutID = shortcutID
|
|
71
|
-
self.title = title
|
|
72
|
-
self.subtitle = subtitle
|
|
73
|
-
self.iconSystemName = iconSystemName
|
|
74
|
-
self.accentToken = accentToken
|
|
75
|
-
self.deckID = deckID
|
|
76
|
-
self.categoryTint = categoryTint
|
|
77
|
-
self.actionID = actionID
|
|
78
|
-
self.payload = payload
|
|
79
|
-
self.isEnabled = isEnabled
|
|
80
|
-
self.isActive = isActive
|
|
81
|
-
}
|
|
82
|
-
}
|