diff --git a/gameyfin/src/main/frontend/components/theming/ThemeSelector.tsx b/gameyfin/src/main/frontend/components/theming/ThemeSelector.tsx index 5f46679..6d2aaed 100644 --- a/gameyfin/src/main/frontend/components/theming/ThemeSelector.tsx +++ b/gameyfin/src/main/frontend/components/theming/ThemeSelector.tsx @@ -4,8 +4,8 @@ import {Button, Card, Divider, Select, Selection, SelectItem} from "@heroui/reac import {themes} from "Frontend/theming/themes"; import {Theme} from "Frontend/theming/theme"; import ThemePreview from "Frontend/components/theming/ThemePreview"; -import {UserPreferencesEndpoint} from "Frontend/generated/endpoints"; import {toTitleCase} from "Frontend/util/utils"; +import {UserPreferenceService} from "Frontend/util/user-preference-service"; export function ThemeSelector() { @@ -24,7 +24,7 @@ export function ThemeSelector() { if (selectedMode instanceof Set) { let theme = `${selectedTheme}-${selectedMode.values().next().value}`; setTheme(theme); - UserPreferencesEndpoint.set("preferred-theme", theme).catch(console.error); + UserPreferenceService.set("preferred-theme", theme).catch(console.error); } } diff --git a/gameyfin/src/main/frontend/util/user-preference-service.ts b/gameyfin/src/main/frontend/util/user-preference-service.ts new file mode 100644 index 0000000..0d6e6c5 --- /dev/null +++ b/gameyfin/src/main/frontend/util/user-preference-service.ts @@ -0,0 +1,39 @@ +import {UserPreferencesEndpoint} from "Frontend/generated/endpoints"; + +export class UserPreferenceService { + static LOCAL_STORAGE_PREFIX = "gameyfin."; + + static async sync(): Promise { + let keys = Object.keys(localStorage); + for (let key of keys) { + if (!key.startsWith(`${this.LOCAL_STORAGE_PREFIX}`)) { + continue; + } + let value = await UserPreferencesEndpoint.get(key.replace(this.LOCAL_STORAGE_PREFIX, "")); + if (value) { + localStorage.setItem(key, value); + } + } + } + + static async get(key: string): Promise { + let localPreference = localStorage.getItem(`${this.LOCAL_STORAGE_PREFIX}${key}`); + + if (localPreference) { + return localPreference; + } else { + let syncedPreference = await UserPreferencesEndpoint.get(key); + if (syncedPreference) { + localStorage.setItem(`${this.LOCAL_STORAGE_PREFIX}${key}`, syncedPreference); + return syncedPreference; + } + } + + return undefined; + } + + static async set(key: string, value: string) { + await UserPreferencesEndpoint.set(key, value); + localStorage.setItem(`${this.LOCAL_STORAGE_PREFIX}${key}`, value); + } +} \ No newline at end of file diff --git a/gameyfin/src/main/frontend/views/MainLayout.tsx b/gameyfin/src/main/frontend/views/MainLayout.tsx index 63e1dc6..fc56bd5 100644 --- a/gameyfin/src/main/frontend/views/MainLayout.tsx +++ b/gameyfin/src/main/frontend/views/MainLayout.tsx @@ -8,8 +8,8 @@ import {Outlet, useNavigate} from "react-router"; import {useAuth} from "Frontend/util/auth"; import {Heart} from "@phosphor-icons/react"; import Confetti, {ConfettiProps} from "react-confetti-boom"; -import {UserPreferencesEndpoint} from "Frontend/generated/endpoints"; import {useTheme} from "next-themes"; +import {UserPreferenceService} from "Frontend/util/user-preference-service"; export default function MainLayout() { const navigate = useNavigate(); @@ -21,7 +21,10 @@ export default function MainLayout() { useEffect(() => { let newTitle = `Gameyfin - ${routeMetadata?.title}`; window.addEventListener('popstate', () => document.title = newTitle); - loadUserTheme().catch(console.error); + + UserPreferenceService.sync() + .then(() => loadUserTheme().catch(console.error)) + .catch(console.error); }, []); const confettiProps: ConfettiProps = { @@ -35,16 +38,9 @@ export default function MainLayout() { } async function loadUserTheme() { - let syncedTheme = await UserPreferencesEndpoint.get("preferred-theme"); - - if (syncedTheme) { + let syncedTheme = await UserPreferenceService.get("preferred-theme") + if (syncedTheme !== undefined) { setTheme(syncedTheme); - } else { - let localTheme = localStorage.getItem('theme'); - if (localTheme) { - setTheme(localTheme); - await UserPreferencesEndpoint.set("preferred-theme", localTheme); - } } } diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/users/preferences/UserPreferences.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/users/preferences/UserPreferences.kt index b1558f6..1135893 100644 --- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/users/preferences/UserPreferences.kt +++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/users/preferences/UserPreferences.kt @@ -9,4 +9,5 @@ sealed class UserPreferences( val allowedValues: List? = null ) { data object PreferredTheme : UserPreferences(String::class, "preferred-theme") + data object PreferredDownloadMethod : UserPreferences(String::class, "preferred-download-method") } \ No newline at end of file