Merge "custom themes" and "configured/imported CSS" into one mechanism (ticket 012)

The backend already stored both under one CssEntry list (Imported/Linked,
differing only by the is_theme flag), but the NavMenu Settings panel split
them into two visually-duplicated sections — "Custom themes" with its own
upload/link forms and list, and "Import CSS"/"Configured CSS" with a nearly
identical upload form and a separate list — and useSettingsPanel exposed
parallel importCssEntry/importThemeEntry and (theme-only) linkThemeEntry
wrappers around the same underlying API calls.

Consolidate to one "CSS" section: a single list of all CssEntries (each
tagged "theme" and selectable when is_theme is set), one import form and
one link form, each with a "Use as theme" checkbox instead of a duplicate
theme-only form. useSettingsPanel now exposes a single importCssEntry(name,
content, isTheme) and a generic linkCssEntry(url, isTheme) — the latter also
fixes the prior asymmetry where linking (vs. uploading) was only available
for themes, not arbitrary CSS.

No backend or settings-schema changes were needed: is_theme already
persists correctly, so existing custom-theme and imported-CSS
configuration keeps working unmodified under the unified UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-05 18:42:40 +01:00
co-authored by Claude Sonnet 5
parent ed0be9726f
commit ffeba3c274
3 changed files with 148 additions and 209 deletions
+9 -16
View File
@@ -162,28 +162,22 @@ export function useSettingsPanel() {
[guarded],
)
// One entry point for both "configured/imported CSS" and "custom themes" —
// `isTheme` is the only thing distinguishing them (ticket 012), so there's
// no separate theme-only import path.
const importCssEntry = useCallback(
(filename: string, content: string) =>
(filename: string, content: string, isTheme = false) =>
guarded(async () => {
await importCss(filename, content)
await importCss(filename, content, isTheme)
await refreshCss()
})(),
[guarded, refreshCss],
)
const importThemeEntry = useCallback(
(filename: string, content: string) =>
const linkCssEntry = useCallback(
(pathOrUrl: string, isTheme = false) =>
guarded(async () => {
await importCss(filename, content, true)
await refreshCss()
})(),
[guarded, refreshCss],
)
const linkThemeEntry = useCallback(
(pathOrUrl: string) =>
guarded(async () => {
await linkCss(pathOrUrl, true)
await linkCss(pathOrUrl, isTheme)
await refreshCss()
})(),
[guarded, refreshCss],
@@ -241,8 +235,7 @@ export function useSettingsPanel() {
setMaxLogs,
setNtfySink,
importCssEntry,
importThemeEntry,
linkThemeEntry,
linkCssEntry,
removeCssEntry,
addProfile,
removeProfile,