refactor(surface): remove the main-area surface concept entirely

activeSurface was permanently 'chat' after the legacy mobile layout
removal, so the whole concept is gone: the store field, surfaceGuard,
setActiveSurface/setSurfaceGuard, the per-runtime surface memory in
prepare/restoreForRuntimeSwitch, and WorkspaceSurface itself. All ~30
setActiveSurface('chat') call sites were no-ops and are deleted;
always-true 'is the chat active' checks in keyboard shortcuts, Header
and ChatContainer are unconditional now. FilesView's dirty-file guard
kept its file-switch and close protection but drops the surface-switch
branch nothing could trigger. TerminalView visibility comes only from
its callers. The router keeps parsing legacy ?tab= links (they open the
matching context-panel surface) via its own RouteTab type and no longer
serializes a tab or diff file into URLs — desktop URLs never carried
them anyway.
This commit is contained in:
Bohdan Triapitsyn
2026-08-24 16:36:41 +03:00
parent c6e39f15fe
commit c82f188fc8
31 changed files with 49 additions and 276 deletions
+8 -17
View File
@@ -59,7 +59,6 @@ export const useKeyboardShortcuts = () => {
}, [currentShortcutDirectory]);
const isMobile = useUIStore((s) => s.isMobile);
const setSessionSwitcherOpen = useUIStore((s) => s.setSessionSwitcherOpen);
const setActiveSurface = useUIStore((s) => s.setActiveSurface);
const setSettingsDialogOpen = useUIStore((s) => s.setSettingsDialogOpen);
const setModelSelectorOpen = useUIStore((s) => s.setModelSelectorOpen);
const setTimelineDialogOpen = useUIStore((s) => s.setTimelineDialogOpen);
@@ -154,7 +153,6 @@ export const useKeyboardShortcuts = () => {
isAboutDialogOpen,
isMultiRunLauncherOpen,
isImagePreviewOpen,
activeSurface,
isPromptNavigatorPanelOpen,
} = useUIStore.getState();
@@ -183,7 +181,7 @@ export const useKeyboardShortcuts = () => {
}
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen || isMultiRunLauncherOpen || isImagePreviewOpen;
const isChatActive = activeSurface === 'chat';
const isChatActive = true;
if (hasOverlay || !isChatActive) {
resetAbortPriming();
@@ -245,7 +243,6 @@ export const useKeyboardShortcuts = () => {
if (eventMatchesShortcut(e, combo('toggle_prompt_navigator'))) {
const {
activeSurface,
promptNavigatorEnabled,
isSettingsDialogOpen,
isCommandPaletteOpen,
@@ -257,7 +254,7 @@ export const useKeyboardShortcuts = () => {
isImagePreviewOpen,
} = useUIStore.getState();
if (!promptNavigatorEnabled || isMobile || isVSCodeRuntime() || activeSurface !== 'chat') {
if (!promptNavigatorEnabled || isMobile || isVSCodeRuntime()) {
return;
}
@@ -308,7 +305,6 @@ export const useKeyboardShortcuts = () => {
if (matchedNewSessionShortcut || matchedWorktreeShortcut) {
e.preventDefault();
setActiveSurface('chat');
setSessionSwitcherOpen(false);
if (!isVSCodeRuntime() && matchedWorktreeShortcut) {
@@ -394,11 +390,10 @@ export const useKeyboardShortcuts = () => {
isHelpDialogOpen,
isSessionSwitcherOpen,
isAboutDialogOpen,
activeSurface,
} = useUIStore.getState();
const hasOverlay = isSettingsDialogOpen || isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
if (hasOverlay || activeSurface !== 'chat' || !isChatInputTarget(e.target)) {
if (hasOverlay || !isChatInputTarget(e.target)) {
return;
}
@@ -525,7 +520,6 @@ export const useKeyboardShortcuts = () => {
isHelpDialogOpen,
isSessionSwitcherOpen,
isAboutDialogOpen,
activeSurface,
isModelSelectorOpen,
} = useUIStore.getState();
@@ -536,7 +530,7 @@ export const useKeyboardShortcuts = () => {
// Skip if any overlay open or not on chat tab
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
const isChatActive = activeSurface === 'chat';
const isChatActive = true;
if (hasOverlay || !isChatActive) {
return;
@@ -555,7 +549,6 @@ export const useKeyboardShortcuts = () => {
isHelpDialogOpen,
isSessionSwitcherOpen,
isAboutDialogOpen,
activeSurface,
} = useUIStore.getState();
if (isSettingsDialogOpen) {
@@ -563,7 +556,7 @@ export const useKeyboardShortcuts = () => {
}
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
const isChatActive = activeSurface === 'chat';
const isChatActive = true;
if (hasOverlay || !isChatActive) {
return;
@@ -602,7 +595,6 @@ export const useKeyboardShortcuts = () => {
isHelpDialogOpen,
isSessionSwitcherOpen,
isAboutDialogOpen,
activeSurface,
favoriteModels,
addRecentModel,
} = useUIStore.getState();
@@ -612,7 +604,7 @@ export const useKeyboardShortcuts = () => {
}
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
const isChatActive = activeSurface === 'chat';
const isChatActive = true;
if (hasOverlay || !isChatActive || favoriteModels.length === 0) {
return;
@@ -644,8 +636,8 @@ export const useKeyboardShortcuts = () => {
}
if (eventMatchesShortcut(e, combo('toggle_dictation'))) {
const { activeSurface, isCommandPaletteOpen, isHelpDialogOpen, isSessionSwitcherOpen, isSettingsDialogOpen } = useUIStore.getState();
if (activeSurface !== 'chat' || isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isSettingsDialogOpen) {
const { isCommandPaletteOpen, isHelpDialogOpen, isSessionSwitcherOpen, isSettingsDialogOpen } = useUIStore.getState();
if (isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isSettingsDialogOpen) {
return;
}
e.preventDefault();
@@ -695,7 +687,6 @@ export const useKeyboardShortcuts = () => {
toggleTerminalSurfaceExpanded,
isMobile,
setSessionSwitcherOpen,
setActiveSurface,
setSettingsDialogOpen,
setModelSelectorOpen,
setTimelineDialogOpen,
+3 -8
View File
@@ -102,7 +102,6 @@ export const useMenuActions = (
const toggleHelpDialog = useUIStore((s) => s.toggleHelpDialog);
const toggleSidebar = useUIStore((s) => s.toggleSidebar);
const setSessionSwitcherOpen = useUIStore((s) => s.setSessionSwitcherOpen);
const setActiveSurface = useUIStore((s) => s.setActiveSurface);
const setSettingsDialogOpen = useUIStore((s) => s.setSettingsDialogOpen);
const setAboutDialogOpen = useUIStore((s) => s.setAboutDialogOpen);
const checkForUpdates = useUpdateStore((state) => state.checkForUpdates);
@@ -151,10 +150,9 @@ export const useMenuActions = (
const nextSession = sessions[nextIndex];
if (!nextSession) return;
setActiveSurface('chat');
setSessionSwitcherOpen(false);
useSessionUIStore.getState().setCurrentSession(nextSession.id);
}, [setActiveSurface, setSessionSwitcherOpen]);
}, [setSessionSwitcherOpen]);
const navigateProject = React.useCallback((direction: -1 | 1) => {
const { activeProjectId, projects, setActiveProject } = useProjectsStore.getState();
@@ -191,8 +189,7 @@ export const useMenuActions = (
break;
case 'new-session':
setActiveSurface('chat');
setSessionSwitcherOpen(false);
setSessionSwitcherOpen(false);
{
const sessionState = useSessionUIStore.getState();
const directory = useDirectoryStore.getState().currentDirectory;
@@ -203,8 +200,7 @@ export const useMenuActions = (
break;
case 'new-worktree-session':
setActiveSurface('chat');
setSessionSwitcherOpen(false);
setSessionSwitcherOpen(false);
createWorktreeSession();
break;
@@ -341,7 +337,6 @@ export const useMenuActions = (
onToggleMemoryDebug,
openNewSessionDraft,
setAboutDialogOpen,
setActiveSurface,
setSessionSwitcherOpen,
setCommandPaletteOpen,
setSettingsDialogOpen,
+3 -21
View File
@@ -3,7 +3,6 @@ import { useSessionUIStore } from '@/sync/session-ui-store';
import { useUIStore, type ContextPanelMode } from '@/stores/useUIStore';
import { parseRoute, updateBrowserURL, hasRouteParams } from '@/lib/router';
import type { RouteState, AppRouteState } from '@/lib/router';
import type { WorkspaceSurface } from '@/stores/useUIStore';
import { resolveSettingsSlug } from '@/lib/settings/metadata';
import { isEmbeddedSessionChat } from '@/components/layout/contextPanelEmbeddedChat';
import { useDirectoryStore } from '@/stores/useDirectoryStore';
@@ -50,7 +49,6 @@ export function useRouter(): void {
// Get store actions (stable references)
const setCurrentSession = useSessionUIStore((state) => state.setCurrentSession);
const setActiveSurface = useUIStore((state) => state.setActiveSurface);
const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen);
const setSettingsPage = useUIStore((state) => state.setSettingsPage);
const navigateToDiff = useUIStore((state) => state.navigateToDiff);
@@ -109,7 +107,7 @@ export function useRouter(): void {
isApplyingRouteRef.current = false;
}
},
[setCurrentSession, setActiveSurface, setSettingsDialogOpen, setSettingsPage, navigateToDiff]
[setCurrentSession, setSettingsDialogOpen, setSettingsPage, navigateToDiff]
);
/**
@@ -121,10 +119,8 @@ export function useRouter(): void {
return {
sessionId: sessionState.currentSessionId,
tab: uiState.activeSurface,
isSettingsOpen: uiState.isSettingsDialogOpen,
settingsPath: uiState.settingsPage,
diffFile: uiState.pendingDiffFile,
};
}, []);
@@ -170,9 +166,7 @@ export function useRouter(): void {
updateBrowserURL({
...getCurrentAppState(),
sessionId: route.sessionId ?? useSessionUIStore.getState().currentSessionId,
tab: route.tab ?? useUIStore.getState().activeSurface,
settingsPath: route.settingsPath ?? useUIStore.getState().settingsPage,
diffFile: route.diffFile ?? useUIStore.getState().pendingDiffFile,
}, { replace: true, force: true });
}
};
@@ -209,10 +203,8 @@ export function useRouter(): void {
return;
}
let prevSurface: WorkspaceSurface = useUIStore.getState().activeSurface;
let prevSettingsOpen: boolean = useUIStore.getState().isSettingsDialogOpen;
let prevSettingsPath: string = useUIStore.getState().settingsPage;
let prevDiffFile: string | null = useUIStore.getState().pendingDiffFile;
const unsubscribe = useUIStore.subscribe((state) => {
// Skip if we're currently applying a route
@@ -220,19 +212,13 @@ export function useRouter(): void {
return;
}
const surfaceChanged = state.activeSurface !== prevSurface;
const settingsOpenChanged = state.isSettingsDialogOpen !== prevSettingsOpen;
const settingsPathChanged = state.settingsPage !== prevSettingsPath;
const diffFileChanged = state.pendingDiffFile !== prevDiffFile && state.activeSurface === 'diff';
// Update tracking vars
prevSurface = state.activeSurface;
prevSettingsOpen = state.isSettingsDialogOpen;
prevSettingsPath = state.settingsPage;
prevDiffFile = state.pendingDiffFile;
// Only sync if something relevant changed
if (surfaceChanged || settingsOpenChanged || settingsPathChanged || diffFileChanged) {
if (settingsOpenChanged || settingsPathChanged) {
syncURLFromState();
}
});
@@ -260,10 +246,6 @@ export function useRouter(): void {
if (uiState.isSettingsDialogOpen) {
setSettingsDialogOpen(false);
}
// Reset to chat when no route view is specified.
if (uiState.activeSurface !== 'chat') {
setActiveSurface('chat');
}
}
};
@@ -272,5 +254,5 @@ export function useRouter(): void {
return () => {
window.removeEventListener('popstate', handlePopState);
};
}, [applyRoute, isVSCode, isEmbeddedChat, setActiveSurface, setSettingsDialogOpen]);
}, [applyRoute, isVSCode, isEmbeddedChat, setSettingsDialogOpen]);
}