@brimveyn/aimux 1.20.4 → 1.22.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 +27 -25
- package/package.json +2 -2
- package/src/app-runtime/auto-commit-driver.ts +22 -27
- package/src/app-runtime/backend-attach-runtime.ts +43 -36
- package/src/app-runtime/backend-runtime-events.ts +107 -88
- package/src/app-runtime/editor-actions.ts +201 -0
- package/src/app-runtime/git-actions.ts +197 -0
- package/src/app-runtime/measure-ref.ts +19 -0
- package/src/app-runtime/navigation-actions.ts +213 -0
- package/src/app-runtime/project-actions.ts +188 -0
- package/src/app-runtime/prompt-injection.ts +123 -0
- package/src/app-runtime/selection.ts +29 -0
- package/src/app-runtime/settings-actions.ts +156 -0
- package/src/app-runtime/setup-actions.ts +237 -0
- package/src/app-runtime/side-effect-context.ts +33 -0
- package/src/app-runtime/side-effects.ts +305 -1589
- package/src/app-runtime/snippet-actions.ts +3 -2
- package/src/app-runtime/split-drag-controller.ts +4 -8
- package/src/app-runtime/tab-actions.ts +218 -0
- package/src/app-runtime/tab-runtime-timeouts.ts +1 -1
- package/src/app-runtime/use-auto-commit-driver.ts +14 -13
- package/src/app-runtime/use-backend-runtime.ts +12 -11
- package/src/app-runtime/use-directory-search.ts +5 -4
- package/src/app-runtime/use-mouse-handlers.ts +28 -42
- package/src/app-runtime/{use-workspace-autosave.ts → use-project-autosave.ts} +4 -4
- package/src/app-runtime/use-renderer-bindings.ts +2 -1
- package/src/app-runtime/use-setup-runner.ts +96 -0
- package/src/app-runtime/use-terminal-resize.ts +28 -33
- package/src/app-runtime/workspace-actions.ts +366 -0
- package/src/app-runtime/workspace-activity.ts +138 -0
- package/src/app-runtime/workspace-naming.ts +90 -0
- package/src/app.tsx +102 -85
- package/src/assets/sounds/bell.wav +0 -0
- package/src/assets/sounds/ding.wav +0 -0
- package/src/assets/sounds/plane.wav +0 -0
- package/src/cli/client/daemon-client.ts +2 -2
- package/src/cli/client/project-resolver.ts +112 -0
- package/src/cli/commands/project/close.ts +32 -0
- package/src/cli/commands/project/create.ts +93 -0
- package/src/cli/commands/project/list.ts +25 -0
- package/src/cli/commands/project/show.ts +32 -0
- package/src/cli/commands/{workspace → project}/switch.ts +19 -19
- package/src/cli/commands/tab/await.ts +2 -2
- package/src/cli/commands/tab/close.ts +3 -3
- package/src/cli/commands/tab/create.ts +74 -73
- package/src/cli/commands/tab/focus.ts +3 -3
- package/src/cli/commands/tab/list.ts +6 -6
- package/src/cli/commands/tab/run.ts +2 -2
- package/src/cli/commands/tab/send.ts +2 -2
- package/src/cli/commands/tab/snapshot.ts +2 -2
- package/src/cli/commands/tab/tail.ts +2 -2
- package/src/cli/commands/tab/wait.ts +2 -2
- package/src/cli/commands/worker/await.ts +3 -3
- package/src/cli/commands/worker/doctor.ts +30 -30
- package/src/cli/commands/worker/list.ts +15 -15
- package/src/cli/commands/worker/prompt.ts +3 -3
- package/src/cli/commands/worker/run.ts +23 -23
- package/src/cli/commands/worker/shared.ts +53 -59
- package/src/cli/commands/worker/stop.ts +29 -29
- package/src/cli/commands/worker/submit.ts +3 -3
- package/src/cli/commands/{worktree → workspace}/create-core.ts +26 -26
- package/src/cli/commands/workspace/create.ts +30 -68
- package/src/cli/commands/workspace/list.ts +52 -9
- package/src/cli/commands/workspace/remove.ts +81 -0
- package/src/cli/completion/plan.ts +2 -2
- package/src/cli/completion/sources.ts +18 -18
- package/src/cli/context.ts +13 -13
- package/src/cli/flags.ts +30 -10
- package/src/cli/index.ts +26 -16
- package/src/cli/output.ts +1 -1
- package/src/cli/registry.ts +12 -12
- package/src/config/loader.ts +16 -5
- package/src/config.ts +149 -101
- package/src/daemon/catalog-writer.ts +67 -67
- package/src/daemon/daemon.ts +205 -201
- package/src/daemon/session-manager.ts +39 -39
- package/src/daemon/session-registry.ts +14 -14
- package/src/git/divergence.ts +33 -2
- package/src/git/git-poller.ts +1 -1
- package/src/git/git-status.ts +2 -2
- package/src/git/{move-worktree.ts → move-workspace.ts} +5 -5
- package/src/git/pr-merge.ts +64 -0
- package/src/git/pr-status-poller.ts +57 -0
- package/src/git/pr-status.ts +227 -0
- package/src/git/repo-discovery.ts +1 -1
- package/src/git/use-repo-discovery.ts +1 -1
- package/src/git/workspace-branch-poller.ts +54 -0
- package/src/git/workspace-divergence-poller.ts +65 -0
- package/src/git/worktree.ts +29 -0
- package/src/index.tsx +11 -6
- package/src/input/keymap/help-entries.ts +7 -5
- package/src/input/modes/bridge.ts +13 -12
- package/src/input/modes/handlers/shared.ts +1 -1
- package/src/input/modes/transitions.ts +34 -21
- package/src/input/modes/types.ts +48 -31
- package/src/ipc/manager-protocol.ts +44 -44
- package/src/ipc/protocol.ts +192 -166
- package/src/platform/open-url.ts +39 -0
- package/src/platform/play-sound.ts +184 -0
- package/src/platform/project-search.ts +8 -8
- package/src/platform/worktree-paths.ts +8 -6
- package/src/pty/assistant-question-extractor.ts +1 -1
- package/src/pty/assistant-status-detection-loop.ts +79 -55
- package/src/pty/assistant-status-detector.ts +40 -15
- package/src/pty/command-registry.ts +81 -1
- package/src/restart-terminal-manager.ts +1 -1
- package/src/services/ai-usage/provider.ts +9 -2
- package/src/services/ai-usage/spawn.ts +3 -1
- package/src/session-backend/bootstrap.ts +4 -4
- package/src/session-backend/local-session-backend.ts +78 -75
- package/src/session-backend/remote-session-backend.ts +64 -52
- package/src/session-backend/types.ts +43 -32
- package/src/settings/live.ts +90 -0
- package/src/settings/search.ts +43 -0
- package/src/settings/sections/about.ts +49 -0
- package/src/settings/sections/appearance.ts +54 -0
- package/src/settings/sections/automation.ts +105 -0
- package/src/settings/sections/commands.ts +72 -0
- package/src/settings/sections/editor.ts +56 -0
- package/src/settings/sections/experimental.ts +57 -0
- package/src/settings/sections/git.ts +112 -0
- package/src/settings/sections/index.ts +95 -0
- package/src/settings/sections/integrations.ts +23 -0
- package/src/settings/sections/layout.ts +72 -0
- package/src/settings/sections/notifications.ts +99 -0
- package/src/settings/sections/setup.ts +54 -0
- package/src/settings/sections/status-bar.ts +63 -0
- package/src/settings/settings-store.ts +207 -0
- package/src/settings/types.ts +108 -0
- package/src/snippets/run-shell-var.ts +48 -22
- package/src/state/actions.ts +342 -0
- package/src/state/app-store.ts +2 -1
- package/src/state/bars.ts +75 -0
- package/src/state/dispatch-ref.ts +1 -1
- package/src/state/git-pane-sizing.ts +0 -9
- package/src/state/layout-resize.ts +2 -2
- package/src/state/pr-status-store.ts +39 -0
- package/src/state/project-catalog.ts +275 -0
- package/src/state/project-data.ts +143 -0
- package/src/state/{session-persistence.ts → project-persistence.ts} +77 -73
- package/src/state/project-save.ts +46 -0
- package/src/state/project-workspaces.ts +392 -0
- package/src/state/reducers/auto-commit-state.ts +11 -10
- package/src/state/reducers/git-commit-modal-state.ts +122 -0
- package/src/state/reducers/git-mode-state.ts +1 -1
- package/src/state/reducers/git-panel-state.ts +10 -53
- package/src/state/reducers/modal-state.ts +290 -681
- package/src/state/reducers/multi-repo-state.ts +3 -6
- package/src/state/reducers/project-state.ts +312 -0
- package/src/state/reducers/settings-state.ts +80 -0
- package/src/state/reducers/tab-state.ts +107 -60
- package/src/state/reducers/ui-state.ts +86 -15
- package/src/state/selectors.ts +49 -37
- package/src/state/store.ts +83 -57
- package/src/state/types.ts +261 -417
- package/src/state/validation.ts +14 -12
- package/src/terminal-manager/manager-client.ts +32 -32
- package/src/terminal-manager/terminal-manager.ts +24 -24
- package/src/ui/components/git/diff-renderer/pierre-diff.tsx +2 -1
- package/src/ui/components/git/git-panel.tsx +2 -2
- package/src/ui/components/git/git-view.tsx +12 -12
- package/src/ui/components/git/image-diff/image-diff-view.tsx +1 -1
- package/src/ui/components/git/pane/git-pane-header.tsx +105 -39
- package/src/ui/components/git/pane/git-pane-widget.tsx +37 -23
- package/src/ui/components/git/pane/pr-checks-panel.tsx +197 -0
- package/src/ui/components/git/pane/pr-state-row.tsx +103 -0
- package/src/ui/components/layout/bar.tsx +191 -0
- package/src/ui/components/layout/sidebar/project-list.tsx +444 -0
- package/src/ui/components/layout/sidebar/tab-item.tsx +27 -12
- package/src/ui/components/layout/sidebar/use-sidebar-auto-scroll.ts +1 -1
- package/src/ui/components/layout/sidebar/workspace-row.tsx +253 -0
- package/src/ui/components/layout/status-bar.tsx +6 -2
- package/src/ui/components/layout/terminal-pane.tsx +34 -29
- package/src/ui/components/layout/top-tab-bar.tsx +48 -37
- package/src/ui/components/modals/git/git-commit-modal.tsx +8 -8
- package/src/ui/components/modals/{sessions/create-session-modal.tsx → projects/create-project-modal.tsx} +12 -12
- package/src/ui/components/modals/{sessions/session-name-modal.tsx → projects/project-name-modal.tsx} +2 -2
- package/src/ui/components/modals/{sessions/session-picker-modal.tsx → projects/project-picker-modal.tsx} +33 -35
- package/src/ui/components/modals/settings/settings-search-modal.tsx +70 -0
- package/src/ui/components/modals/shared/form.tsx +34 -22
- package/src/ui/components/modals/shared/picker.tsx +10 -10
- package/src/ui/components/modals/shared/{worktree-delete-confirm.tsx → workspace-delete-confirm.tsx} +9 -9
- package/src/ui/components/modals/tabs/new-tab-modal.tsx +30 -324
- package/src/ui/components/modals/workspace/create-workspace-modal.tsx +101 -0
- package/src/ui/components/modals/{worktree/worktree-move-confirm-modal.tsx → workspace/workspace-move-confirm-modal.tsx} +5 -5
- package/src/ui/components/modals/{worktree/worktree-move-modal.tsx → workspace/workspace-move-modal.tsx} +29 -27
- package/src/ui/components/primitives/input-field.tsx +7 -3
- package/src/ui/components/primitives/surface.tsx +3 -0
- package/src/ui/components/settings/row-value.tsx +74 -0
- package/src/ui/components/settings/settings-row.tsx +78 -0
- package/src/ui/components/settings/settings-view.tsx +169 -0
- package/src/ui/components/setup/setup-widget.tsx +152 -0
- package/src/ui/flash/build-labels.ts +27 -27
- package/src/ui/hooks/use-activity-sprite.ts +73 -0
- package/src/ui/hooks/use-scroll-active-into-view.ts +26 -0
- package/src/ui/{session-ordering.ts → project-ordering.ts} +4 -4
- package/src/ui/root.tsx +164 -230
- package/src/ui/status-bar-model.ts +48 -34
- package/src/ui/terminal-graphics/kitty.ts +28 -2
- package/src/ui/terminal-graphics/sprites/done@330/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/done@330/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/idle@1000/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/idle@1000/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/waiting@170/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/waiting@170/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/2.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/3.png +0 -0
- package/src/ui/terminal-graphics/sprites.ts +246 -0
- package/src/ui/truncate.ts +7 -0
- package/src/ui/widgets/registry.tsx +21 -0
- package/src/ui/widgets/widget-context-menu.ts +85 -0
- package/src/update.ts +2 -2
- package/src/app-runtime/session-actions.ts +0 -187
- package/src/cli/client/workspace-resolver.ts +0 -110
- package/src/cli/commands/workspace/close.ts +0 -32
- package/src/cli/commands/workspace/show.ts +0 -32
- package/src/cli/commands/worktree/create.ts +0 -55
- package/src/cli/commands/worktree/list.ts +0 -68
- package/src/cli/commands/worktree/remove.ts +0 -81
- package/src/git/worktree-branch-poller.ts +0 -54
- package/src/git/worktree-divergence-poller.ts +0 -59
- package/src/state/reducers/session-state.ts +0 -262
- package/src/state/session-catalog.ts +0 -143
- package/src/state/session-worktrees.ts +0 -260
- package/src/state/workspace-save.ts +0 -45
- package/src/ui/components/git/pane/git-pane-context-menu.ts +0 -26
- package/src/ui/components/layout/sidebar/sidebar.tsx +0 -163
- package/src/ui/components/layout/sidebar/use-top-tab-bar-auto-scroll.ts +0 -30
- package/src/ui/components/layout/sidebar/workspace-list.tsx +0 -418
- package/src/ui/components/layout/sidebar/worktree-row.tsx +0 -149
- /package/src/ui/{components/git/image-diff → terminal-graphics}/dimensions.ts +0 -0
package/src/ui/root.tsx
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import type { MouseEvent } from '@opentui/core'
|
|
2
2
|
|
|
3
|
-
import { useCallback, useMemo } from 'react'
|
|
3
|
+
import { type ReactNode, useCallback, useMemo } from 'react'
|
|
4
4
|
|
|
5
5
|
import type { MeasuredPaneRect } from '../app-runtime/use-pane-size-report'
|
|
6
|
-
import type { WorktreeTemplate } from '../config'
|
|
7
6
|
import type { TerminalContentOrigin } from '../input/raw-input-handler'
|
|
8
7
|
import type {
|
|
8
|
+
BarSide,
|
|
9
9
|
FocusMode,
|
|
10
10
|
ModalState,
|
|
11
|
-
|
|
11
|
+
ProjectRecord,
|
|
12
12
|
SnippetRecord,
|
|
13
|
-
|
|
13
|
+
WorkspaceRecord,
|
|
14
14
|
} from '../state/types'
|
|
15
15
|
import type { ThemeId } from './themes'
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { useWorkspaceBranchPolling } from '../git/workspace-branch-poller'
|
|
18
|
+
import { useAutoCommitModel } from '../settings/live'
|
|
18
19
|
import { useAppStore } from '../state/app-store'
|
|
19
|
-
import {
|
|
20
|
-
import { getGitPaneWidthFromRatio } from '../state/git-pane-sizing'
|
|
20
|
+
import { getBarWidth } from '../state/bars'
|
|
21
21
|
import { getTreeForTab, PANE_BORDER, type SplitDirection } from '../state/layout-tree'
|
|
22
22
|
import { GitView } from './components/git/git-view'
|
|
23
|
-
import {
|
|
24
|
-
import { GitPaneWidget } from './components/git/pane/git-pane-widget'
|
|
25
|
-
import { Sidebar } from './components/layout/sidebar/sidebar'
|
|
23
|
+
import { Bar, type BarBoundaryResizeInfo } from './components/layout/bar'
|
|
26
24
|
import { SplitLayout } from './components/layout/split-layout'
|
|
27
25
|
import { StatusBar } from './components/layout/status-bar'
|
|
28
26
|
import { TerminalPane } from './components/layout/terminal-pane'
|
|
@@ -31,40 +29,41 @@ import { AIUsageModal } from './components/modals/app/ai-usage-modal'
|
|
|
31
29
|
import { HelpModal } from './components/modals/app/help-modal'
|
|
32
30
|
import { UpdateAvailableModal } from './components/modals/app/update-available-modal'
|
|
33
31
|
import { GitCommitModal } from './components/modals/git/git-commit-modal'
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
32
|
+
import { CreateProjectModal } from './components/modals/projects/create-project-modal'
|
|
33
|
+
import { ProjectNameModal } from './components/modals/projects/project-name-modal'
|
|
34
|
+
import { ProjectPickerModal } from './components/modals/projects/project-picker-modal'
|
|
35
|
+
import { SettingsSearchModal } from './components/modals/settings/settings-search-modal'
|
|
36
|
+
import { WorkspaceDeleteConfirm } from './components/modals/shared/workspace-delete-confirm'
|
|
38
37
|
import { SnippetEditorModal } from './components/modals/snippets/snippet-editor-modal'
|
|
39
38
|
import { SnippetPickerModal } from './components/modals/snippets/snippet-picker-modal'
|
|
40
39
|
import { NewTabModal } from './components/modals/tabs/new-tab-modal'
|
|
41
40
|
import { ThemePickerModal } from './components/modals/themes/theme-picker-modal'
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
41
|
+
import { CreateWorkspaceModal } from './components/modals/workspace/create-workspace-modal'
|
|
42
|
+
import { WorkspaceMoveConfirmModal } from './components/modals/workspace/workspace-move-confirm-modal'
|
|
43
|
+
import { WorkspaceMoveModal } from './components/modals/workspace/workspace-move-modal'
|
|
45
44
|
import { ContextMenuOverlay } from './components/overlays/context-menu/context-menu-overlay'
|
|
46
45
|
import { PendingChordOverlay } from './components/overlays/pending-chord-overlay'
|
|
47
46
|
import { ToastViewport } from './components/overlays/toast/toast-viewport'
|
|
47
|
+
import { SettingsView } from './components/settings/settings-view'
|
|
48
48
|
import { useTheme } from './theme'
|
|
49
49
|
|
|
50
|
-
const
|
|
51
|
-
const EMPTY_BASE_BRANCHES: string[] = []
|
|
50
|
+
const EMPTY_WORKSPACES: WorkspaceRecord[] = []
|
|
52
51
|
|
|
53
|
-
function
|
|
54
|
-
if (modal.type !== 'create-
|
|
55
|
-
return { directoryQuery: '',
|
|
52
|
+
function getCreateProjectFields(modal: ModalState) {
|
|
53
|
+
if (modal.type !== 'create-project') {
|
|
54
|
+
return { directoryQuery: '', projectName: '' }
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
if (modal.activeField === 'directory') {
|
|
59
58
|
return {
|
|
60
59
|
directoryQuery: modal.editBuffer ?? '',
|
|
61
|
-
|
|
60
|
+
projectName: modal.nameBuffer,
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
return {
|
|
66
65
|
directoryQuery: modal.nameBuffer,
|
|
67
|
-
|
|
66
|
+
projectName: modal.editBuffer ?? '',
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
|
|
@@ -85,18 +84,17 @@ function renderModal(
|
|
|
85
84
|
modal: ModalState,
|
|
86
85
|
options: {
|
|
87
86
|
customCommands: Record<string, string>
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
projects: ProjectRecord[]
|
|
88
|
+
currentProjectId: string | null
|
|
90
89
|
currentTabCount: number
|
|
91
90
|
snippets: SnippetRecord[]
|
|
92
91
|
themeId: ThemeId
|
|
93
|
-
|
|
92
|
+
createProjectFields: { directoryQuery: string; projectName: string }
|
|
94
93
|
snippetEditorFields: { snippetName: string; snippetTrigger: string; snippetContent: string }
|
|
95
94
|
focusMode: FocusMode
|
|
96
95
|
activeAssistant?: string
|
|
97
96
|
autoCommitModel?: string
|
|
98
|
-
|
|
99
|
-
worktreeTemplates: WorktreeTemplate[]
|
|
97
|
+
workspaceDivergence: Record<string, { ahead: number; behind: number }>
|
|
100
98
|
}
|
|
101
99
|
) {
|
|
102
100
|
switch (modal.type) {
|
|
@@ -108,62 +106,72 @@ function renderModal(
|
|
|
108
106
|
customCommands={options.customCommands}
|
|
109
107
|
filter={modal.editBuffer}
|
|
110
108
|
cursorPos={modal.cursorPos}
|
|
111
|
-
currentSessionId={options.currentSessionId}
|
|
112
109
|
editingCommand={modal.type === 'new-tab' ? modal.editingCommand : null}
|
|
113
110
|
editBuffer={modal.editBuffer ?? ''}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
111
|
+
excludeTerminal={modal.type === 'new-tab' && modal.pendingWorkspace != null}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
case 'create-workspace':
|
|
115
|
+
return (
|
|
116
|
+
<CreateWorkspaceModal
|
|
117
|
+
activeField={modal.activeField}
|
|
118
|
+
prompt={modal.prompt}
|
|
119
|
+
branchError={modal.branchError}
|
|
120
|
+
baseQuery={modal.baseQuery}
|
|
121
|
+
baseRef={modal.baseRef}
|
|
122
|
+
baseBranches={modal.baseBranches}
|
|
123
|
+
cursorPos={modal.cursorPos}
|
|
124
|
+
selectedIndex={modal.selectedIndex}
|
|
125
|
+
workspaces={
|
|
126
|
+
options.currentProjectId != null && options.currentProjectId !== ''
|
|
127
|
+
? (options.projects.find((project) => project.id === options.currentProjectId)
|
|
128
|
+
?.workspaces ?? EMPTY_WORKSPACES)
|
|
129
|
+
: EMPTY_WORKSPACES
|
|
129
130
|
}
|
|
130
|
-
worktreeName={modal.type === 'new-tab' ? modal.worktreeName : ''}
|
|
131
|
-
worktreeTemplates={options.worktreeTemplates}
|
|
132
|
-
allowTemplateShortcut={modal.type === 'new-tab'}
|
|
133
131
|
/>
|
|
134
132
|
)
|
|
135
|
-
case '
|
|
133
|
+
case 'project-picker':
|
|
136
134
|
return (
|
|
137
|
-
<
|
|
138
|
-
|
|
135
|
+
<ProjectPickerModal
|
|
136
|
+
projects={options.projects}
|
|
139
137
|
selectedIndex={modal.selectedIndex}
|
|
140
|
-
|
|
138
|
+
currentProjectId={options.currentProjectId}
|
|
141
139
|
currentTabCount={options.currentTabCount}
|
|
142
140
|
filter={modal.editBuffer}
|
|
143
141
|
cursorPos={modal.cursorPos}
|
|
144
142
|
/>
|
|
145
143
|
)
|
|
146
|
-
case '
|
|
144
|
+
case 'project-name':
|
|
147
145
|
return (
|
|
148
|
-
<
|
|
146
|
+
<ProjectNameModal
|
|
149
147
|
title={
|
|
150
|
-
modal.
|
|
151
|
-
? 'Rename
|
|
152
|
-
: 'Create
|
|
148
|
+
modal.projectTargetId != null && modal.projectTargetId !== ''
|
|
149
|
+
? 'Rename project'
|
|
150
|
+
: 'Create project'
|
|
153
151
|
}
|
|
154
152
|
value={modal.editBuffer ?? ''}
|
|
155
153
|
/>
|
|
156
154
|
)
|
|
157
155
|
case 'rename-tab':
|
|
158
|
-
return <
|
|
159
|
-
case '
|
|
160
|
-
return <
|
|
161
|
-
case '
|
|
156
|
+
return <ProjectNameModal title="Rename tab" value={modal.editBuffer ?? ''} />
|
|
157
|
+
case 'setting-text':
|
|
158
|
+
return <ProjectNameModal title={modal.settingLabel} value={modal.editBuffer ?? ''} />
|
|
159
|
+
case 'settings-search':
|
|
162
160
|
return (
|
|
163
|
-
<
|
|
161
|
+
<SettingsSearchModal
|
|
162
|
+
filter={modal.editBuffer}
|
|
163
|
+
selectedIndex={modal.selectedIndex}
|
|
164
|
+
cursorPos={modal.cursorPos}
|
|
165
|
+
/>
|
|
166
|
+
)
|
|
167
|
+
case 'rename-workspace':
|
|
168
|
+
return <ProjectNameModal title="Rename workspace" value={modal.editBuffer ?? ''} />
|
|
169
|
+
case 'create-project':
|
|
170
|
+
return (
|
|
171
|
+
<CreateProjectModal
|
|
164
172
|
activeField={modal.activeField}
|
|
165
|
-
directoryQuery={options.
|
|
166
|
-
|
|
173
|
+
directoryQuery={options.createProjectFields.directoryQuery}
|
|
174
|
+
projectName={options.createProjectFields.projectName}
|
|
167
175
|
results={modal.directoryResults}
|
|
168
176
|
selectedIndex={modal.selectedIndex}
|
|
169
177
|
pendingProjectPath={modal.pendingProjectPath}
|
|
@@ -186,7 +194,7 @@ function renderModal(
|
|
|
186
194
|
snippetName={options.snippetEditorFields.snippetName}
|
|
187
195
|
snippetTrigger={options.snippetEditorFields.snippetTrigger}
|
|
188
196
|
snippetContent={options.snippetEditorFields.snippetContent}
|
|
189
|
-
isEditing={modal.
|
|
197
|
+
isEditing={modal.projectTargetId !== null}
|
|
190
198
|
/>
|
|
191
199
|
)
|
|
192
200
|
case 'theme-picker':
|
|
@@ -206,25 +214,25 @@ function renderModal(
|
|
|
206
214
|
latestVersion={modal.latestVersion}
|
|
207
215
|
/>
|
|
208
216
|
)
|
|
209
|
-
case '
|
|
210
|
-
const
|
|
211
|
-
options.
|
|
212
|
-
? options.
|
|
217
|
+
case 'workspace-move': {
|
|
218
|
+
const project =
|
|
219
|
+
options.currentProjectId != null && options.currentProjectId !== ''
|
|
220
|
+
? options.projects.find((entry) => entry.id === options.currentProjectId)
|
|
213
221
|
: undefined
|
|
214
222
|
return (
|
|
215
|
-
<
|
|
216
|
-
deleteSource={modal.type === '
|
|
217
|
-
divergence={options.
|
|
223
|
+
<WorkspaceMoveModal
|
|
224
|
+
deleteSource={modal.type === 'workspace-move' ? modal.deleteSource : false}
|
|
225
|
+
divergence={options.workspaceDivergence}
|
|
218
226
|
selectedIndex={modal.selectedIndex}
|
|
219
|
-
|
|
227
|
+
sourceWorkspaceId={modal.sourceWorkspaceId}
|
|
220
228
|
stats={modal.stats}
|
|
221
|
-
|
|
229
|
+
workspaces={project?.workspaces ?? EMPTY_WORKSPACES}
|
|
222
230
|
/>
|
|
223
231
|
)
|
|
224
232
|
}
|
|
225
|
-
case '
|
|
233
|
+
case 'workspace-move-confirm':
|
|
226
234
|
return (
|
|
227
|
-
<
|
|
235
|
+
<WorkspaceMoveConfirmModal
|
|
228
236
|
variant={modal.variant}
|
|
229
237
|
files={modal.files}
|
|
230
238
|
sourceLabel={modal.sourceLabel}
|
|
@@ -242,12 +250,12 @@ function renderModal(
|
|
|
242
250
|
)
|
|
243
251
|
case 'ai-usage':
|
|
244
252
|
return <AIUsageModal />
|
|
245
|
-
case '
|
|
253
|
+
case 'workspace-delete-confirm':
|
|
246
254
|
return (
|
|
247
|
-
<
|
|
248
|
-
keybindsModeId="modal.
|
|
255
|
+
<WorkspaceDeleteConfirm
|
|
256
|
+
keybindsModeId="modal.workspace-delete-confirm"
|
|
249
257
|
reason={modal.reason}
|
|
250
|
-
|
|
258
|
+
workspaceLabel={modal.workspaceLabel}
|
|
251
259
|
/>
|
|
252
260
|
)
|
|
253
261
|
case 'git-commit': {
|
|
@@ -289,17 +297,8 @@ interface RootViewProps {
|
|
|
289
297
|
onTerminalMouseUp?: (event: MouseEvent) => boolean
|
|
290
298
|
onPaneActivate?: (tabId: string) => void
|
|
291
299
|
onSplitResize?: (tabId: string, ratio: number, axis: SplitDirection) => void
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
initialWidth: number
|
|
295
|
-
screenStart: number
|
|
296
|
-
side: 'left' | 'right'
|
|
297
|
-
}) => void
|
|
298
|
-
onEmbeddedGitResizeStart?: (info: {
|
|
299
|
-
containerStart: number
|
|
300
|
-
position: 'top' | 'bottom'
|
|
301
|
-
totalSize: number
|
|
302
|
-
}) => void
|
|
300
|
+
onBarResizeStart?: (info: { initialWidth: number; screenStart: number; side: BarSide }) => void
|
|
301
|
+
onBarBoundaryResizeStart?: (info: BarBoundaryResizeInfo) => void
|
|
303
302
|
onSeparatorDragStart?: (info: {
|
|
304
303
|
tabId: string
|
|
305
304
|
direction: SplitDirection
|
|
@@ -317,14 +316,13 @@ export function RootView({
|
|
|
317
316
|
contentOrigin,
|
|
318
317
|
localScrollbackEnabled,
|
|
319
318
|
mouseForwardingEnabled,
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
onBarBoundaryResizeStart,
|
|
320
|
+
onBarResizeStart,
|
|
322
321
|
onMeasure,
|
|
323
322
|
onPaneActivate,
|
|
324
323
|
onSeparatorDrag,
|
|
325
324
|
onSeparatorDragEnd,
|
|
326
325
|
onSeparatorDragStart,
|
|
327
|
-
onSidebarResizeStart,
|
|
328
326
|
onSplitResize,
|
|
329
327
|
onTerminalClick,
|
|
330
328
|
onTerminalDrag,
|
|
@@ -345,35 +343,28 @@ export function RootView({
|
|
|
345
343
|
const modal = useAppStore((s) => s.modal)
|
|
346
344
|
const snippets = useAppStore((s) => s.snippets)
|
|
347
345
|
const customCommands = useAppStore((s) => s.customCommands)
|
|
348
|
-
const
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
const gitPaneMode = useAppStore((s) => s.gitPane.mode)
|
|
353
|
-
const gitPaneVisible = useAppStore((s) => s.gitPane.visible)
|
|
354
|
-
const gitPanePosition = useAppStore((s) => s.gitPane.position)
|
|
355
|
-
const gitPaneRatio = useAppStore((s) => s.gitPane.paneRatio)
|
|
356
|
-
const sidebarWidth = useAppStore((s) => s.sidebar.width)
|
|
357
|
-
const sidebarVisible = useAppStore((s) => s.sidebar.visible)
|
|
346
|
+
const projects = useAppStore((s) => s.projects)
|
|
347
|
+
const currentProjectId = useAppStore((s) => s.currentProjectId)
|
|
348
|
+
const workspaceDivergence = useAppStore((s) => s.workspaceDivergence)
|
|
349
|
+
const leftBarWidth = useAppStore((s) => getBarWidth(s.bars.left))
|
|
358
350
|
|
|
359
|
-
const gitPaneInPaneOnLeft = gitPaneMode === 'pane' && gitPaneVisible && gitPanePosition === 'left'
|
|
360
351
|
const splitChrome = PANE_BORDER * 2
|
|
361
352
|
|
|
362
|
-
// Keep every
|
|
353
|
+
// Keep every workspace's `branch` in state synchronized with the on-disk
|
|
363
354
|
// HEAD so the sidebar (and divergence calc) never reads a stale value.
|
|
364
|
-
|
|
355
|
+
useWorkspaceBranchPolling(true)
|
|
365
356
|
|
|
366
|
-
|
|
357
|
+
// The terminal's own left edge stays a drag target for the left bar, so the
|
|
358
|
+
// resize gesture works from either side of the seam.
|
|
359
|
+
const handleLeftBarEdgeResize = useCallback(
|
|
367
360
|
(event: MouseEvent): boolean => {
|
|
368
|
-
|
|
361
|
+
onBarResizeStart?.({ initialWidth: leftBarWidth, screenStart: event.x, side: 'left' })
|
|
369
362
|
return true
|
|
370
363
|
},
|
|
371
|
-
[
|
|
364
|
+
[leftBarWidth, onBarResizeStart]
|
|
372
365
|
)
|
|
373
366
|
const handleTerminalLeftEdgeMouseDown =
|
|
374
|
-
|
|
375
|
-
? handleSidebarEdgeResize
|
|
376
|
-
: undefined
|
|
367
|
+
leftBarWidth > 0 && onBarResizeStart ? handleLeftBarEdgeResize : undefined
|
|
377
368
|
|
|
378
369
|
const handleRootMouseDrag = useCallback(
|
|
379
370
|
(event: MouseEvent) => {
|
|
@@ -415,66 +406,53 @@ export function RootView({
|
|
|
415
406
|
)
|
|
416
407
|
|
|
417
408
|
const activeTab = tabs.find((tab) => tab.id === activeTabId)
|
|
409
|
+
// The generating overlay has always been able to name the model, and nothing
|
|
410
|
+
// ever passed it one.
|
|
411
|
+
const autoCommitModel = useAutoCommitModel(activeTab?.assistant)
|
|
418
412
|
const activeTree =
|
|
419
413
|
activeTabId != null && activeTabId !== ''
|
|
420
414
|
? getTreeForTab(layoutTrees, tabGroupMap, activeTabId)
|
|
421
415
|
: null
|
|
422
|
-
const
|
|
416
|
+
const createProjectFields = getCreateProjectFields(modal)
|
|
423
417
|
const snippetEditorFields = getSnippetEditorFields(modal)
|
|
424
418
|
|
|
419
|
+
// Git mode and settings each swap the pane tree for one full-width view.
|
|
420
|
+
// Everything else on screen — status bar, overlays, modal, toasts — is the
|
|
421
|
+
// same either way, so only the center is a branch: a return per view would
|
|
422
|
+
// mean maintaining the chrome three times.
|
|
425
423
|
const inGitMode = focusMode === 'git' || modal.type === 'git-commit'
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
customCommands,
|
|
440
|
-
focusMode,
|
|
441
|
-
sessions,
|
|
442
|
-
snippetEditorFields,
|
|
443
|
-
snippets,
|
|
444
|
-
themeId,
|
|
445
|
-
worktreeDivergence,
|
|
446
|
-
worktreeTemplates,
|
|
447
|
-
})}
|
|
448
|
-
<ToastViewport />
|
|
449
|
-
</box>
|
|
450
|
-
)
|
|
451
|
-
}
|
|
424
|
+
// A settings row's text field flips focusMode to command-edit, the same way the
|
|
425
|
+
// commit modal does in git mode, so the screen behind it has to stay mounted:
|
|
426
|
+
// those two modals belong to the screen and are read against it.
|
|
427
|
+
//
|
|
428
|
+
// Not `returnTo === 'settings'`, which is where focus goes and not what is
|
|
429
|
+
// behind: the theme picker also returns here, and it previews each theme as you
|
|
430
|
+
// move. Previewing it on the settings screen is not the answer to "how does this
|
|
431
|
+
// theme look" — so it gets the panes, and closing still comes back here.
|
|
432
|
+
const inSettings =
|
|
433
|
+
focusMode === 'settings' || modal.type === 'setting-text' || modal.type === 'settings-search'
|
|
434
|
+
let replacesPanes: ReactNode = null
|
|
435
|
+
if (inGitMode) replacesPanes = <GitView themeId={themeId} />
|
|
436
|
+
else if (inSettings) replacesPanes = <SettingsView />
|
|
452
437
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
onMouseUp={handleRootMouseUp}
|
|
461
|
-
>
|
|
438
|
+
const center =
|
|
439
|
+
replacesPanes !== null ? (
|
|
440
|
+
<>
|
|
441
|
+
<TopTabBar panesReplaced />
|
|
442
|
+
{replacesPanes}
|
|
443
|
+
</>
|
|
444
|
+
) : (
|
|
462
445
|
<box flexDirection="row" gap={0} padding={0} flexGrow={1}>
|
|
463
|
-
<
|
|
464
|
-
|
|
446
|
+
<Bar
|
|
447
|
+
side="left"
|
|
448
|
+
onBoundaryResizeStart={onBarBoundaryResizeStart}
|
|
449
|
+
onEdgeResizeStart={onBarResizeStart}
|
|
465
450
|
onResizeDrag={onSeparatorDrag}
|
|
466
451
|
onResizeDragEnd={onSeparatorDragEnd}
|
|
467
452
|
/>
|
|
468
453
|
<box flexDirection="column" flexGrow={1}>
|
|
469
454
|
<TopTabBar />
|
|
470
455
|
<box flexDirection="row" gap={0} padding={0} flexGrow={1}>
|
|
471
|
-
{gitPaneMode === 'pane' && gitPaneVisible && gitPanePosition === 'left' ? (
|
|
472
|
-
<GitPaneInPaneMode
|
|
473
|
-
position="left"
|
|
474
|
-
ratio={gitPaneRatio}
|
|
475
|
-
onGitPaneResizeStart={onGitPaneResizeStart}
|
|
476
|
-
/>
|
|
477
|
-
) : null}
|
|
478
456
|
{activeTree && activeTree.type === 'split' ? (
|
|
479
457
|
<SplitLayout
|
|
480
458
|
node={activeTree}
|
|
@@ -517,93 +495,49 @@ export function RootView({
|
|
|
517
495
|
onMeasure={onMeasure}
|
|
518
496
|
/>
|
|
519
497
|
)}
|
|
520
|
-
{gitPaneMode === 'pane' && gitPaneVisible && gitPanePosition === 'right' ? (
|
|
521
|
-
<GitPaneInPaneMode
|
|
522
|
-
position="right"
|
|
523
|
-
ratio={gitPaneRatio}
|
|
524
|
-
onGitPaneResizeStart={onGitPaneResizeStart}
|
|
525
|
-
/>
|
|
526
|
-
) : null}
|
|
527
498
|
</box>
|
|
528
499
|
</box>
|
|
500
|
+
<Bar
|
|
501
|
+
side="right"
|
|
502
|
+
onBoundaryResizeStart={onBarBoundaryResizeStart}
|
|
503
|
+
onEdgeResizeStart={onBarResizeStart}
|
|
504
|
+
onResizeDrag={onSeparatorDrag}
|
|
505
|
+
onResizeDragEnd={onSeparatorDragEnd}
|
|
506
|
+
/>
|
|
529
507
|
</box>
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
return (
|
|
511
|
+
<box
|
|
512
|
+
flexDirection="column"
|
|
513
|
+
width="100%"
|
|
514
|
+
height="100%"
|
|
515
|
+
backgroundColor={editorBg}
|
|
516
|
+
// Both drag handlers no-op unless a gesture is in flight, so the full-width
|
|
517
|
+
// views inherit them harmlessly — and a drag that was in flight when one
|
|
518
|
+
// opened gets finalised instead of stranded.
|
|
519
|
+
onMouseDrag={handleRootMouseDrag}
|
|
520
|
+
onMouseUp={handleRootMouseUp}
|
|
521
|
+
>
|
|
522
|
+
{center}
|
|
530
523
|
<StatusBar />
|
|
531
524
|
<PendingChordOverlay />
|
|
532
525
|
<ContextMenuOverlay />
|
|
533
526
|
{renderModal(modal, {
|
|
534
|
-
|
|
535
|
-
|
|
527
|
+
activeAssistant: activeTab?.assistant,
|
|
528
|
+
autoCommitModel,
|
|
529
|
+
createProjectFields,
|
|
530
|
+
currentProjectId,
|
|
536
531
|
currentTabCount: tabs.length,
|
|
537
532
|
customCommands,
|
|
538
533
|
focusMode,
|
|
539
|
-
|
|
534
|
+
projects,
|
|
540
535
|
snippetEditorFields,
|
|
541
536
|
snippets,
|
|
542
537
|
themeId,
|
|
543
|
-
|
|
544
|
-
worktreeTemplates,
|
|
538
|
+
workspaceDivergence,
|
|
545
539
|
})}
|
|
546
540
|
<ToastViewport />
|
|
547
541
|
</box>
|
|
548
542
|
)
|
|
549
543
|
}
|
|
550
|
-
|
|
551
|
-
function GitPaneInPaneMode({
|
|
552
|
-
onGitPaneResizeStart,
|
|
553
|
-
position,
|
|
554
|
-
ratio,
|
|
555
|
-
}: {
|
|
556
|
-
ratio: number
|
|
557
|
-
position: 'left' | 'right'
|
|
558
|
-
onGitPaneResizeStart?: (info: {
|
|
559
|
-
initialWidth: number
|
|
560
|
-
screenStart: number
|
|
561
|
-
side: 'left' | 'right'
|
|
562
|
-
}) => void
|
|
563
|
-
}) {
|
|
564
|
-
const tokens = useTheme()
|
|
565
|
-
const bg = tokens.backgroundPanel
|
|
566
|
-
const gitPane = useAppStore((s) => s.gitPane)
|
|
567
|
-
const width = getGitPaneWidthFromRatio(ratio)
|
|
568
|
-
const contentWidth = Math.max(1, width - 1)
|
|
569
|
-
const gitPaneMenu = buildGitPaneContextMenu(
|
|
570
|
-
gitPane,
|
|
571
|
-
() => dispatchGlobal({ type: 'toggle-git-pane' }),
|
|
572
|
-
(mode, nextPosition) => {
|
|
573
|
-
dispatchGlobal({ mode, type: 'set-git-pane-mode' })
|
|
574
|
-
dispatchGlobal({ position: nextPosition, type: 'set-git-pane-position' })
|
|
575
|
-
}
|
|
576
|
-
)
|
|
577
|
-
const handleResizeMouseDown = useCallback(
|
|
578
|
-
(event: MouseEvent) => {
|
|
579
|
-
event.preventDefault()
|
|
580
|
-
event.stopPropagation()
|
|
581
|
-
onGitPaneResizeStart?.({ initialWidth: width, screenStart: event.x, side: position })
|
|
582
|
-
},
|
|
583
|
-
[onGitPaneResizeStart, position, width]
|
|
584
|
-
)
|
|
585
|
-
const handle = (
|
|
586
|
-
<box
|
|
587
|
-
width={1}
|
|
588
|
-
flexShrink={0}
|
|
589
|
-
backgroundColor={tokens.border}
|
|
590
|
-
onMouseDown={handleResizeMouseDown}
|
|
591
|
-
/>
|
|
592
|
-
)
|
|
593
|
-
return (
|
|
594
|
-
<box flexDirection="column" width={width} flexShrink={0} backgroundColor={bg} overflow="hidden">
|
|
595
|
-
<box flexDirection="row" flexGrow={1} overflow="hidden">
|
|
596
|
-
{position === 'right' ? handle : null}
|
|
597
|
-
<ContextMenuBox
|
|
598
|
-
width={contentWidth}
|
|
599
|
-
flexGrow={1}
|
|
600
|
-
overflow="hidden"
|
|
601
|
-
rightClickMenu={gitPaneMenu}
|
|
602
|
-
>
|
|
603
|
-
<GitPaneWidget pollingEnabled />
|
|
604
|
-
</ContextMenuBox>
|
|
605
|
-
{position === 'left' ? handle : null}
|
|
606
|
-
</box>
|
|
607
|
-
</box>
|
|
608
|
-
)
|
|
609
|
-
}
|