Separate theme management from theme component

This commit is contained in:
Mattias Granlund 2023-06-30 18:11:30 +01:00
parent d95cbdb738
commit d3ab856cdc
3 changed files with 50 additions and 34 deletions

42
src/lib/theme.ts Normal file
View File

@ -0,0 +1,42 @@
import { writable, type Writable } from '@square/svelte-store';
import { appWindow, type Theme } from '@tauri-apps/api/window';
const themeStorageKey = 'theme';
export const theme: Writable<string> = writable('dark');
let systemTheme: string | null;
export function initTheme() {
appWindow.theme().then((value: Theme | null) => {
systemTheme = value;
updateDom();
});
appWindow.onThemeChanged((e) => {
systemTheme = e.payload;
updateDom();
});
}
export function setTheme(name: string) {
localStorage.setItem(themeStorageKey, name);
theme.set(name);
updateDom();
}
export function getTheme(): string | null {
return localStorage.getItem(themeStorageKey);
}
export function updateDom() {
const docEl = document.documentElement;
const selectedTheme = localStorage.getItem(themeStorageKey);
if (selectedTheme == 'dark' || (selectedTheme == 'system' && systemTheme == 'dark')) {
docEl.classList.add('dark');
docEl.style.colorScheme = 'dark';
theme.set('dark');
} else if (selectedTheme == 'light' || (selectedTheme == 'system' && systemTheme == 'light')) {
docEl.classList.remove('dark');
docEl.style.colorScheme = 'light';
theme.set('light');
}
}

View File

@ -3,6 +3,7 @@ import { api, log } from '$lib';
import Posthog from '$lib/posthog';
import Sentry from '$lib/sentry';
import { wrapLoadWithSentry } from '@sentry/sveltekit';
import { initTheme } from '$lib/theme';
export const ssr = false;
export const prerender = true;
@ -10,6 +11,7 @@ export const csr = true;
export const load: LayoutLoad = wrapLoadWithSentry(({ fetch }) => {
log.setup();
initTheme();
return {
projects: api.projects.Projects(),
cloud: api.CloudApi({ fetch }),

View File

@ -1,43 +1,15 @@
<script lang="ts">
import { appWindow, type Theme } from '@tauri-apps/api/window';
const themeStorageKey = 'theme';
let systemTheme: string | null;
let selectedTheme: string | null;
appWindow.theme().then((value: Theme | null) => {
selectedTheme = localStorage.getItem(themeStorageKey);
systemTheme = value;
updateDom();
});
appWindow.onThemeChanged((e) => {
systemTheme = e.payload;
updateDom();
});
import { theme, setTheme } from '$lib/theme';
function onThemeChange(e: Event & { currentTarget: HTMLSelectElement }) {
selectedTheme = e.currentTarget.value;
localStorage.setItem(themeStorageKey, selectedTheme);
updateDom();
}
function updateDom() {
const docEl = document.documentElement;
if (selectedTheme == 'dark' || (selectedTheme == 'system' && systemTheme == 'dark')) {
docEl.classList.add('dark');
docEl.style.colorScheme = 'dark';
} else if (selectedTheme == 'light' || (selectedTheme == 'system' && systemTheme == 'light')) {
docEl.classList.remove('dark');
docEl.style.colorScheme = 'light';
}
setTheme(e.currentTarget.value);
}
</script>
<div>
<label for="dark-mode-toggle" class="mr-2">Theme</label>
<select bind:value={selectedTheme} on:change={onThemeChange}>
<option>system</option>
<option>light</option>
<option>dark</option>
<select bind:value={$theme} on:change={onThemeChange}>
<option value="system">System preference</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>