import { useState, useEffect } from 'react' import type { DesktopSettings } from '../types/ipc' import { useLanguage } from '../contexts/LanguageContext' import { translate, type LangPreference } from '../locales' interface SettingsModalProps { onClose: () => void } type Section = 'general' | 'startup' function requiresAppRestart(previous: DesktopSettings, next: DesktopSettings): boolean { return previous.apiHome !== next.apiHome || previous.oauthApp !== next.oauthApp || previous.enterpriseUrl !== next.enterpriseUrl } function Toggle({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) { return ( ) } function SettingRow({ label, description, children }: { label: string; description?: string; children: React.ReactNode }) { return (
{label}
{description &&
{description}
}
{children}
) } const IconGeneral = () => ( ) const IconStartup = () => ( ) export default function SettingsModal({ onClose }: SettingsModalProps) { const { t, setLangPref } = useLanguage() const [section, setSection] = useState
('general') const [settings, setSettings] = useState({ apiHome: '', oauthApp: 'default', enterpriseUrl: '', lastPort: 4141, minimizeToTray: false, accountType: 'individual', verbose: false, showToken: false, language: 'auto', }) const [initialSettings, setInitialSettings] = useState(null) const [saving, setSaving] = useState(false) useEffect(() => { window.electronAPI.getSettings().then((loadedSettings) => { setSettings(loadedSettings) setInitialSettings(loadedSettings) }) }, []) const handleSave = async () => { const shouldPromptRestart = initialSettings !== null && requiresAppRestart(initialSettings, settings) setSaving(true) try { await window.electronAPI.saveSettings(settings) setLangPref(settings.language) if (shouldPromptRestart) { window.alert(translate('settings.restartAppPrompt', settings.language, undefined, navigator.language)) } onClose() } finally { setSaving(false) } } const langOptions: { value: LangPreference; label: string }[] = [ { value: 'auto', label: t('settings.langAuto') }, { value: 'en', label: t('settings.langEn') }, { value: 'zh', label: t('settings.langZh') }, ] const navItems: { key: Section; label: string; icon: React.ReactNode }[] = [ { key: 'general', label: t('settings.sectionGeneral'), icon: }, { key: 'startup', label: t('settings.sectionStartup'), icon: }, ] return (
{/* Title bar */}
{t('settings.title')}
{/* Main content */}
{/* Left navigation */}
{navItems.map(item => ( ))}
{/* Right panel */}
{section === 'general' && (
{t('settings.sectionLanguage')}
setSettings(s => ({ ...s, minimizeToTray: v }))} />
)} {section === 'startup' && (
{t('settings.restartAppNote')}
{t('settings.oauthApp')}

{t('settings.oauthAppDesc')}

{t('settings.apiHome')}
setSettings(s => ({ ...s, apiHome: e.target.value }))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-[13px] bg-slate-50 text-[#0f172a] placeholder-slate-300 focus:outline-none focus:ring-2 focus:ring-slate-300 focus:bg-white transition-colors" />

{t('settings.apiHomeDesc')}

{t('settings.enterpriseUrl')}
setSettings(s => ({ ...s, enterpriseUrl: e.target.value }))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-[13px] bg-slate-50 text-[#0f172a] placeholder-slate-300 focus:outline-none focus:ring-2 focus:ring-slate-300 focus:bg-white transition-colors" />

{t('settings.enterpriseUrlDesc')}

setSettings(s => ({ ...s, verbose: v }))} /> setSettings(s => ({ ...s, showToken: v }))} />
)}
{/* Footer actions */}
) }