import React from 'react'; import { OpenChamberVisualSettings } from './OpenChamberVisualSettings'; import { AboutSettings } from './AboutSettings'; import { SessionRetentionSettings } from './SessionRetentionSettings'; import { PasskeySettings } from './PasskeySettings'; import { AppLinkSecuritySettings } from './AppLinkSecuritySettings'; import { DefaultsSettings } from './DefaultsSettings'; import { GitSettings } from './GitSettings'; import { NotificationSettings } from './NotificationSettings'; import { VoiceSettings } from './VoiceSettings'; import { TunnelSettings } from './TunnelSettings'; import { OpenCodeCliSettings } from './OpenCodeCliSettings'; import { OpenChamberToolsSettings } from './OpenChamberToolsSettings'; import { DesktopNetworkSettings } from './DesktopNetworkSettings'; import { KeyboardShortcutsSettings } from './KeyboardShortcutsSettings'; import { SettingsPageLayout } from '@/components/sections/shared/SettingsPageLayout'; import { useDeviceInfo } from '@/lib/device'; import { isDesktopLocalOriginActive, isDesktopShell, isVSCodeRuntime, isWebRuntime } from '@/lib/desktop'; import { isCapacitorApp } from '@/lib/platform'; import { useI18n } from '@/lib/i18n'; import { subscribeRuntimeEndpointChanged } from '@/lib/runtime-switch'; import type { OpenChamberSection } from './types'; const useRuntimeEndpointEpoch = (): number => { const [epoch, setEpoch] = React.useState(0); React.useEffect(() => { return subscribeRuntimeEndpointChanged(() => setEpoch((current) => current + 1)); }, []); return epoch; }; interface OpenChamberPageProps { /** Which section to display. If undefined, shows all sections (mobile/legacy behavior) */ section?: OpenChamberSection; } export const OpenChamberPage: React.FC = ({ section }) => { const { t } = useI18n(); const { isMobile } = useDeviceInfo(); const runtimeEndpointEpoch = useRuntimeEndpointEpoch(); const showAbout = isMobile && isWebRuntime(); const isVSCode = isVSCodeRuntime(); void runtimeEndpointEpoch; const showDesktopNetworkSettings = isDesktopShell() && isDesktopLocalOriginActive(); // If no section specified, show all (mobile/legacy behavior) if (!section) { return ( {showDesktopNetworkSettings && } {!isVSCode && } {!isVSCode && } {isWebRuntime() && !isDesktopShell() && !isVSCode && !isCapacitorApp() && } {showAbout && } ); } // Show specific section content const renderSectionContent = () => { switch (section) { case 'general': return ; case 'visual': return ; case 'chat': return ; case 'sessions': return ; case 'shortcuts': return ; case 'git': return ; case 'notifications': return ; case 'voice': return ; case 'tunnel': return ; default: return null; } }; const pageTitle = { general: t('settings.page.general.title'), visual: t('settings.page.appearance.title'), chat: t('settings.page.chat.title'), sessions: t('settings.page.sessions.title'), shortcuts: t('settings.page.shortcuts.title'), git: t('settings.page.git.title'), github: t('settings.page.git.title'), notifications: t('settings.page.notifications.title'), voice: t('settings.page.voice.title'), tunnel: t('settings.page.tunnel.title'), }[section]; const pageDescription = { general: t('settings.page.general.description'), visual: t('settings.page.appearance.description'), chat: t('settings.page.chat.description'), sessions: t('settings.page.sessions.description'), shortcuts: t('settings.page.shortcuts.description'), git: undefined, github: undefined, notifications: t('settings.page.notifications.description'), voice: t('settings.page.voice.description'), tunnel: t('settings.page.tunnel.description'), }[section]; return ( {renderSectionContent()} ); }; const ShortcutsSectionContent: React.FC = () => { return ; }; // General section: app-level settings — startup/tray/network, access password, // passkeys, OpenCode CLI binary, message stream transport, privacy. const GeneralSectionContent: React.FC = () => { const isVSCode = isVSCodeRuntime(); const runtimeEndpointEpoch = useRuntimeEndpointEpoch(); void runtimeEndpointEpoch; const showDesktopNetworkSettings = isDesktopShell() && isDesktopLocalOriginActive(); // Passkeys only work against the browser's WebAuthn UI on the web surface — // desktop shell, VS Code, and the Capacitor app never show the login screen. const showPasskeySettings = isWebRuntime() && !isDesktopShell() && !isVSCode && !isCapacitorApp(); return ( <> {showDesktopNetworkSettings && } {showPasskeySettings && } {!isVSCode && } {!isVSCode && } ); }; // Visual section: Theme Mode, Font Size, Spacing, Input Bar Offset (mobile), Nav Rail const VisualSectionContent: React.FC = () => { const isVSCode = isVSCodeRuntime(); return ; }; // Chat section: User message rendering, Diff layout, Mobile status bar, Show reasoning traces, Follow-up behavior, Persist draft const ChatSectionContent: React.FC = () => { const isVSCode = isVSCodeRuntime(); return ( ); }; // Sessions section: Default model & agent, Session retention const SessionsSectionContent: React.FC = () => { return ( <> ); }; // Git section: Commit message model, Worktree settings const GitSectionContent: React.FC = () => { return ; }; // Notifications section: Native browser notifications const NotificationSectionContent: React.FC = () => { return ; }; // Voice section: Language selection and continuous mode const VoiceSectionContent: React.FC = () => { if (isVSCodeRuntime()) { return null; } return ; }; const TunnelSectionContent: React.FC = () => { if (isVSCodeRuntime()) { return null; } return ; };