import { useContext, useEffect, useMemo, useState } from 'react' import { Descriptions, Flex, Select, Space, Spin, Typography } from 'antd' import { LoadingOutlined, SettingOutlined } from '@ant-design/icons' import { useThemeContext } from '../context/ThemeContext' import { ApiServerContext } from '../context/ApiServerContext' import { ElectronContext } from '../context/ElectronContext' import { AuthContext } from '../context/AuthContext' import { useMessageContext } from '../context/MessageContext' import useCollapseState from '../hooks/useCollapseState' import InfoCollapse from '../common/InfoCollapse' import ViewButton from '../common/ViewButton' import EditButtons from '../common/EditButtons' const { Text } = Typography const { Option } = Select const DEFAULT_UPDATE_BRANCH = 'main' const Settings = () => { const { isDarkMode, isCompact, isSystem, setThemeMode, setDensityMode } = useThemeContext() const { fetchAppUpdateBranches } = useContext(ApiServerContext) const { isElectron, getAppSettings, setAppSettings } = useContext(ElectronContext) const { userProfile, setUserProfile } = useContext(AuthContext) const { showSuccess, showError } = useMessageContext() const [collapseState, updateCollapseState] = useCollapseState('Settings', { appearance: true, appUpdates: true }) const [isEditing, setIsEditing] = useState(false) const [settingsLoading, setSettingsLoading] = useState(true) const [saving, setSaving] = useState(false) const [appSettings, setAppSettingsState] = useState({}) const [draftSettings, setDraftSettings] = useState({}) const [branches, setBranches] = useState([]) const [branchLoading, setBranchLoading] = useState(false) useEffect(() => { const loadSettings = async () => { setSettingsLoading(true) const storedSettings = isElectron ? await getAppSettings() : userProfile?.settings || {} setAppSettingsState(storedSettings || {}) setDraftSettings(storedSettings || {}) setSettingsLoading(false) } loadSettings() }, [getAppSettings, isElectron, userProfile?.settings]) useEffect(() => { if (settingsLoading || isEditing) return if (appSettings.theme) setThemeMode(appSettings.theme) if (appSettings.density) setDensityMode(appSettings.density) }, [ appSettings.density, appSettings.theme, isEditing, setDensityMode, setThemeMode, settingsLoading ]) useEffect(() => { if (!isElectron) { setBranches([]) setBranchLoading(false) return } const loadBranches = async () => { setBranchLoading(true) const availableBranches = await fetchAppUpdateBranches() setBranches(availableBranches) setDraftSettings((previous) => { if (previous.appUpdateBranch) return previous const defaultBranch = availableBranches.includes(DEFAULT_UPDATE_BRANCH) ? DEFAULT_UPDATE_BRANCH : availableBranches[0] return defaultBranch ? { ...previous, appUpdateBranch: defaultBranch } : previous }) setBranchLoading(false) } loadBranches() }, [fetchAppUpdateBranches, isElectron]) const branchOptions = useMemo( () => branches.map((branch) => ( )), [branches] ) const viewItems = [ { key: 'appearance', label: 'Appearance Settings' }, ...(isElectron ? [{ key: 'appUpdates', label: 'App Update Settings' }] : []) ] const getCurrentThemeValue = () => { if (isSystem) return 'system' return isDarkMode ? 'dark' : 'light' } const currentThemeValue = getCurrentThemeValue() const currentDensityValue = isCompact ? 'compact' : 'comfortable' const currentBranch = appSettings.appUpdateBranch || (branches.includes(DEFAULT_UPDATE_BRANCH) ? DEFAULT_UPDATE_BRANCH : null) || branches[0] || 'Not configured' const startEditing = () => { setDraftSettings({ ...appSettings, appUpdateBranch: currentBranch === 'Not configured' ? undefined : currentBranch, theme: currentThemeValue, density: currentDensityValue }) setIsEditing(true) } const cancelEditing = () => { setDraftSettings(appSettings) setIsEditing(false) } const handleSave = async () => { setSaving(true) try { const nextSettings = { ...appSettings, theme: draftSettings.theme, density: draftSettings.density, ...(isElectron ? { appUpdateBranch: draftSettings.appUpdateBranch } : {}) } const saved = isElectron ? await setAppSettings(nextSettings) : Boolean(userProfile) if (!saved) { showError('Unable to save settings.') return } if (!isElectron) { setUserProfile((previous) => ({ ...previous, settings: { ...(previous?.settings || {}), theme: draftSettings.theme, density: draftSettings.density } })) } setThemeMode(draftSettings.theme) setDensityMode(draftSettings.density) setAppSettingsState(nextSettings) setDraftSettings(nextSettings) setIsEditing(false) showSuccess('Settings saved.') } finally { setSaving(false) } } return (
}> } active={collapseState.appearance} onToggle={(expanded) => updateCollapseState('appearance', expanded) } collapseKey='appearance' > {isEditing ? ( ) : ( {currentThemeValue} )} {isEditing ? ( ) : ( {isCompact ? 'Compact' : 'Comfortable'} )} {isElectron && ( } active={collapseState.appUpdates} onToggle={(expanded) => updateCollapseState('appUpdates', expanded) } collapseKey='appUpdates' > {isEditing ? ( ) : ( {currentBranch} )} )}
) } export default Settings