first commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
export type Theme = 'dark' | 'light'
|
||||
|
||||
const STORAGE_KEY = 'viewer.theme'
|
||||
const listeners = new Set<(theme: Theme) => void>()
|
||||
|
||||
export function initTheme(): Theme {
|
||||
const isAndroidShell =
|
||||
typeof (window as unknown as { AndroidViewer?: unknown }).AndroidViewer !== 'undefined'
|
||||
let theme: Theme = 'dark'
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEY)
|
||||
if (stored === 'light' || stored === 'dark') {
|
||||
theme = stored
|
||||
} else if (!isAndroidShell && window.matchMedia?.('(prefers-color-scheme: light)').matches) {
|
||||
theme = 'light'
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
applyTheme(theme, false)
|
||||
return theme
|
||||
}
|
||||
|
||||
export function getTheme(): Theme {
|
||||
return document.documentElement.dataset.theme === 'light' ? 'light' : 'dark'
|
||||
}
|
||||
|
||||
export function setTheme(theme: Theme): void {
|
||||
applyTheme(theme, true)
|
||||
}
|
||||
|
||||
export function toggleTheme(): Theme {
|
||||
const next: Theme = getTheme() === 'dark' ? 'light' : 'dark'
|
||||
setTheme(next)
|
||||
return next
|
||||
}
|
||||
|
||||
function applyTheme(theme: Theme, persist: boolean): void {
|
||||
document.documentElement.dataset.theme = theme
|
||||
document.documentElement.style.colorScheme = theme
|
||||
const meta = document.querySelector('meta[name="theme-color"]')
|
||||
if (meta) meta.setAttribute('content', theme === 'dark' ? '#0b0e14' : '#f2f5fa')
|
||||
if (persist) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, theme)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
for (const listener of listeners) listener(theme)
|
||||
}
|
||||
|
||||
export function onThemeChange(listener: (theme: Theme) => void): () => void {
|
||||
listeners.add(listener)
|
||||
return () => listeners.delete(listener)
|
||||
}
|
||||
Reference in New Issue
Block a user