import { ScrollArea } from '../ui/scroll-area'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; import { View, ViewOptions } from '../../utils/navigationUtils'; import ModelsSection from './models/ModelsSection'; import SessionSharingSection from './sessions/SessionSharingSection'; import ExternalBackendSection from './app/ExternalBackendSection'; import AppSettingsSection from './app/AppSettingsSection'; import ConfigSettings from './config/ConfigSettings'; import PromptsSettingsSection from './PromptsSettingsSection'; import { ExtensionConfig } from '../../api'; import { MainPanelLayout } from '../Layout/MainPanelLayout'; import { Bot, Share2, Monitor, MessageSquare, FileText, Keyboard, HardDrive, Network, KeyRound, } from 'lucide-react'; import { useState, useEffect, useRef } from 'react'; import TunnelSection from './tunnel/TunnelSection'; import GatewaySettingsSection from './gateways/GatewaySettingsSection'; import { getTunnelStatus } from '../../api/sdk.gen'; import ChatSettingsSection from './chat/ChatSettingsSection'; import KeyboardShortcutsSection from './keyboard/KeyboardShortcutsSection'; import AuthSettingsSection from './auth/AuthSettingsSection'; import LocalInferenceSection from './localInference/LocalInferenceSection'; import MeshSection from './mesh/MeshSection'; import { CONFIGURATION_ENABLED } from '../../updates'; import { trackSettingsTabViewed } from '../../utils/analytics'; import { useFeatures } from '../../contexts/FeaturesContext'; import { defineMessages, useIntl } from '../../i18n'; const i18n = defineMessages({ title: { id: 'settingsView.title', defaultMessage: 'Settings', }, tabModels: { id: 'settingsView.tabModels', defaultMessage: 'Models', }, tabLocalInference: { id: 'settingsView.tabLocalInference', defaultMessage: 'Local Inference', }, tabChat: { id: 'settingsView.tabChat', defaultMessage: 'Chat', }, tabSession: { id: 'settingsView.tabSession', defaultMessage: 'Session', }, tabPrompts: { id: 'settingsView.tabPrompts', defaultMessage: 'Prompts', }, tabKeyboard: { id: 'settingsView.tabKeyboard', defaultMessage: 'Keyboard', }, tabAuth: { id: 'settingsView.tabAuth', defaultMessage: 'Auth', }, tabApp: { id: 'settingsView.tabApp', defaultMessage: 'App', }, }); export type SettingsViewOptions = { deepLinkConfig?: ExtensionConfig; showEnvVars?: boolean; section?: string; sessionId?: string; }; export default function SettingsView({ onClose, setView, viewOptions, }: { onClose: () => void; setView: (view: View, viewOptions?: ViewOptions) => void; viewOptions: SettingsViewOptions; }) { const [activeTab, setActiveTab] = useState('models'); const [tunnelDisabled, setTunnelDisabled] = useState(false); const hasTrackedInitialTab = useRef(false); const { localInference } = useFeatures(); const intl = useIntl(); const handleTabChange = (tab: string) => { setActiveTab(tab); trackSettingsTabViewed(tab); }; // Determine initial tab based on section prop useEffect(() => { if (viewOptions.section) { // Map section names to tab values const sectionToTab: Record = { update: 'app', models: 'models', modes: 'chat', sharing: 'sharing', styles: 'chat', tools: 'chat', app: 'app', chat: 'chat', prompts: 'prompts', keyboard: 'keyboard', auth: 'auth', gateway: 'sharing', 'local-inference': 'local-inference', mesh: 'mesh', }; const targetTab = sectionToTab[viewOptions.section]; if ( targetTab && (targetTab !== 'local-inference' || localInference) && (targetTab !== 'mesh' || !tunnelDisabled) ) { setActiveTab(targetTab); } } }, [viewOptions.section, localInference, tunnelDisabled]); // Reset active tab if local-inference or mesh becomes unavailable useEffect(() => { if (!localInference && activeTab === 'local-inference') { setActiveTab('models'); } if (tunnelDisabled && activeTab === 'mesh') { setActiveTab('models'); } }, [localInference, tunnelDisabled, activeTab]); useEffect(() => { if (!hasTrackedInitialTab.current) { trackSettingsTabViewed(activeTab); hasTrackedInitialTab.current = true; } }, [activeTab]); useEffect(() => { getTunnelStatus() .then(({ data }) => { setTunnelDisabled(data?.state === 'disabled'); }) .catch(() => { setTunnelDisabled(false); }); }, []); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape' && !event.defaultPrevented) { onClose(); } }; document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [onClose]); return ( <>

{intl.formatMessage(i18n.title)}

{intl.formatMessage(i18n.tabModels)} {localInference && ( {intl.formatMessage(i18n.tabLocalInference)} )} {!tunnelDisabled && ( Mesh )} {intl.formatMessage(i18n.tabChat)} {intl.formatMessage(i18n.tabSession)} {intl.formatMessage(i18n.tabPrompts)} {intl.formatMessage(i18n.tabKeyboard)} {intl.formatMessage(i18n.tabAuth)} {intl.formatMessage(i18n.tabApp)}
{localInference && ( )} {!tunnelDisabled && ( )}
{!tunnelDisabled && (
)}
{CONFIGURATION_ENABLED && }
); }