@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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import AppKit
|
|
2
2
|
import SwiftUI
|
|
3
3
|
|
|
4
|
-
/// Manages the unified app window (
|
|
4
|
+
/// Manages the unified app window (Home + Layout + Search + Settings).
|
|
5
5
|
/// Singleton with show/close/toggle, plus showPage() for navigation.
|
|
6
6
|
final class ScreenMapWindowController: ObservableObject {
|
|
7
7
|
static let shared = ScreenMapWindowController()
|
|
8
8
|
|
|
9
9
|
private var window: NSWindow?
|
|
10
10
|
private var controller: ScreenMapController?
|
|
11
|
-
@Published var activePage: AppPage = .
|
|
11
|
+
@Published var activePage: AppPage = .home
|
|
12
12
|
|
|
13
13
|
var isVisible: Bool { window?.isVisible ?? false }
|
|
14
14
|
|
|
@@ -23,7 +23,7 @@ final class ScreenMapWindowController: ObservableObject {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/// Show the window on the current page (defaults to
|
|
26
|
+
/// Show the window on the current page (defaults to Home).
|
|
27
27
|
func show() {
|
|
28
28
|
if let existing = window {
|
|
29
29
|
if activePage == .screenMap {
|
|
@@ -78,6 +78,14 @@ final class ScreenMapWindowController: ObservableObject {
|
|
|
78
78
|
show()
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
func showScreenMapOverview() {
|
|
82
|
+
activePage = .screenMap
|
|
83
|
+
show()
|
|
84
|
+
DispatchQueue.main.async { [weak self] in
|
|
85
|
+
self?.controller?.focusViewportPreset(.overview)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
/// Open screen map focused on a specific window.
|
|
82
90
|
func showWindow(wid: UInt32) {
|
|
83
91
|
activePage = .screenMap
|
|
@@ -105,7 +113,7 @@ final class ScreenMapWindowController: ObservableObject {
|
|
|
105
113
|
window?.orderOut(nil)
|
|
106
114
|
window = nil
|
|
107
115
|
controller = nil
|
|
108
|
-
activePage = .
|
|
116
|
+
activePage = .home
|
|
109
117
|
AppDelegate.updateActivationPolicy()
|
|
110
118
|
}
|
|
111
119
|
}
|
package/app/Sources/{VoiceCommandWindow.swift → Core/Overlays/Voice/VoiceCommandWindow.swift}
RENAMED
|
@@ -2,37 +2,12 @@ import AppKit
|
|
|
2
2
|
import Combine
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
|
-
// MARK: - Panel subclass (handles keyDown when focused)
|
|
6
|
-
|
|
7
|
-
final class VoicePanel: NSPanel {
|
|
8
|
-
var onKeyDown: ((NSEvent) -> Void)?
|
|
9
|
-
var onFlagsChanged: ((NSEvent) -> Void)?
|
|
10
|
-
|
|
11
|
-
override var canBecomeKey: Bool { true }
|
|
12
|
-
|
|
13
|
-
override func keyDown(with event: NSEvent) {
|
|
14
|
-
if let handler = onKeyDown {
|
|
15
|
-
handler(event)
|
|
16
|
-
} else {
|
|
17
|
-
super.keyDown(with: event)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
override func flagsChanged(with event: NSEvent) {
|
|
22
|
-
if let handler = onFlagsChanged {
|
|
23
|
-
handler(event)
|
|
24
|
-
} else {
|
|
25
|
-
super.flagsChanged(with: event)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
5
|
// MARK: - Window Controller
|
|
31
6
|
|
|
32
7
|
final class VoiceCommandWindow {
|
|
33
8
|
static let shared = VoiceCommandWindow()
|
|
34
9
|
|
|
35
|
-
private(set) var panel:
|
|
10
|
+
private(set) var panel: OverlayPanel?
|
|
36
11
|
private var keyMonitor: Any?
|
|
37
12
|
private var state: VoiceCommandState?
|
|
38
13
|
|
|
@@ -48,7 +23,7 @@ final class VoiceCommandWindow {
|
|
|
48
23
|
|
|
49
24
|
func show() {
|
|
50
25
|
// If panel exists but is hidden, just re-show it
|
|
51
|
-
if let p = panel,
|
|
26
|
+
if let p = panel, state != nil {
|
|
52
27
|
p.alphaValue = 0
|
|
53
28
|
p.orderFrontRegardless()
|
|
54
29
|
NSAnimationContext.runAnimationGroup { ctx in
|
|
@@ -69,38 +44,32 @@ final class VoiceCommandWindow {
|
|
|
69
44
|
.preferredColorScheme(.dark)
|
|
70
45
|
|
|
71
46
|
let mouseLocation = NSEvent.mouseLocation
|
|
72
|
-
let screen = NSScreen.screens.first(where: { $0.frame.contains(mouseLocation) })
|
|
47
|
+
let screen = NSScreen.screens.first(where: { $0.frame.contains(mouseLocation) })
|
|
48
|
+
?? NSScreen.main
|
|
49
|
+
?? NSScreen.screens.first!
|
|
73
50
|
let visible = screen.visibleFrame
|
|
74
|
-
|
|
75
51
|
let panelWidth: CGFloat = min(900, visible.width - 80)
|
|
76
52
|
let panelHeight: CGFloat = min(560, visible.height - 80)
|
|
77
53
|
|
|
78
|
-
let p =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
54
|
+
let p = OverlayPanelShell.makePanel(
|
|
55
|
+
config: .init(
|
|
56
|
+
size: NSSize(width: panelWidth, height: panelHeight),
|
|
57
|
+
styleMask: [.titled, .nonactivatingPanel],
|
|
58
|
+
titleVisible: .hidden,
|
|
59
|
+
titlebarAppearsTransparent: true,
|
|
60
|
+
background: .clear,
|
|
61
|
+
hidesOnDeactivate: false,
|
|
62
|
+
isMovableByWindowBackground: true,
|
|
63
|
+
activatesOnMouseDown: true,
|
|
64
|
+
onKeyDown: { [weak self] event in self?.handleKey(event) },
|
|
65
|
+
onFlagsChanged: { [weak self] event in self?.handleFlags(event) }
|
|
66
|
+
),
|
|
67
|
+
rootView: view
|
|
83
68
|
)
|
|
84
|
-
p
|
|
85
|
-
p.onFlagsChanged = { [weak self] event in self?.handleFlags(event) }
|
|
86
|
-
p.titlebarAppearsTransparent = true
|
|
87
|
-
p.titleVisibility = .hidden
|
|
88
|
-
p.isOpaque = false
|
|
89
|
-
p.backgroundColor = .clear
|
|
90
|
-
p.level = .floating
|
|
91
|
-
p.hasShadow = true
|
|
92
|
-
p.hidesOnDeactivate = false
|
|
93
|
-
p.isReleasedWhenClosed = false
|
|
94
|
-
p.isMovableByWindowBackground = true
|
|
95
|
-
p.contentView = NSHostingView(rootView: view)
|
|
96
|
-
|
|
97
|
-
// Position: top-center of screen
|
|
98
|
-
let x = visible.midX - panelWidth / 2
|
|
99
|
-
let y = visible.maxY - panelHeight - 40
|
|
100
|
-
p.setFrameOrigin(NSPoint(x: x, y: y))
|
|
69
|
+
OverlayPanelShell.position(p, placement: .topCenter(margin: 40))
|
|
101
70
|
|
|
102
71
|
p.alphaValue = 0
|
|
103
|
-
p
|
|
72
|
+
OverlayPanelShell.present(p, activate: true, makeKey: true, orderFrontRegardless: true)
|
|
104
73
|
|
|
105
74
|
NSAnimationContext.runAnimationGroup { ctx in
|
|
106
75
|
ctx.duration = 0.15
|
|
@@ -538,6 +507,7 @@ final class VoiceCommandState: ObservableObject {
|
|
|
538
507
|
|
|
539
508
|
struct VoiceCommandView: View {
|
|
540
509
|
@ObservedObject var state: VoiceCommandState
|
|
510
|
+
@ObservedObject private var activeSelection = WindowSelectionStore.shared
|
|
541
511
|
let onDismiss: () -> Void
|
|
542
512
|
|
|
543
513
|
private let docsURL = "https://lattices.dev/docs/voice"
|
|
@@ -862,6 +832,30 @@ struct VoiceCommandView: View {
|
|
|
862
832
|
VStack(alignment: .leading, spacing: 14) {
|
|
863
833
|
// Zero-height spacer forces VStack to fill ScrollView width
|
|
864
834
|
Color.clear.frame(maxWidth: .infinity, maxHeight: 0)
|
|
835
|
+
if activeSelection.isActive {
|
|
836
|
+
commandSection("selection") {
|
|
837
|
+
VStack(alignment: .leading, spacing: 6) {
|
|
838
|
+
HStack(spacing: 6) {
|
|
839
|
+
Text("\(activeSelection.count) window\(activeSelection.count == 1 ? "" : "s")")
|
|
840
|
+
.font(Typo.geistMonoBold(11))
|
|
841
|
+
.foregroundColor(Palette.running)
|
|
842
|
+
if let source = activeSelection.sourceLabel {
|
|
843
|
+
Text(source)
|
|
844
|
+
.font(Typo.geistMono(10))
|
|
845
|
+
.foregroundColor(Palette.textMuted)
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
Text(activeSelection.summary(maxItems: 4))
|
|
849
|
+
.font(Typo.geistMono(11))
|
|
850
|
+
.foregroundColor(Palette.textDim)
|
|
851
|
+
.lineLimit(3)
|
|
852
|
+
Text("Try: grid that in the bottom half")
|
|
853
|
+
.font(Typo.geistMono(10))
|
|
854
|
+
.foregroundColor(Palette.textMuted)
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
865
859
|
// Partial transcript (while listening)
|
|
866
860
|
if state.phase == .listening, !state.partialText.isEmpty {
|
|
867
861
|
commandSection("hearing...") {
|
|
@@ -1591,4 +1585,3 @@ final class DragDividerNSView: NSView {
|
|
|
1591
1585
|
return expanded.contains(point) ? self : nil
|
|
1592
1586
|
}
|
|
1593
1587
|
}
|
|
1594
|
-
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
struct PiAuthNextStepCard: View {
|
|
4
|
+
@ObservedObject var session: PiChatSession
|
|
5
|
+
let compact: Bool
|
|
6
|
+
|
|
7
|
+
var body: some View {
|
|
8
|
+
VStack(alignment: .leading, spacing: compact ? 10 : 12) {
|
|
9
|
+
HStack(spacing: 8) {
|
|
10
|
+
Circle()
|
|
11
|
+
.fill(Palette.running)
|
|
12
|
+
.frame(width: compact ? 6 : 7, height: compact ? 6 : 7)
|
|
13
|
+
|
|
14
|
+
Text(session.authStepLabel)
|
|
15
|
+
.font(Typo.geistMonoBold(compact ? 9 : 10))
|
|
16
|
+
.foregroundColor(Palette.running.opacity(0.95))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Text(session.authStepTitle)
|
|
20
|
+
.font(Typo.geistMonoBold(compact ? 11 : 13))
|
|
21
|
+
.foregroundColor(Palette.text)
|
|
22
|
+
|
|
23
|
+
Text(session.authStepDescription)
|
|
24
|
+
.font(Typo.mono(compact ? 10 : 11))
|
|
25
|
+
.foregroundColor(Palette.textDim)
|
|
26
|
+
.fixedSize(horizontal: false, vertical: true)
|
|
27
|
+
|
|
28
|
+
if let code = session.authVerificationCode {
|
|
29
|
+
VStack(alignment: .leading, spacing: 6) {
|
|
30
|
+
HStack(spacing: 6) {
|
|
31
|
+
Text("CODE READY")
|
|
32
|
+
.font(Typo.geistMonoBold(compact ? 8 : 9))
|
|
33
|
+
.foregroundColor(Palette.textMuted)
|
|
34
|
+
|
|
35
|
+
if session.authVerificationCodeCopied {
|
|
36
|
+
statusCapsule("COPIED")
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Text(code)
|
|
41
|
+
.font(Typo.geistMonoBold(compact ? 14 : 16))
|
|
42
|
+
.foregroundColor(Palette.text)
|
|
43
|
+
.textSelection(.enabled)
|
|
44
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
45
|
+
.padding(.horizontal, compact ? 10 : 12)
|
|
46
|
+
.padding(.vertical, compact ? 9 : 10)
|
|
47
|
+
.background(
|
|
48
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
49
|
+
.fill(Color.white.opacity(0.04))
|
|
50
|
+
.overlay(
|
|
51
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
52
|
+
.strokeBorder(Palette.borderLit.opacity(0.5), lineWidth: 0.5)
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
primaryActionButton(
|
|
59
|
+
session.latestAuthURL == nil
|
|
60
|
+
? "OPENING BROWSER..."
|
|
61
|
+
: (session.authVerificationCode != nil ? "OPEN PAGE AGAIN" : "OPEN BROWSER AGAIN"),
|
|
62
|
+
tint: Palette.running,
|
|
63
|
+
disabled: session.latestAuthURL == nil
|
|
64
|
+
) {
|
|
65
|
+
session.reopenLatestAuthURL()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
HStack(spacing: 8) {
|
|
69
|
+
if session.authVerificationCode != nil {
|
|
70
|
+
secondaryActionButton("COPY AGAIN", tint: Palette.text) {
|
|
71
|
+
session.copyAuthVerificationCode()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Spacer(minLength: 0)
|
|
76
|
+
|
|
77
|
+
secondaryActionButton("CANCEL", tint: Palette.textMuted) {
|
|
78
|
+
session.cancelAuthFlow()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
.padding(.horizontal, compact ? 10 : 16)
|
|
83
|
+
.padding(.vertical, compact ? 10 : 14)
|
|
84
|
+
.background(
|
|
85
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
86
|
+
.fill(Palette.running.opacity(0.06))
|
|
87
|
+
.overlay(
|
|
88
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
89
|
+
.strokeBorder(Palette.running.opacity(0.22), lineWidth: 0.5)
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private func primaryActionButton(_ label: String, tint: Color, disabled: Bool = false, action: @escaping () -> Void) -> some View {
|
|
95
|
+
Button(action: action) {
|
|
96
|
+
Text(label)
|
|
97
|
+
.font(Typo.geistMonoBold(compact ? 10 : 11))
|
|
98
|
+
.foregroundColor(disabled ? Palette.textMuted : tint)
|
|
99
|
+
.frame(maxWidth: .infinity)
|
|
100
|
+
.padding(.horizontal, compact ? 10 : 12)
|
|
101
|
+
.padding(.vertical, compact ? 8 : 10)
|
|
102
|
+
.background(
|
|
103
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
104
|
+
.fill(tint.opacity(disabled ? 0.05 : 0.12))
|
|
105
|
+
.overlay(
|
|
106
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
107
|
+
.strokeBorder((disabled ? Palette.border : tint.opacity(0.35)), lineWidth: 0.5)
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
.buttonStyle(.plain)
|
|
112
|
+
.opacity(disabled ? 0.7 : 1)
|
|
113
|
+
.disabled(disabled)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private func secondaryActionButton(_ label: String, tint: Color, action: @escaping () -> Void) -> some View {
|
|
117
|
+
Button(label, action: action)
|
|
118
|
+
.buttonStyle(.plain)
|
|
119
|
+
.font(Typo.geistMonoBold(compact ? 9 : 10))
|
|
120
|
+
.foregroundColor(tint)
|
|
121
|
+
.padding(.horizontal, compact ? 8 : 10)
|
|
122
|
+
.padding(.vertical, compact ? 5 : 6)
|
|
123
|
+
.background(
|
|
124
|
+
Capsule()
|
|
125
|
+
.fill(Color.white.opacity(0.03))
|
|
126
|
+
.overlay(
|
|
127
|
+
Capsule()
|
|
128
|
+
.strokeBorder(Palette.border, lineWidth: 0.5)
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private func statusCapsule(_ text: String) -> some View {
|
|
134
|
+
Text(text)
|
|
135
|
+
.font(Typo.geistMonoBold(compact ? 8 : 9))
|
|
136
|
+
.foregroundColor(Palette.running.opacity(0.95))
|
|
137
|
+
.padding(.horizontal, compact ? 6 : 7)
|
|
138
|
+
.padding(.vertical, compact ? 3 : 4)
|
|
139
|
+
.background(
|
|
140
|
+
Capsule()
|
|
141
|
+
.fill(Palette.running.opacity(0.12))
|
|
142
|
+
.overlay(
|
|
143
|
+
Capsule()
|
|
144
|
+
.strokeBorder(Palette.running.opacity(0.28), lineWidth: 0.5)
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
struct PiAuthPromptCard: View {
|
|
4
|
+
@ObservedObject var session: PiChatSession
|
|
5
|
+
let prompt: PiAuthPrompt
|
|
6
|
+
let compact: Bool
|
|
7
|
+
var focus: FocusState<Bool>.Binding
|
|
8
|
+
|
|
9
|
+
var body: some View {
|
|
10
|
+
VStack(alignment: .leading, spacing: compact ? 10 : 12) {
|
|
11
|
+
HStack(spacing: 8) {
|
|
12
|
+
Circle()
|
|
13
|
+
.fill(Palette.detach)
|
|
14
|
+
.frame(width: compact ? 6 : 7, height: compact ? 6 : 7)
|
|
15
|
+
|
|
16
|
+
Text("STEP 1")
|
|
17
|
+
.font(Typo.geistMonoBold(compact ? 9 : 10))
|
|
18
|
+
.foregroundColor(Palette.detach.opacity(0.95))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Text("One quick question")
|
|
22
|
+
.font(Typo.geistMonoBold(compact ? 11 : 13))
|
|
23
|
+
.foregroundColor(Palette.text)
|
|
24
|
+
|
|
25
|
+
Text(prompt.message)
|
|
26
|
+
.font(Typo.mono(compact ? 10 : 11))
|
|
27
|
+
.foregroundColor(Palette.textDim)
|
|
28
|
+
.fixedSize(horizontal: false, vertical: true)
|
|
29
|
+
|
|
30
|
+
HStack(spacing: 8) {
|
|
31
|
+
TextField(prompt.placeholder ?? "Type your answer", text: $session.authPromptInput)
|
|
32
|
+
.textFieldStyle(.plain)
|
|
33
|
+
.font(Typo.mono(compact ? 11 : 12))
|
|
34
|
+
.foregroundColor(Palette.text)
|
|
35
|
+
.focused(focus)
|
|
36
|
+
|
|
37
|
+
actionButton("CONTINUE", tint: Palette.detach, disabled: !session.canSubmitAuthPrompt) {
|
|
38
|
+
session.submitAuthPrompt()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
.padding(.horizontal, compact ? 10 : 12)
|
|
42
|
+
.padding(.vertical, compact ? 8 : 10)
|
|
43
|
+
.background(
|
|
44
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
45
|
+
.fill(Color.white.opacity(0.04))
|
|
46
|
+
.overlay(
|
|
47
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
48
|
+
.strokeBorder(Palette.border.opacity(0.85), lineWidth: 0.5)
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
HStack(spacing: 8) {
|
|
53
|
+
Spacer(minLength: 0)
|
|
54
|
+
|
|
55
|
+
actionButton("CANCEL", tint: Palette.textMuted) {
|
|
56
|
+
session.cancelAuthFlow()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
.padding(.horizontal, compact ? 10 : 16)
|
|
61
|
+
.padding(.vertical, compact ? 10 : 14)
|
|
62
|
+
.background(
|
|
63
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
64
|
+
.fill(Palette.detach.opacity(0.06))
|
|
65
|
+
.overlay(
|
|
66
|
+
RoundedRectangle(cornerRadius: compact ? 6 : 8)
|
|
67
|
+
.strokeBorder(Palette.detach.opacity(0.22), lineWidth: 0.5)
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private func actionButton(_ label: String, tint: Color, disabled: Bool = false, action: @escaping () -> Void) -> some View {
|
|
73
|
+
Button(label, action: action)
|
|
74
|
+
.buttonStyle(.plain)
|
|
75
|
+
.font(Typo.geistMonoBold(compact ? 9 : 10))
|
|
76
|
+
.foregroundColor(disabled ? Palette.textMuted : tint)
|
|
77
|
+
.padding(.horizontal, compact ? 8 : 10)
|
|
78
|
+
.padding(.vertical, compact ? 5 : 6)
|
|
79
|
+
.background(
|
|
80
|
+
Capsule()
|
|
81
|
+
.fill(Color.white.opacity(0.03))
|
|
82
|
+
.overlay(
|
|
83
|
+
Capsule()
|
|
84
|
+
.strokeBorder(Palette.border, lineWidth: 0.5)
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
.opacity(disabled ? 0.65 : 1)
|
|
88
|
+
.disabled(disabled)
|
|
89
|
+
}
|
|
90
|
+
}
|