diff --git a/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx b/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx
index 1d60f005..92334d62 100644
--- a/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx
+++ b/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx
@@ -32,8 +32,6 @@ export const DefaultsSettings: React.FC = () => {
const setSettingsDefaultModel = useConfigStore((state) => state.setSettingsDefaultModel);
const setSettingsDefaultVariant = useConfigStore((state) => state.setSettingsDefaultVariant);
const setSettingsDefaultAgent = useConfigStore((state) => state.setSettingsDefaultAgent);
- const setSettingsDefaultFileViewerPreview = useConfigStore((state) => state.setSettingsDefaultFileViewerPreview);
- const settingsDefaultFileViewerPreview = useConfigStore((state) => state.settingsDefaultFileViewerPreview);
const showDeletionDialog = useUIStore((state) => state.showDeletionDialog);
const setShowDeletionDialog = useUIStore((state) => state.setShowDeletionDialog);
const providers = useConfigStore((state) => state.providers);
@@ -191,12 +189,6 @@ export const DefaultsSettings: React.FC = () => {
[setAgent, setSettingsDefaultAgent]
);
- const handleToggleFileViewerPreview = React.useCallback(() => {
- const next = !settingsDefaultFileViewerPreview;
- setSettingsDefaultFileViewerPreview(next);
- updateDesktopSettings({ defaultFileViewerPreview: next }).catch(console.warn);
- }, [settingsDefaultFileViewerPreview, setSettingsDefaultFileViewerPreview]);
-
const availableVariants = React.useMemo(() => {
if (!parsedModel.providerId || !parsedModel.modelId) return [];
const provider = providers.find((p) => p.id === parsedModel.providerId);
@@ -311,23 +303,6 @@ export const DefaultsSettings: React.FC = () => {
{t('settings.openchamber.defaults.field.showDeletionDialog')}
-
{
- if (event.key === ' ' || event.key === 'Enter') {
- event.preventDefault();
- handleToggleFileViewerPreview();
- }
- }}
- >
-
- {t('settings.openchamber.defaults.field.openFilesPreview')}
-
-
);
diff --git a/packages/ui/src/components/sections/openchamber/OpenChamberPage.tsx b/packages/ui/src/components/sections/openchamber/OpenChamberPage.tsx
index f1a64b0f..7e998f5f 100644
--- a/packages/ui/src/components/sections/openchamber/OpenChamberPage.tsx
+++ b/packages/ui/src/components/sections/openchamber/OpenChamberPage.tsx
@@ -142,7 +142,7 @@ const VisualSectionContent: React.FC = () => {
// Chat section: User message rendering, Diff layout, Mobile status bar, Show reasoning traces, Queue mode, Persist draft
const ChatSectionContent: React.FC = () => {
- return ;
+ return ;
};
// Sessions section: Default model & agent, Session retention
diff --git a/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx b/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx
index f9df4f25..07777071 100644
--- a/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx
+++ b/packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx
@@ -247,7 +247,7 @@ const normalizeUserMessageRenderingMode = (mode: unknown): 'markdown' | 'plain'
return mode === 'markdown' ? 'markdown' : 'plain';
};
-export type VisibleSetting = 'theme' | 'pwaInstallName' | 'pwaOrientation' | 'mobileKeyboardMode' | 'timeFormat' | 'weekStart' | 'fontSize' | 'terminalFontSize' | 'spacing' | 'inputBarOffset' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'messageTransport' | 'activityRenderMode' | 'stickyUserHeader' | 'wideChatLayout' | 'splitAssistantMessageActions' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'reasoning' | 'showToolFileIcons' | 'expandedTools' | 'queueMode' | 'terminalQuickKeys' | 'persistDraft' | 'inputSpellcheck' | 'reportUsage';
+export type VisibleSetting = 'theme' | 'pwaInstallName' | 'pwaOrientation' | 'mobileKeyboardMode' | 'timeFormat' | 'weekStart' | 'fontSize' | 'terminalFontSize' | 'spacing' | 'inputBarOffset' | 'mermaidRendering' | 'userMessageRendering' | 'chatRenderMode' | 'messageTransport' | 'activityRenderMode' | 'stickyUserHeader' | 'wideChatLayout' | 'splitAssistantMessageActions' | 'diffLayout' | 'mobileStatusBar' | 'dotfiles' | 'fileViewerPreview' | 'reasoning' | 'showToolFileIcons' | 'expandedTools' | 'queueMode' | 'terminalQuickKeys' | 'persistDraft' | 'inputSpellcheck' | 'reportUsage';
interface OpenChamberVisualSettingsProps {
/** Which settings to show. If undefined, shows all. */
@@ -319,6 +319,8 @@ export const OpenChamberVisualSettings: React.FC
const setShowMobileSessionStatusBar = useUIStore(state => state.setShowMobileSessionStatusBar);
const messageStreamTransport = useConfigStore((state) => state.settingsMessageStreamTransport);
const setMessageStreamTransport = useConfigStore((state) => state.setSettingsMessageStreamTransport);
+ const settingsDefaultFileViewerPreview = useConfigStore((state) => state.settingsDefaultFileViewerPreview);
+ const setSettingsDefaultFileViewerPreview = useConfigStore((state) => state.setSettingsDefaultFileViewerPreview);
const isSettingsDialogOpen = useUIStore(state => state.isSettingsDialogOpen);
const {
themeMode,
@@ -439,6 +441,12 @@ export const OpenChamberVisualSettings: React.FC
void updateDesktopSettings({ showToolFileIcons: enabled });
}, [setShowToolFileIcons]);
+ const handleFileViewerPreviewChange = React.useCallback((enabled: boolean) => {
+ setSettingsDefaultFileViewerPreview(enabled);
+ void updateDesktopSettings({ defaultFileViewerPreview: enabled });
+ window.dispatchEvent(new CustomEvent('openchamber:file-viewer-preview-mode-changed', { detail: { enabled } }));
+ }, [setSettingsDefaultFileViewerPreview]);
+
const handleShowExpandedBashToolsChange = React.useCallback((enabled: boolean) => {
setShowExpandedBashTools(enabled);
void updateDesktopSettings({ showExpandedBashTools: enabled });
@@ -513,6 +521,7 @@ export const OpenChamberVisualSettings: React.FC
|| shouldShow('diffLayout')
|| (shouldShow('mobileStatusBar') && isMobile)
|| shouldShow('dotfiles')
+ || shouldShow('fileViewerPreview')
|| shouldShow('reasoning')
|| shouldShow('queueMode')
|| shouldShow('persistDraft')
@@ -1578,7 +1587,7 @@ export const OpenChamberVisualSettings: React.FC
)}
- {(shouldShow('stickyUserHeader') || shouldShow('wideChatLayout') || shouldShow('splitAssistantMessageActions') || (shouldShow('mobileStatusBar') && isMobile) || shouldShow('dotfiles') || shouldShow('queueMode') || shouldShow('persistDraft') || shouldShow('showToolFileIcons') || (!isMobile && shouldShow('inputSpellcheck')) || shouldShow('reasoning')) && (
+ {(shouldShow('stickyUserHeader') || shouldShow('wideChatLayout') || shouldShow('splitAssistantMessageActions') || (shouldShow('mobileStatusBar') && isMobile) || shouldShow('dotfiles') || shouldShow('fileViewerPreview') || shouldShow('queueMode') || shouldShow('persistDraft') || shouldShow('showToolFileIcons') || (!isMobile && shouldShow('inputSpellcheck')) || shouldShow('reasoning')) && (
{shouldShow('reasoning') && (
)}
+ {shouldShow('fileViewerPreview') && (
+ handleFileViewerPreviewChange(!settingsDefaultFileViewerPreview)}
+ onKeyDown={(event) => {
+ if (event.key === ' ' || event.key === 'Enter') {
+ event.preventDefault();
+ handleFileViewerPreviewChange(!settingsDefaultFileViewerPreview);
+ }
+ }}
+ >
+ event.stopPropagation()}>
+
+
+ {t('settings.openchamber.defaults.field.openFilesPreview')}
+
+ )}
+
{shouldShow('queueMode') && (
= ({ mode = 'full' }) => {
const getHtmlViewMode = React.useCallback((): PreviewViewMode => {
return htmlViewMode;
}, [htmlViewMode]);
+
+ React.useEffect(() => {
+ const applyDefaultFileViewerMode = (enabled: boolean) => {
+ const textMode: TextViewMode = enabled ? 'view' : 'edit';
+ const previewMode: PreviewViewMode = enabled ? 'preview' : 'edit';
+ const nextJsonMode: 'tree' | 'text' = enabled ? 'tree' : 'text';
+
+ for (const path of openPaths) {
+ textViewModeByPathRef.current[path] = textMode;
+ if (isMarkdownFile(path)) {
+ mdViewModeByPathRef.current[path] = previewMode;
+ }
+ if (isHtmlFile(path)) {
+ htmlViewModeByPathRef.current[path] = previewMode;
+ }
+ }
+
+ setTextViewMode(textMode);
+ setMdViewMode(previewMode);
+ setHtmlViewMode(previewMode);
+ setJsonViewMode(nextJsonMode);
+
+ try {
+ localStorage.setItem(MD_VIEWER_MODE_KEY, previewMode);
+ localStorage.setItem(HTML_VIEWER_MODE_KEY, previewMode);
+ localStorage.setItem(JSON_VIEWER_MODE_KEY, nextJsonMode);
+ } catch {
+ // Ignore localStorage errors
+ }
+ };
+
+ const handleFileViewerModeChanged = (event: Event) => {
+ const enabled = Boolean((event as CustomEvent<{ enabled?: boolean }>).detail?.enabled);
+ applyDefaultFileViewerMode(enabled);
+ };
+
+ window.addEventListener('openchamber:file-viewer-preview-mode-changed', handleFileViewerModeChanged);
+ return () => {
+ window.removeEventListener('openchamber:file-viewer-preview-mode-changed', handleFileViewerModeChanged);
+ };
+ }, [openPaths]);
+
React.useEffect(() => {
if (!pendingFileNavigation || !root) {
return;