/** * useReadingSettings — fetch and manage user reading preferences. * Applies settings as CSS custom properties on the document root. */ import { useCallback, useEffect, useState } from "react"; import { getReadingSettings, updateReadingSettings, } from "../api/reader"; import type { ReadingSettings } from "../types/reader"; const DEFAULT_SETTINGS: ReadingSettings = { font_family: "serif", font_size: 18, line_height: 1.6, margin_width: 16, background_color: "#f5f0eb", text_color: "#1a1a1a", brightness: 100, orientation_lock: "auto", theme: "sepia", created_at: "", updated_at: "", }; function applyCssVariables(settings: ReadingSettings): void { const root = document.documentElement; root.style.setProperty("--reader-bg", settings.background_color); root.style.setProperty("--reader-text", settings.text_color); root.style.setProperty("--reader-font-family", settings.font_family); root.style.setProperty("--reader-font-size", `${settings.font_size}px`); root.style.setProperty("--reader-line-height", String(settings.line_height)); root.style.setProperty("--reader-margin", `${settings.margin_width}px`); root.style.setProperty("--reader-brightness", `${settings.brightness}%`); } export interface UseReadingSettingsReturn { settings: ReadingSettings; isLoading: boolean; error: string | null; updateSettings: (partial: Partial) => Promise; } export function useReadingSettings(): UseReadingSettingsReturn { const [settings, setSettings] = useState(DEFAULT_SETTINGS); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Fetch settings on mount useEffect(() => { let cancelled = false; setIsLoading(true); getReadingSettings() .then((data) => { if (!cancelled) { setSettings(data); applyCssVariables(data); } }) .catch((err: unknown) => { if (!cancelled) { setError( err instanceof Error ? err.message : "Failed to load reading settings" ); // Apply defaults applyCssVariables(DEFAULT_SETTINGS); } }) .finally(() => { if (!cancelled) setIsLoading(false); }); return () => { cancelled = true; }; }, []); const updateSettings = useCallback( async (partial: Partial) => { try { const updated = await updateReadingSettings(partial); setSettings(updated); applyCssVariables(updated); setError(null); } catch (err: unknown) { setError( err instanceof Error ? err.message : "Failed to update reading settings" ); throw err; } }, [] ); return { settings, isLoading, error, updateSettings }; }