system theme support + as default

This commit is contained in:
lightling 2025-04-20 15:19:17 -04:00
parent 2b1c357603
commit 22361db2a9
Signed by: lightling
GPG key ID: F1F29650D537C773

View file

@ -3,20 +3,39 @@ import { computed, onMounted, ref } from 'vue'
import PrimeVueSelect from 'primevue/select'
import type { SiteTheme } from '@goldenwere/mackenzii-types'
import type { SiteTheme, SiteThemeType } from '@goldenwere/mackenzii-types'
import { injectStylesheet } from 'src/utilities/dom'
import { storage } from 'src/utilities/fetch'
import { useRouteStore } from 'src/routes'
type Theme = SiteTheme & { id: string }
const systemTheme = {
id: 'SYSTEM',
displayName: 'System',
type: null as any,
url: null as any,
}
const routeStore = useRouteStore()
const globalConfig = routeStore._globals
const options = ref(globalConfig.themes)
const optionsArray = computed(() => Object.keys(options.value).map(key => ({...options.value[key], id: key})))
const optionsArray = computed<Theme[]>(() => {
const val = Object.keys(options.value).map(key => ({...options.value[key], id: key}))
if (val.find(other => other.type === 'dark') && val.find(other => other.type === 'light')) {
val.push(systemTheme)
}
return val
})
const currentTheme = ref<SiteTheme & { id: string }>(null as any)
const currentSystem = ref<SiteThemeType>(null as any)
let node: HTMLLinkElement
const setModeClass = () => {
switch (currentTheme.value.type) {
const type = currentTheme.value.id === 'SYSTEM'
? currentSystem.value
: currentTheme.value.type
switch (type) {
case 'dark':
document.body.parentElement!.classList.add('app-dark')
document.body.parentElement!.classList.remove('app-dark-hc')
@ -50,29 +69,63 @@ const setModeClass = () => {
}
}
const onThemeChosen = (event: Event) => {
const getUrlOfTheme = (id: string) => {
if (id === 'SYSTEM') {
return optionsArray.value.find(other => other.type === currentSystem.value)!.url
} else {
return globalConfig.themes[id].url
}
}
const onThemeChosen = (event?: Event) => {
const themeId = currentTheme.value.id
storage.write(`${globalConfig.id}::currentTheme`, themeId)
node.setAttribute('href', globalConfig.themes[themeId].url)
node.setAttribute('href', getUrlOfTheme(themeId))
setModeClass()
}
const onSystemThemeChanged = (query: MediaQueryListEvent | MediaQueryList) => {
if (query.matches) {
currentSystem.value = 'dark'
} else {
currentSystem.value = 'light'
}
onThemeChosen()
}
const setupSystemThemeListener = () => {
const themeListener = window.matchMedia('(prefers-color-scheme: dark)')
onSystemThemeChanged(themeListener)
themeListener.addEventListener('change', onSystemThemeChanged)
}
const loadThemeFromStorage = () => {
const themeId = storage.read<string>(`${globalConfig.id}::currentTheme`) || (
!!optionsArray.value.find(other => other.id === 'SYSTEM') ? 'SYSTEM' : Object.keys(globalConfig.themes)[0]
)
currentTheme.value = themeId === 'SYSTEM' ? systemTheme : { ...options.value[themeId], id: themeId }
node = injectStylesheet(getUrlOfTheme(themeId), 'theme-stylesheet')
}
onMounted(async () => {
const themeId = storage.read<string>(`${globalConfig.id}::currentTheme`) || Object.keys(globalConfig.themes)[0]
currentTheme.value = { ...options.value[themeId], id: themeId }
node = injectStylesheet(globalConfig.themes[themeId].url, 'theme-stylesheet')
loadThemeFromStorage()
setupSystemThemeListener()
setModeClass()
})
</script>
<template lang="pug">
.theme-picker
label(
for='site theme'
) Theme
PrimeVueSelect(
v-model='currentTheme'
:options='optionsArray'
@change='onThemeChosen($event)'
optionLabel='displayName'
placeholder='theme'
name='site theme'
)
</template>