Ensure theme remains on load and syncs to account
This commit is contained in:
@@ -29,6 +29,13 @@
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
});
|
||||
|
||||
async function setThemeColors() {
|
||||
await tick();
|
||||
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
interfaceAdvancedThemingStore.set(currentThemeColors);
|
||||
}
|
||||
|
||||
async function colorOnInput(
|
||||
color: {
|
||||
hsv: HsvaColor | null;
|
||||
@@ -43,10 +50,7 @@
|
||||
colorPickerDebounce = setTimeout(async () => {
|
||||
if (!color.hex) return;
|
||||
setThemeColor(propetyKey, color.hex);
|
||||
await tick();
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
|
||||
interfaceAdvancedThemingStore.set(currentThemeColors);
|
||||
await setThemeColors();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -62,8 +66,10 @@
|
||||
colorPickerDebounce = setTimeout(async () => {
|
||||
themeColorStore.set(color.hex);
|
||||
await tick();
|
||||
|
||||
setAmoledTheme();
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
interfaceAdvancedThemingStore.set({});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -79,6 +85,7 @@
|
||||
}
|
||||
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
interfaceAdvancedThemingStore.set({});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -126,7 +133,7 @@
|
||||
bind:checked={$interfaceAmoledTheme}
|
||||
onclick={async () => {
|
||||
interfaceAmoledTheme.set(!$interfaceAmoledTheme);
|
||||
currentThemeColors = await getDynamicTheme();
|
||||
await setThemeColors();
|
||||
}}
|
||||
role="switch"
|
||||
/>
|
||||
|
||||
@@ -183,7 +183,7 @@ menu.player-settings {
|
||||
|
||||
.player-slider [data-melt-slider-thumb] {
|
||||
position: absolute;
|
||||
border-radius: 1rem;
|
||||
border-radius: var(--player-border-radius);
|
||||
background: var(--primary);
|
||||
left: var(--percentage);
|
||||
top: 50%;
|
||||
|
||||
@@ -53,9 +53,11 @@ import {
|
||||
playerPreferredVolumeStore,
|
||||
watchHistoryEnabledStore,
|
||||
filterContentUrlStore,
|
||||
filterContentUrlAutoUpdateStore
|
||||
filterContentUrlAutoUpdateStore,
|
||||
interfaceAdvancedThemingStore
|
||||
} from '$lib/store';
|
||||
import { isOwnBackend } from '$lib/shared';
|
||||
import { SUPPORTED_THEME_KEYS } from '$lib/shared/theme';
|
||||
|
||||
type PersistedStore<T> = {
|
||||
name: string;
|
||||
@@ -77,6 +79,12 @@ const zAuth = z.object({
|
||||
username: z.string(),
|
||||
token: z.string()
|
||||
});
|
||||
const zThemeColors = z.record(
|
||||
z.string().refine((val) => SUPPORTED_THEME_KEYS.includes(val), {
|
||||
message: 'CSS property not allowed'
|
||||
}),
|
||||
z.string().regex(/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
|
||||
);
|
||||
|
||||
export const persistedStores: PersistedStore<any>[] = [
|
||||
{
|
||||
@@ -270,6 +278,12 @@ export const persistedStores: PersistedStore<any>[] = [
|
||||
name: 'filterContentUrlAutoUpdate',
|
||||
store: filterContentUrlAutoUpdateStore,
|
||||
schema: zBoolean
|
||||
},
|
||||
{
|
||||
name: 'advancedTheming',
|
||||
store: interfaceAdvancedThemingStore,
|
||||
schema: zThemeColors,
|
||||
serialize: JSON.stringify
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
export const SUPPORTED_THEME_KEYS: string[] = [
|
||||
'--primary',
|
||||
'--on-primary',
|
||||
'--primary-container',
|
||||
'--on-primary-container',
|
||||
'--secondary',
|
||||
'--on-secondary',
|
||||
'--secondary-container',
|
||||
'--on-secondary-container',
|
||||
'--tertiary',
|
||||
'--on-tertiary',
|
||||
'--tertiary-container',
|
||||
'--on-tertiary-container',
|
||||
'--error',
|
||||
'--on-error',
|
||||
'--error-container',
|
||||
'--on-error-container',
|
||||
'--background',
|
||||
'--on-background',
|
||||
'--surface',
|
||||
'--on-surface',
|
||||
'--surface-variant',
|
||||
'--on-surface-variant',
|
||||
'--outline',
|
||||
'--outline-variant',
|
||||
'--shadow',
|
||||
'--scrim',
|
||||
'--inverse-surface',
|
||||
'--inverse-on-surface',
|
||||
'--inverse-primary',
|
||||
'--surface-dim',
|
||||
'--surface-bright',
|
||||
'--surface-container-lowest',
|
||||
'--surface-container-low',
|
||||
'--surface-container',
|
||||
'--surface-container-high',
|
||||
'--surface-container-highest'
|
||||
] as const;
|
||||
@@ -116,45 +116,6 @@ export function setTheme() {
|
||||
}
|
||||
}
|
||||
|
||||
export const SUPPORTED_THEME_KEYS: ThemeKey[] = [
|
||||
'--primary',
|
||||
'--on-primary',
|
||||
'--primary-container',
|
||||
'--on-primary-container',
|
||||
'--secondary',
|
||||
'--on-secondary',
|
||||
'--secondary-container',
|
||||
'--on-secondary-container',
|
||||
'--tertiary',
|
||||
'--on-tertiary',
|
||||
'--tertiary-container',
|
||||
'--on-tertiary-container',
|
||||
'--error',
|
||||
'--on-error',
|
||||
'--error-container',
|
||||
'--on-error-container',
|
||||
'--background',
|
||||
'--on-background',
|
||||
'--surface',
|
||||
'--on-surface',
|
||||
'--surface-variant',
|
||||
'--on-surface-variant',
|
||||
'--outline',
|
||||
'--outline-variant',
|
||||
'--shadow',
|
||||
'--scrim',
|
||||
'--inverse-surface',
|
||||
'--inverse-on-surface',
|
||||
'--inverse-primary',
|
||||
'--surface-dim',
|
||||
'--surface-bright',
|
||||
'--surface-container-lowest',
|
||||
'--surface-container-low',
|
||||
'--surface-container',
|
||||
'--surface-container-high',
|
||||
'--surface-container-highest'
|
||||
] as const;
|
||||
|
||||
export function setThemeColors(theme: ThemeColors) {
|
||||
for (const [themeKey, themeValue] of Object.entries(theme)) {
|
||||
setThemeColor(themeKey as ThemeKey, themeValue.trim());
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
playerState,
|
||||
playerTheatreModeIsActive,
|
||||
rawMasterKeyStore,
|
||||
themeColorStore,
|
||||
backendInUseStore,
|
||||
hideSearchStore
|
||||
} from '$lib/store';
|
||||
@@ -126,11 +125,6 @@
|
||||
notifications = feed.notifications;
|
||||
}
|
||||
|
||||
themeColorStore.subscribe(async (hex) => {
|
||||
if (!hex) return;
|
||||
await ui('theme', hex);
|
||||
});
|
||||
|
||||
function resetScroll() {
|
||||
const main = document.querySelector('main.root');
|
||||
if (main) main.scrollTop = 0;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
darkModeStore,
|
||||
interfaceAdvancedThemingStore,
|
||||
interfaceAmoledTheme,
|
||||
invidiousAuthStore,
|
||||
isAndroidTvStore,
|
||||
@@ -15,7 +16,7 @@
|
||||
import 'beercss';
|
||||
import 'material-dynamic-colors';
|
||||
|
||||
import { setAmoledTheme, setStatusBarColor, setTheme } from '$lib/theme';
|
||||
import { setAmoledTheme, setStatusBarColor, setTheme, setThemeColors } from '$lib/theme';
|
||||
|
||||
import { pwaInfo } from 'virtual:pwa-info';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -30,8 +31,18 @@
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
themeColorStore.subscribe(async (hex) => {
|
||||
if (!hex || Object.keys($interfaceAdvancedThemingStore).length > 0) return;
|
||||
await ui('theme', hex);
|
||||
});
|
||||
|
||||
interfaceAdvancedThemingStore.subscribe((colors) => {
|
||||
setThemeColors(colors);
|
||||
});
|
||||
|
||||
interfaceAmoledTheme.subscribe(async () => {
|
||||
setAmoledTheme();
|
||||
setThemeColors($interfaceAdvancedThemingStore);
|
||||
|
||||
await setStatusBarColor();
|
||||
});
|
||||
@@ -40,6 +51,8 @@
|
||||
setTheme();
|
||||
setAmoledTheme();
|
||||
|
||||
setThemeColors($interfaceAdvancedThemingStore);
|
||||
|
||||
await setStatusBarColor();
|
||||
});
|
||||
|
||||
@@ -114,11 +127,6 @@
|
||||
// Should always be loaded after env settings
|
||||
// So user preferences overwrite instance preferences.
|
||||
bookmarkletLoadFromUrl();
|
||||
|
||||
await setStatusBarColor();
|
||||
|
||||
setTheme();
|
||||
setAmoledTheme();
|
||||
});
|
||||
|
||||
let syncToSettingsInitialized = false;
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function DELETE({ locals, params }) {
|
||||
}
|
||||
|
||||
const zUpdateKeyStore = z.object({
|
||||
valueCipher: z.string().max(1000),
|
||||
valueCipher: z.string().max(3000),
|
||||
valueNonce: z.string().max(255)
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user