refactor(settings): always-docked editor toolbar; reorder Navigation

The 'Always show editor toolbar' preference is gone — the docked
toolbar under the file tabs is now the only mode, and the floating
hover toolbar branch in the files editor (with its open-state and
outside-click machinery) is deleted. The stored preference is dropped
by a store migration and removed from desktop settings persistence,
settings search and every locale.

Navigation section order now reads: file editor keymap, auto-save,
terminal shell + login shell, Terminal Quick Keys, and the Session
tabs group last.
This commit is contained in:
Bohdan Triapitsyn
2026-08-25 00:32:09 +03:00
parent f40a247be9
commit b6e14cbf21
18 changed files with 34 additions and 174 deletions
@@ -154,7 +154,6 @@ const GeneralSectionContent: React.FC = () => {
'fileEditorKeymap',
...(!isVSCode ? ['sessionTabs' as const] : []),
'autoSaveEnabled',
'expandedEditorToolbar',
...(!isVSCode ? ['terminalQuickKeys' as const] : []),
...(!isVSCode ? ['terminalShell' as const] : []),
...(!isVSCode ? ['terminalLoginShell' as const] : []),
@@ -266,7 +266,7 @@ const normalizeUserMessageRenderingMode = (mode: unknown): 'markdown' | 'plain'
return mode === 'markdown' ? 'markdown' : 'plain';
};
type VisibleSetting = 'sessionAssist' | 'sessionGoal' | 'theme' | 'windowControlsPosition' | 'pwaInstallName' | 'pwaOrientation' | 'mobileKeyboardMode' | 'timeFormat' | 'weekStart' | 'fontSize' | 'terminalFontSize' | 'terminalShell' | 'terminalLoginShell' | 'editorFontSize' | 'spacing' | 'inputBarOffset' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'messageTransport' | 'activityRenderMode' | 'collapsibleUserMessages' | 'stickyUserHeader' | 'promptNavigatorEnabled' | 'wideChatLayout' | 'codeBlockLineWrap' | 'splitAssistantMessageActions' | 'subagentReadOnlyBanner' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'fileViewerPreview' | 'reasoning' | 'showToolFileIcons' | 'showTurnChangedFiles' | 'expandedTools' | 'followUpBehavior' | 'terminalQuickKeys' | 'fileEditorKeymap' | 'persistDraft' | 'inputSpellcheck' | 'reportUsage' | 'expandedEditorToolbar' | 'autoSaveEnabled' | 'sessionTabs';
type VisibleSetting = 'sessionAssist' | 'sessionGoal' | 'theme' | 'windowControlsPosition' | 'pwaInstallName' | 'pwaOrientation' | 'mobileKeyboardMode' | 'timeFormat' | 'weekStart' | 'fontSize' | 'terminalFontSize' | 'terminalShell' | 'terminalLoginShell' | 'editorFontSize' | 'spacing' | 'inputBarOffset' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'messageTransport' | 'activityRenderMode' | 'collapsibleUserMessages' | 'stickyUserHeader' | 'promptNavigatorEnabled' | 'wideChatLayout' | 'codeBlockLineWrap' | 'splitAssistantMessageActions' | 'subagentReadOnlyBanner' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'fileViewerPreview' | 'reasoning' | 'showToolFileIcons' | 'showTurnChangedFiles' | 'expandedTools' | 'followUpBehavior' | 'terminalQuickKeys' | 'fileEditorKeymap' | 'persistDraft' | 'inputSpellcheck' | 'reportUsage' | 'autoSaveEnabled' | 'sessionTabs';
const WINDOW_CONTROLS_POSITION_OPTIONS: Array<{ id: DesktopWindowControlsPosition; labelKey: string }> = [
{ id: 'left', labelKey: 'settings.openchamber.desktopNetwork.option.windowControlsLeft' },
@@ -315,8 +315,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
const promptNavigatorEnabled = useUIStore(state => state.promptNavigatorEnabled);
const setStickyUserHeader = useUIStore(state => state.setStickyUserHeader);
const setPromptNavigatorEnabled = useUIStore(state => state.setPromptNavigatorEnabled);
const expandedEditorToolbar = useUIStore(state => state.expandedEditorToolbar);
const setExpandedEditorToolbar = useUIStore(state => state.setExpandedEditorToolbar);
const autoSaveEnabled = useUIStore(state => state.autoSaveEnabled);
const setAutoSaveEnabled = useUIStore(state => state.setAutoSaveEnabled);
const wideChatLayoutEnabled = useUIStore(state => state.wideChatLayoutEnabled);
@@ -500,11 +498,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
void updateDesktopSettings({ draftStartersVisible: enabled });
}, [setDraftStartersVisible]);
const handleExpandedEditorToolbarChange = React.useCallback((enabled: boolean) => {
setExpandedEditorToolbar(enabled);
void updateDesktopSettings({ expandedEditorToolbar: enabled });
}, [setExpandedEditorToolbar]);
const handleCollapsibleUserMessagesChange = React.useCallback((enabled: boolean) => {
setCollapsibleUserMessages(enabled);
void updateDesktopSettings({ collapsibleUserMessages: enabled });
@@ -623,7 +616,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
? hasLocalizationSettings
: (shouldShow('theme') || showWindowControlsPositionSetting || shouldShow('pwaInstallName') || shouldShow('pwaOrientation') || shouldShow('timeFormat') || shouldShow('weekStart'));
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('editorFontSize') || shouldShow('spacing') || (shouldShow('inputBarOffset') && isMobile);
const hasNavigationSettings = (shouldShow('terminalQuickKeys') && !isMobile) || ((shouldShow('terminalShell') || shouldShow('terminalLoginShell')) && !isVSCode) || shouldShow('fileEditorKeymap') || shouldShow('autoSaveEnabled') || (shouldShow('expandedEditorToolbar') && !isVSCode) || (shouldShow('sessionTabs') && !isVSCode && !isMobile);
const hasNavigationSettings = (shouldShow('terminalQuickKeys') && !isMobile) || ((shouldShow('terminalShell') || shouldShow('terminalLoginShell')) && !isVSCode) || shouldShow('fileEditorKeymap') || shouldShow('autoSaveEnabled') || (shouldShow('sessionTabs') && !isVSCode && !isMobile);
const hasBehaviorSettings = shouldShow('mermaidRendering')
|| (shouldShow('sessionGoal') && !isVSCode)
|| shouldShow('userMessageRendering')
@@ -1438,20 +1431,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
</SettingsRadioGroup>
</SettingsControlGroup>
)}
{shouldShow('sessionTabs') && !isVSCode && !isMobile && (
<SettingsControlGroup
title={t('settings.openchamber.visual.field.sessionTabsGroup')}
settingsItem="appearance.session-tabs"
>
<SettingsCheckboxRow
checked={sessionTabsEnabled}
onChange={setSessionTabsEnabled}
label={t('settings.openchamber.visual.field.sessionTabs')}
ariaLabel={t('settings.openchamber.visual.field.sessionTabsAria')}
info={t('settings.openchamber.visual.field.sessionTabsInfo')}
/>
</SettingsControlGroup>
)}
<div className={SETTINGS_OPTION_STACK_CLASS}>
{shouldShow('autoSaveEnabled') && (
<SettingsCheckboxRow
@@ -1463,25 +1442,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
settingsItem="appearance.auto-save-enabled"
/>
)}
{shouldShow('expandedEditorToolbar') && !isVSCode && (
<SettingsCheckboxRow
checked={expandedEditorToolbar}
onChange={handleExpandedEditorToolbarChange}
label={t('settings.openchamber.visual.field.expandedEditorToolbar')}
ariaLabel={t('settings.openchamber.visual.field.expandedEditorToolbarAria')}
settingsItem="appearance.expanded-editor-toolbar"
/>
)}
{shouldShow('terminalQuickKeys') && !isMobile && (
<SettingsCheckboxRow
checked={showTerminalQuickKeysOnDesktop}
onChange={setShowTerminalQuickKeysOnDesktop}
label={t('settings.openchamber.visual.field.terminalQuickKeys')}
ariaLabel={t('settings.openchamber.visual.field.terminalQuickKeysAria')}
settingsItem="appearance.terminal-quick-keys"
info={t('settings.openchamber.visual.field.terminalQuickKeysTooltip')}
/>
)}
{showTerminalShellSetting && (
<SettingsStackedField
label={t('settings.openchamber.visual.field.terminalShell')}
@@ -1511,7 +1471,31 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
settingsItem="appearance.terminal-login-shell"
/>
)}
{shouldShow('terminalQuickKeys') && !isMobile && (
<SettingsCheckboxRow
checked={showTerminalQuickKeysOnDesktop}
onChange={setShowTerminalQuickKeysOnDesktop}
label={t('settings.openchamber.visual.field.terminalQuickKeys')}
ariaLabel={t('settings.openchamber.visual.field.terminalQuickKeysAria')}
settingsItem="appearance.terminal-quick-keys"
info={t('settings.openchamber.visual.field.terminalQuickKeysTooltip')}
/>
)}
</div>
{shouldShow('sessionTabs') && !isVSCode && !isMobile && (
<SettingsControlGroup
title={t('settings.openchamber.visual.field.sessionTabsGroup')}
settingsItem="appearance.session-tabs"
>
<SettingsCheckboxRow
checked={sessionTabsEnabled}
onChange={setSessionTabsEnabled}
label={t('settings.openchamber.visual.field.sessionTabs')}
ariaLabel={t('settings.openchamber.visual.field.sessionTabsAria')}
info={t('settings.openchamber.visual.field.sessionTabsInfo')}
/>
</SettingsControlGroup>
)}
</SettingsSection>
)}
+2 -86
View File
@@ -750,8 +750,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
const [wrapLines, setWrapLines] = React.useState(true);
const [isFullscreen, setIsFullscreen] = React.useState(false);
const [isSearchOpen, setIsSearchOpen] = React.useState(false);
const [isFloatingToolbarOpen, setIsFloatingToolbarOpen] = React.useState(false);
const floatingToolbarRef = React.useRef<HTMLDivElement | null>(null);
const toolbarDropdownOpenCountRef = React.useRef(0);
const handleToolbarDropdownOpenChange = React.useCallback((open: boolean) => {
@@ -761,23 +759,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
);
}, []);
const isClickInsidePortalledMenu = React.useCallback((target: EventTarget | null) => {
if (!(target instanceof Element)) return false;
return target.closest('[data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]') !== null;
}, []);
React.useEffect(() => {
if (!isFloatingToolbarOpen) return;
const handler = (event: MouseEvent) => {
if (toolbarDropdownOpenCountRef.current > 0) return;
if (isClickInsidePortalledMenu(event.target)) return;
if (floatingToolbarRef.current && !floatingToolbarRef.current.contains(event.target as Node)) {
setIsFloatingToolbarOpen(false);
}
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, [isClickInsidePortalledMenu, isFloatingToolbarOpen]);
type TextViewMode = 'view' | 'edit';
type PreviewViewMode = 'preview' | 'edit';
@@ -1036,7 +1017,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
const fileEditorKeymap = useUIStore((state) => state.fileEditorKeymap);
const settingsDefaultFileViewerPreview = useConfigStore((state) => state.settingsDefaultFileViewerPreview);
const showMessageTTSButtons = useConfigStore((state) => state.showMessageTTSButtons);
const settingsExpandedEditorToolbar = useUIStore((state) => state.expandedEditorToolbar);
// Global mouseup to end drag selection
React.useEffect(() => {
@@ -3741,9 +3721,8 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
</div>
) : null}
{/* Row 2: Docked editor toolbar (expanded). Desktop opt-in; ALWAYS on
for mobile — floating hover controls don't work with touch. */}
{(settingsExpandedEditorToolbar || isMobile) && selectedFile ? (
{/* Row 2: Docked editor toolbar. */}
{selectedFile ? (
<div className="flex min-w-0 items-center gap-3 border-t border-border/40 bg-[var(--surface-subtle)] px-3 py-1">
{/* Mobile hosts already show the file name in their own header;
a truncated duplicate here just eats toolbar width. */}
@@ -3764,69 +3743,6 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
</div>
<div className="flex-1 min-h-0 min-w-0 relative">
{selectedFile && !isSearchOpen && !(settingsExpandedEditorToolbar || isMobile) && (
<div
ref={floatingToolbarRef}
className="absolute right-3 top-3 z-30"
onMouseLeave={() => {
if (toolbarDropdownOpenCountRef.current > 0) return;
setIsFloatingToolbarOpen(false);
}}
>
{isFloatingToolbarOpen ? (
renderFloatingFileControls()
) : (
<div className="flex items-center gap-1">
{isMarkdown ? (
<Tooltip>
<TooltipTrigger asChild>
<span className="inline-flex">
<Button
variant="ghost"
size="sm"
onClick={() => saveMdViewMode(getMdViewMode() === 'preview' ? 'edit' : 'preview')}
className={cn(
'size-8 rounded-lg border border-[var(--interactive-border)] bg-[var(--surface-elevated)] p-0 shadow-sm transition-colors',
getMdViewMode() === 'preview'
? 'bg-[var(--interactive-selection)] text-[var(--interactive-selection-foreground)] hover:bg-[var(--interactive-selection)]'
: 'text-muted-foreground hover:text-foreground'
)}
aria-label={t(getMdViewMode() === 'preview' ? 'filesView.editor.switchToEditMode' : 'filesView.editor.switchToPreviewMode')}
title={t(getMdViewMode() === 'preview' ? 'filesView.editor.switchToEditMode' : 'filesView.editor.switchToPreviewMode')}
>
<Icon name={getMdViewMode() === 'preview' ? 'eye' : 'eye-off'} className="size-4" />
</Button>
</span>
</TooltipTrigger>
<TooltipContent side="bottom" sideOffset={6}>
{t(getMdViewMode() === 'preview' ? 'filesView.editor.switchToEditMode' : 'filesView.editor.switchToPreviewMode')}
</TooltipContent>
</Tooltip>
) : null}
<Tooltip>
<TooltipTrigger asChild>
<span
className="inline-flex"
onMouseEnter={() => setIsFloatingToolbarOpen(true)}
>
<Button
variant="ghost"
size="sm"
onClick={() => setIsFloatingToolbarOpen(true)}
className="size-8 rounded-lg border border-[var(--interactive-border)] bg-[var(--surface-elevated)] p-0 text-muted-foreground shadow-sm hover:text-foreground"
aria-label={t('filesView.editor.showControlsAria')}
title={t('filesView.editor.controlsTitle')}
>
<Icon name="more-2-fill" className="size-4" />
</Button>
</span>
</TooltipTrigger>
<TooltipContent side="bottom" sideOffset={6}>{t('filesView.editor.controlsTitle')}</TooltipContent>
</Tooltip>
</div>
)}
</div>
)}
<ScrollableOverlay outerClassName="h-full min-w-0" className="h-full min-w-0">
{!selectedFile ? (
<div className="p-3 typography-ui text-muted-foreground">{t('filesView.editor.pickFileFromTree')}</div>
-1
View File
@@ -179,7 +179,6 @@ export type DesktopSettings = {
collapsibleUserMessages?: boolean;
stickyUserHeader?: boolean;
promptNavigatorEnabled?: boolean;
expandedEditorToolbar?: boolean;
wideChatLayoutEnabled?: boolean;
showSplitAssistantMessageActions?: boolean;
fontSize?: number;
@@ -1953,8 +1953,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': 'Fixierter Benutzerkopf',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': 'Prompt-Navigator',
'settings.openchamber.visual.field.promptNavigatorEnabled': 'Prompt-Navigator',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Editor-Werkzeugleiste immer anzeigen',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Editor-Werkzeugleiste immer anzeigen (unter den Datei-Reitern angeheftet)',
'settings.openchamber.visual.field.wideChatLayoutAria': 'Breites Chat-Layout',
'settings.openchamber.visual.field.wideChatLayout': 'Breites Chat-Layout',
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'Codeblock-Zeilen umbrechen',
@@ -2031,8 +2031,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': 'Sticky User Header',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': 'Prompt navigator',
'settings.openchamber.visual.field.promptNavigatorEnabled': 'Prompt Navigator',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Always show editor toolbar',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Always show editor toolbar (docked under the file tabs)',
'settings.openchamber.visual.field.autoSaveEnabledAria': 'Auto-save files',
'settings.openchamber.visual.field.autoSaveEnabled': 'Auto-save files',
'settings.openchamber.visual.field.autoSaveEnabledInfo': 'Automatically save file edits after you stop typing. Disable to require manual save.',
@@ -2008,8 +2008,6 @@ export const settingsDict = {
"settings.openchamber.visual.field.stickyUserHeader": "Encabezado de usuario fijo",
"settings.openchamber.visual.field.promptNavigatorEnabledAria": "Navegador de prompts",
"settings.openchamber.visual.field.promptNavigatorEnabled": "Navegador de prompts",
"settings.openchamber.visual.field.expandedEditorToolbarAria": "Mostrar siempre la barra de herramientas del editor",
"settings.openchamber.visual.field.expandedEditorToolbar": "Mostrar siempre la barra de herramientas del editor (anclada bajo las pestañas)",
"settings.openchamber.visual.field.autoSaveEnabledAria": "Guardado automático de archivos",
"settings.openchamber.visual.field.autoSaveEnabled": "Guardado automático de archivos",
"settings.openchamber.visual.field.autoSaveEnabledInfo": "Guarda automáticamente las ediciones del archivo después de dejar de escribir. Desactívalo para exigir un guardado manual.",
@@ -1915,8 +1915,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': 'En-tête utilisateur collant',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': 'Navigateur de prompts',
'settings.openchamber.visual.field.promptNavigatorEnabled': 'Navigateur de prompts',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Toujours afficher la barre doutils de l’éditeur',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Toujours afficher la barre doutils de l’éditeur (ancrée sous les onglets de fichiers)',
'settings.openchamber.visual.field.autoSaveEnabledAria': 'Enregistrement automatique des fichiers',
'settings.openchamber.visual.field.autoSaveEnabled': 'Enregistrement automatique des fichiers',
'settings.openchamber.visual.field.autoSaveEnabledInfo': 'Enregistre automatiquement les modifications après larrêt de la saisie. Désactivez pour exiger un enregistrement manuel.',
@@ -2041,8 +2041,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': 'ユーザーヘッダー固定',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': 'プロンプトナビゲーター',
'settings.openchamber.visual.field.promptNavigatorEnabled': 'プロンプトナビゲーター',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'エディターツールバーを常に表示',
'settings.openchamber.visual.field.expandedEditorToolbar': 'エディターツールバーを常に表示(ファイルタブの下にドッキング)',
'settings.openchamber.visual.field.autoSaveEnabledAria': 'ファイルの自動保存',
'settings.openchamber.visual.field.autoSaveEnabled': 'ファイルの自動保存',
'settings.openchamber.visual.field.autoSaveEnabledInfo': '入力を止めた後にファイルの編集内容を自動保存します。無効にすると手動保存が必要になります。',
@@ -2008,8 +2008,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': '고정 사용자 헤더',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': '프롬프트 탐색기',
'settings.openchamber.visual.field.promptNavigatorEnabled': '프롬프트 탐색기',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Always show editor toolbar',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Always show editor toolbar (docked under the file tabs)',
'settings.openchamber.visual.field.autoSaveEnabledAria': '파일 자동 저장',
'settings.openchamber.visual.field.autoSaveEnabled': '파일 자동 저장',
'settings.openchamber.visual.field.autoSaveEnabledInfo': '입력을 멈춘 후 파일 편집 내용을 자동으로 저장합니다. 끄면 수동으로 저장해야 합니다.',
@@ -1111,8 +1111,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeaderAria': 'Przyklejony nagłówek użytkownika',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': 'Nawigator promptów',
'settings.openchamber.visual.field.promptNavigatorEnabled': 'Nawigator promptów',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Always show editor toolbar',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Always show editor toolbar (docked under the file tabs)',
'settings.openchamber.visual.field.autoSaveEnabledAria': 'Autozapis plików',
'settings.openchamber.visual.field.autoSaveEnabled': 'Autozapis plików',
'settings.openchamber.visual.field.autoSaveEnabledInfo': 'Automatycznie zapisuje edycje pliku po zatrzymaniu pisania. Wyłącz, aby wymagać ręcznego zapisu.',
@@ -2008,8 +2008,6 @@ export const settingsDict = {
"settings.openchamber.visual.field.stickyUserHeader": "Cabeçalho do usuário fixo",
"settings.openchamber.visual.field.promptNavigatorEnabledAria": "Navegador de prompts",
"settings.openchamber.visual.field.promptNavigatorEnabled": "Navegador de prompts",
"settings.openchamber.visual.field.expandedEditorToolbarAria": "Mostrar sempre a barra de ferramentas do editor",
"settings.openchamber.visual.field.expandedEditorToolbar": "Mostrar sempre a barra de ferramentas do editor (ancorada sob as abas)",
"settings.openchamber.visual.field.autoSaveEnabledAria": "Salvamento automático de arquivos",
"settings.openchamber.visual.field.autoSaveEnabled": "Salvamento automático de arquivos",
"settings.openchamber.visual.field.autoSaveEnabledInfo": "Salva automaticamente as edições do arquivo depois que você parar de digitar. Desative para exigir salvamento manual.",
@@ -2008,8 +2008,6 @@ export const settingsDict = {
"settings.openchamber.visual.field.stickyUserHeader": "Закріплений заголовок користувача",
"settings.openchamber.visual.field.promptNavigatorEnabledAria": "Навігатор промптів",
"settings.openchamber.visual.field.promptNavigatorEnabled": "Навігатор промптів",
"settings.openchamber.visual.field.expandedEditorToolbarAria": "Завжди показувати панель інструментів редактора",
"settings.openchamber.visual.field.expandedEditorToolbar": "Завжди показувати панель інструментів редактора (закріплена під вкладками)",
"settings.openchamber.visual.field.autoSaveEnabledAria": "Автозбереження файлів",
"settings.openchamber.visual.field.autoSaveEnabled": "Автозбереження файлів",
"settings.openchamber.visual.field.autoSaveEnabledInfo": "Автоматично зберігати зміни у файлі після того, як ви припините друкувати. Вимкніть, щоб зберігати лише вручну.",
@@ -2008,8 +2008,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': '固定用户消息头',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': '提示词导航',
'settings.openchamber.visual.field.promptNavigatorEnabled': '提示词导航',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Always show editor toolbar',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Always show editor toolbar (docked under the file tabs)',
'settings.openchamber.visual.field.autoSaveEnabledAria': '自动保存文件',
'settings.openchamber.visual.field.autoSaveEnabled': '自动保存文件',
'settings.openchamber.visual.field.autoSaveEnabledInfo': '停止输入后自动保存文件编辑内容。关闭后需手动保存。',
@@ -1915,8 +1915,6 @@ export const settingsDict = {
'settings.openchamber.visual.field.stickyUserHeader': '固定使用者訊息標頭',
'settings.openchamber.visual.field.promptNavigatorEnabledAria': '提示詞導覽',
'settings.openchamber.visual.field.promptNavigatorEnabled': '提示詞導覽',
'settings.openchamber.visual.field.expandedEditorToolbarAria': 'Always show editor toolbar',
'settings.openchamber.visual.field.expandedEditorToolbar': 'Always show editor toolbar (docked under the file tabs)',
'settings.openchamber.visual.field.autoSaveEnabledAria': '自動儲存檔案',
'settings.openchamber.visual.field.autoSaveEnabled': '自動儲存檔案',
'settings.openchamber.visual.field.autoSaveEnabledInfo': '停止輸入後自動儲存檔案編輯內容。關閉後需手動儲存。',
-7
View File
@@ -578,7 +578,6 @@ const materializeAuthoritativeUiSettings = (settings: DesktopSettings): DesktopS
messageStreamTransport: 'auto',
stickyUserHeader: defaults.stickyUserHeader,
promptNavigatorEnabled: defaults.promptNavigatorEnabled,
expandedEditorToolbar: defaults.expandedEditorToolbar,
wideChatLayoutEnabled: defaults.wideChatLayoutEnabled,
showSplitAssistantMessageActions: defaults.showSplitAssistantMessageActions,
draftStartersVisible: defaults.draftStartersVisible,
@@ -842,9 +841,6 @@ const applyDesktopUiPreferences = (settings: DesktopSettings) => {
if (typeof settings.promptNavigatorEnabled === 'boolean' && settings.promptNavigatorEnabled !== store.promptNavigatorEnabled) {
store.setPromptNavigatorEnabled(settings.promptNavigatorEnabled);
}
if (typeof settings.expandedEditorToolbar === 'boolean' && settings.expandedEditorToolbar !== store.expandedEditorToolbar) {
store.setExpandedEditorToolbar(settings.expandedEditorToolbar);
}
if (typeof settings.wideChatLayoutEnabled === 'boolean' && settings.wideChatLayoutEnabled !== store.wideChatLayoutEnabled) {
store.setWideChatLayoutEnabled(settings.wideChatLayoutEnabled);
}
@@ -1511,9 +1507,6 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
if (typeof candidate.promptNavigatorEnabled === 'boolean') {
result.promptNavigatorEnabled = candidate.promptNavigatorEnabled;
}
if (typeof candidate.expandedEditorToolbar === 'boolean') {
result.expandedEditorToolbar = candidate.expandedEditorToolbar;
}
if (typeof candidate.wideChatLayoutEnabled === 'boolean') {
result.wideChatLayoutEnabled = candidate.wideChatLayoutEnabled;
}
-7
View File
@@ -148,13 +148,6 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
descriptionKey: 'settings.openchamber.visual.field.autoSaveEnabledInfo',
keywords: ['editor', 'autosave', 'auto-save', 'files', 'save'],
},
{
id: 'appearance.expanded-editor-toolbar',
page: 'general',
titleKey: 'settings.openchamber.visual.field.expandedEditorToolbar',
keywords: ['editor', 'toolbar', 'tabs', 'docked', 'files'],
isAvailable: (ctx) => !ctx.isVSCode,
},
{
id: 'appearance.file-editor-keymap',
page: 'general',
+6 -8
View File
@@ -787,7 +787,6 @@ interface UIStore {
collapsibleUserMessages: boolean;
stickyUserHeader: boolean;
promptNavigatorEnabled: boolean;
expandedEditorToolbar: boolean;
showSplitAssistantMessageActions: boolean;
allowPromptingSubagentSessions: boolean;
isExpandedInput: boolean;
@@ -960,7 +959,6 @@ interface UIStore {
setCollapsibleUserMessages: (value: boolean) => void;
setStickyUserHeader: (value: boolean) => void;
setPromptNavigatorEnabled: (value: boolean) => void;
setExpandedEditorToolbar: (value: boolean) => void;
setShowSplitAssistantMessageActions: (value: boolean) => void;
setAllowPromptingSubagentSessions: (value: boolean) => void;
viewPagerPage: 'left' | 'center' | 'right';
@@ -1121,7 +1119,6 @@ export const useUIStore = create<UIStore>()(
collapsibleUserMessages: true,
stickyUserHeader: false,
promptNavigatorEnabled: true,
expandedEditorToolbar: false,
showSplitAssistantMessageActions: false,
allowPromptingSubagentSessions: false,
draftStartersVisible: true,
@@ -2357,9 +2354,6 @@ export const useUIStore = create<UIStore>()(
setPromptNavigatorEnabled: (value) => {
set({ promptNavigatorEnabled: value });
},
setExpandedEditorToolbar: (value: boolean) => {
set({ expandedEditorToolbar: value });
},
setShowSplitAssistantMessageActions: (value) => {
set({ showSplitAssistantMessageActions: value });
},
@@ -2411,7 +2405,7 @@ export const useUIStore = create<UIStore>()(
{
name: 'ui-store',
storage: createDeferredSafeJSONStorage(),
version: 16,
version: 17,
migrate: (persistedState, version) => {
if (!persistedState || typeof persistedState !== 'object') {
return persistedState;
@@ -2427,6 +2421,11 @@ export const useUIStore = create<UIStore>()(
delete state.activeSurface;
}
// v16 -> v17: the editor toolbar is always docked; the preference is gone.
if (version < 17) {
delete state.expandedEditorToolbar;
}
// v13 -> v14: the separate 'preview' surface merged into 'browser'.
// Stored preview tabs keep their URL and become browser tabs; their
// id encodes the mode, so it is rebuilt rather than left dangling.
@@ -2714,7 +2713,6 @@ export const useUIStore = create<UIStore>()(
collapsibleUserMessages: state.collapsibleUserMessages,
stickyUserHeader: state.stickyUserHeader,
promptNavigatorEnabled: state.promptNavigatorEnabled,
expandedEditorToolbar: state.expandedEditorToolbar,
showSplitAssistantMessageActions: state.showSplitAssistantMessageActions,
allowPromptingSubagentSessions: state.allowPromptingSubagentSessions,
draftStartersVisible: state.draftStartersVisible,