import type { ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { Clock, Palette, Store, Upload } from 'lucide-react'; import { useThemeStore } from '@/store/themeStore'; import { useInstalledThemesStore } from '@/store/installedThemesStore'; import CustomSelect from '@/ui/CustomSelect'; import BackToTopButton from '@/ui/BackToTopButton'; import { FIXED_THEMES } from '@/components/settings/fixedThemes'; import { InstalledThemes } from '@/features/settings/components/InstalledThemes'; import { ThemeImportSection } from '@/features/settings/components/ThemeImportSection'; import { ThemeStoreSection } from '@/features/settings/components/ThemeStoreSection'; import { SettingsGroup } from '@/features/settings/components/SettingsGroup'; import { SettingsSubCard, SettingsField } from '@/features/settings/components/SettingsSubCard'; /** * A flat, always-visible section. The Themes tab has a single purpose, so its * parts are laid out one below the other with no collapsing — deliberately not * the collapsible
SettingsSubSection used elsewhere. `data-settings- * search` keeps each section reachable from the global settings search. */ function ThemesSection({ icon, title, children, boxed }: { icon: ReactNode; title: string; children: ReactNode; boxed?: boolean }) { if (boxed) { return (
{children}
); } return (

{icon} {title}

{children}
); } /** * Dedicated Themes tab: pick a theme (fixed cores + installed community themes), * the day/night scheduler, and the community Theme Store — all flat on one page. */ export function ThemesTab() { const { t, i18n } = useTranslation(); const theme = useThemeStore(); const installed = useInstalledThemesStore(s => s.themes); return ( <> } title={t('settings.themesYourThemesTitle')} boxed> {theme.enableThemeScheduler && (
{t('settings.themeSchedulerActiveHint')}
)}
} title={t('settings.themeSchedulerTitle')} boxed>
{t('settings.themeSchedulerEnable')}
{t('settings.themeSchedulerEnableSub')}
{theme.enableThemeScheduler && (() => { const themeOptions = [ ...FIXED_THEMES.map(f => ({ value: f.id, label: f.label })), ...installed.map(it => ({ value: it.id, label: it.name, group: t('settings.themesYourThemesTitle'), })), ]; const use12h = i18n.language === 'en'; const hourOptions = Array.from({ length: 24 }, (_, i) => { const value = String(i).padStart(2, '0'); const label = use12h ? `${i % 12 === 0 ? 12 : i % 12} ${i < 12 ? 'AM' : 'PM'}` : value; return { value, label }; }); const minuteOptions = ['00', '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55'].map(m => ({ value: m, label: m })); const dayH = theme.timeDayStart.split(':')[0]; const dayM = theme.timeDayStart.split(':')[1]; const nightH = theme.timeNightStart.split(':')[0]; const nightM = theme.timeNightStart.split(':')[1]; const isSystem = theme.schedulerMode === 'system'; return (
{isSystem && (
{t('settings.themeSchedulerSystemRestartHint')}
)}
{!isSystem && (
theme.setTimeDayStart(`${v}:${dayM}`)} options={hourOptions} /> : theme.setTimeDayStart(`${dayH}:${v}`)} options={minuteOptions} />
)}
{!isSystem && (
theme.setTimeNightStart(`${v}:${nightM}`)} options={hourOptions} /> : theme.setTimeNightStart(`${nightH}:${v}`)} options={minuteOptions} />
)}
); })()}
} title={t('settings.themeImportTitle')} boxed> } title={t('settings.themeStoreTitle')}> ); }