YT-AI-Automation / frontend /src /store /SettingsProvider.tsx
github-actions
Sync Docker Space
5f3e9f5
import { useCallback, useEffect, useMemo, useState } from 'react'
import type { ReactNode } from 'react'
import {
applyTheme,
DEFAULT_SETTINGS,
SETTINGS_STORAGE_KEY,
SettingsContext,
type AppSettings,
} from './settings'
import { setBackendBaseUrl } from '../api/client'
function loadInitial(): AppSettings {
try {
const raw = localStorage.getItem(SETTINGS_STORAGE_KEY)
if (!raw) return DEFAULT_SETTINGS
const parsed = JSON.parse(raw) as Partial<AppSettings>
return { ...DEFAULT_SETTINGS, ...parsed }
} catch {
return DEFAULT_SETTINGS
}
}
// Apply any persisted backend URL *before* React renders so the first API
// call from any component picks up the override.
setBackendBaseUrl(loadInitial().backendUrl)
export function SettingsProvider({ children }: { children: ReactNode }) {
const [settings, setSettings] = useState<AppSettings>(loadInitial)
useEffect(() => {
applyTheme(settings)
setBackendBaseUrl(settings.backendUrl)
try {
localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settings))
} catch {
/* quota exceeded / disabled — swallow */
}
}, [settings])
// React to system theme changes when the user picked 'system'.
useEffect(() => {
if (settings.theme !== 'system') return
const mql = window.matchMedia('(prefers-color-scheme: dark)')
const onChange = () => applyTheme(settings)
mql.addEventListener('change', onChange)
return () => mql.removeEventListener('change', onChange)
}, [settings])
const update = useCallback((patch: Partial<AppSettings>) => {
setSettings((prev) => ({ ...prev, ...patch }))
}, [])
const reset = useCallback(() => setSettings(DEFAULT_SETTINGS), [])
const value = useMemo(() => ({ settings, update, reset }), [settings, update, reset])
return <SettingsContext.Provider value={value}>{children}</SettingsContext.Provider>
}