diff --git a/frontend/src/lib/settings.ts b/frontend/src/lib/settings.ts index 51a8abc..c33a3c4 100644 --- a/frontend/src/lib/settings.ts +++ b/frontend/src/lib/settings.ts @@ -212,6 +212,15 @@ const LEGACY_GEKANATOR_BACKGROUND_MOTION_STORAGE_KEY = const LEGACY_MIGRATED_THEME_ID = 'custom:legacy-migrated' +const createCustomThemeId = (): `custom:${ string }` => { + const randomPart = + globalThis.crypto?.randomUUID?.() + ?? `${ Date.now ().toString (36) }-${ Math.random ().toString (36).slice (2) }` + + return `custom:${ randomPart }` +} + + export const fetchUserSettings = async (): Promise => { const raw = await apiGet<{ theme: UserSettings['theme'] @@ -567,7 +576,7 @@ export const createCustomThemeFromBase = ( baseTheme: BuiltinThemeId, tokens?: ThemeTokens, ): CustomClientTheme => { - const id = `custom:${ crypto.randomUUID () }` as ThemeId + const id = createCustomThemeId () return { id, name: themeCopyName (baseTheme), diff --git a/frontend/src/pages/users/SettingPage.tsx b/frontend/src/pages/users/SettingPage.tsx index 9d1af16..7e83cc7 100644 --- a/frontend/src/pages/users/SettingPage.tsx +++ b/frontend/src/pages/users/SettingPage.tsx @@ -71,6 +71,7 @@ type SharedSectionProps = { selectedTheme: ClientTheme draftTagColours: ThemeTagColours onThemeChange: (themeId: ActiveThemeId) => void + onEnsureEditableTheme: () => void onTagColourChange: (category: Category, colour: string) => void onResetAllTagColours: () => void onResetTagColour: (category: Category) => void @@ -252,6 +253,7 @@ const ThemeSection: FC = ({ draftCustomThemes, selectedTheme, draftTagColours, + onEnsureEditableTheme, onResetAllTagColours, onResetTagColour, onTagColourChange, @@ -331,6 +333,8 @@ const ThemeSection: FC = ({ onTagColourChange (category, ev.target.value)} className="h-10 w-16 cursor-pointer rounded border border-border bg-transparent p-1"/> @@ -514,6 +518,21 @@ const SettingPage: FC = ({ user, setUser }) => { } } + const handleEnsureEditableTheme = (): { + activeThemeId: ActiveThemeId + customThemes: Record + } => { + const editable = ensureEditableCustomTheme () + + if (editable.activeThemeId !== draftActiveThemeId + || editable.customThemes !== draftCustomThemes) + { + applyDraftThemeSelection (editable.activeThemeId, editable.customThemes) + } + + return editable + } + const handleTabKeyDown = (event: KeyboardEvent) => { const currentIndex = tabs.findIndex (tab => tab.id === activeTab) @@ -677,8 +696,11 @@ const SettingPage: FC = ({ user, setUser }) => { onThemeChange: themeId => { applyDraftThemeSelection (themeId, draftCustomThemes) }, + onEnsureEditableTheme: () => { + handleEnsureEditableTheme () + }, onTagColourChange: (category, colour) => { - const editable = ensureEditableCustomTheme () + const editable = handleEnsureEditableTheme () const editableTheme = editable.customThemes[editable.activeThemeId] const nextCustomThemes = { ...editable.customThemes,