Add API Server (Go/PocketBase), Web App (Go BFF + Vue), Fly App (Flutter/DJI MSDK), Adobe Plugin, and Docker/Docker AIO deployment configs. Design assets and build artifacts are gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
2.0 KiB
JavaScript
74 lines
2.0 KiB
JavaScript
// Theme store — light is the PilotVault default. The user picks a *mode*
|
|
// (light | dark | system); `theme` is the resolved value (light | dark) that
|
|
// actually drives [data-theme] on <html>. The pre-paint script in index.html
|
|
// resolves the same way to avoid a flash before hydration.
|
|
import { ref } from 'vue'
|
|
|
|
const KEY = 'pv_theme'
|
|
|
|
// Concrete ground colors (--bg-app per theme), set inline on <html> so the
|
|
// viewport canvas repaints reliably when the theme flips (Chromium quirk).
|
|
const GROUND = { light: '#EEF0F3', dark: '#0B1730' }
|
|
|
|
const media = typeof window !== 'undefined' && window.matchMedia
|
|
? window.matchMedia('(prefers-color-scheme: dark)')
|
|
: null
|
|
|
|
function systemTheme() {
|
|
return media && media.matches ? 'dark' : 'light'
|
|
}
|
|
|
|
function initialMode() {
|
|
try {
|
|
return localStorage.getItem(KEY) || 'light'
|
|
} catch {
|
|
return 'light'
|
|
}
|
|
}
|
|
|
|
function resolve(mode) {
|
|
return mode === 'system' ? systemTheme() : mode
|
|
}
|
|
|
|
function paint(resolved) {
|
|
const html = document.documentElement
|
|
html.setAttribute('data-theme', resolved)
|
|
html.style.backgroundColor = GROUND[resolved] || GROUND.light
|
|
}
|
|
|
|
// The user's chosen mode, and the concrete resolved theme.
|
|
export const themeMode = ref(initialMode())
|
|
export const theme = ref(resolve(themeMode.value))
|
|
|
|
export function setThemeMode(mode) {
|
|
themeMode.value = mode
|
|
const resolved = resolve(mode)
|
|
theme.value = resolved
|
|
paint(resolved)
|
|
try {
|
|
localStorage.setItem(KEY, mode)
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
// Back-compat alias used by older call sites.
|
|
export const applyTheme = setThemeMode
|
|
|
|
// Simple light/dark flip for the header toggle. From "system" it commits to the
|
|
// opposite of whatever is currently showing.
|
|
export function toggleTheme() {
|
|
setThemeMode(theme.value === 'dark' ? 'light' : 'dark')
|
|
}
|
|
|
|
// Follow the OS while in "system" mode.
|
|
if (media) {
|
|
media.addEventListener('change', () => {
|
|
if (themeMode.value === 'system') {
|
|
const resolved = systemTheme()
|
|
theme.value = resolved
|
|
paint(resolved)
|
|
}
|
|
})
|
|
}
|