fix: move file preview setting to chat settings
Moved file preview mode toggle next to Show Dotfiles Saved checkbox changes through settings config Applied preview mode changes to open editor tabs immediately
This commit is contained in:
@@ -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 = () => {
|
||||
<span className="typography-ui-label text-foreground">{t('settings.openchamber.defaults.field.showDeletionDialog')}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="group flex cursor-pointer items-center gap-2 py-1"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-pressed={settingsDefaultFileViewerPreview}
|
||||
onClick={handleToggleFileViewerPreview}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === ' ' || event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
handleToggleFileViewerPreview();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Checkbox checked={settingsDefaultFileViewerPreview} onChange={setSettingsDefaultFileViewerPreview} ariaLabel={t('settings.openchamber.defaults.field.openFilesPreviewAria')} />
|
||||
<span className="typography-ui-label text-foreground">{t('settings.openchamber.defaults.field.openFilesPreview')}</span>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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 <OpenChamberVisualSettings visibleSettings={['chatRenderMode', 'messageTransport', 'activityRenderMode', 'userMessageRendering', 'mermaidRendering', 'reasoning', 'showToolFileIcons', 'expandedTools', 'stickyUserHeader', 'wideChatLayout', 'splitAssistantMessageActions', 'diffLayout', 'mobileStatusBar', 'dotfiles', 'queueMode', 'persistDraft', 'inputSpellcheck']} />;
|
||||
return <OpenChamberVisualSettings visibleSettings={['chatRenderMode', 'messageTransport', 'activityRenderMode', 'userMessageRendering', 'mermaidRendering', 'reasoning', 'showToolFileIcons', 'expandedTools', 'stickyUserHeader', 'wideChatLayout', 'splitAssistantMessageActions', 'diffLayout', 'mobileStatusBar', 'dotfiles', 'fileViewerPreview', 'queueMode', 'persistDraft', 'inputSpellcheck']} />;
|
||||
};
|
||||
|
||||
// Sessions section: Default model & agent, Session retention
|
||||
|
||||
@@ -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<OpenChamberVisualSettingsProps>
|
||||
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<OpenChamberVisualSettingsProps>
|
||||
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<OpenChamberVisualSettingsProps>
|
||||
|| shouldShow('diffLayout')
|
||||
|| (shouldShow('mobileStatusBar') && isMobile)
|
||||
|| shouldShow('dotfiles')
|
||||
|| shouldShow('fileViewerPreview')
|
||||
|| shouldShow('reasoning')
|
||||
|| shouldShow('queueMode')
|
||||
|| shouldShow('persistDraft')
|
||||
@@ -1578,7 +1587,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(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')) && (
|
||||
<section className="p-2 space-y-0.5">
|
||||
{shouldShow('reasoning') && (
|
||||
<div
|
||||
@@ -1774,6 +1783,31 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldShow('fileViewerPreview') && (
|
||||
<div
|
||||
className="group flex cursor-pointer items-center gap-2 py-0.5"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-pressed={settingsDefaultFileViewerPreview}
|
||||
onClick={() => handleFileViewerPreviewChange(!settingsDefaultFileViewerPreview)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === ' ' || event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
handleFileViewerPreviewChange(!settingsDefaultFileViewerPreview);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span onClick={(event) => event.stopPropagation()}>
|
||||
<Checkbox
|
||||
checked={settingsDefaultFileViewerPreview}
|
||||
onChange={handleFileViewerPreviewChange}
|
||||
ariaLabel={t('settings.openchamber.defaults.field.openFilesPreviewAria')}
|
||||
/>
|
||||
</span>
|
||||
<span className="typography-ui-label text-foreground">{t('settings.openchamber.defaults.field.openFilesPreview')}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldShow('queueMode') && (
|
||||
<div
|
||||
className="group flex cursor-pointer items-center gap-2 py-0.5"
|
||||
|
||||
@@ -2258,6 +2258,48 @@ export const FilesView: React.FC<FilesViewProps> = ({ 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;
|
||||
|
||||
Reference in New Issue
Block a user