feat(stage-web): theme for settings
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import Color from 'colorjs.io'
|
||||
|
||||
import { withRetry } from '@moeru/std'
|
||||
import { useDark } from '@vueuse/core'
|
||||
|
||||
export function themeColorFromPropertyOf(colorFromClass: string, property: string): () => Promise<string> {
|
||||
return async () => {
|
||||
const fetchUntilWidgetMounted = withRetry(() => {
|
||||
const widgets = document.querySelector(colorFromClass) as HTMLDivElement | undefined
|
||||
if (!widgets)
|
||||
throw new Error('Widgets element not found')
|
||||
|
||||
return widgets
|
||||
}, { retry: 10, retryDelay: 1000 })
|
||||
|
||||
const widgets = await fetchUntilWidgetMounted()
|
||||
return window.getComputedStyle(widgets).getPropertyValue(property)
|
||||
}
|
||||
}
|
||||
|
||||
export function themeColorFromValue(value: string | { light: string, dark: string }): () => Promise<string> {
|
||||
return async () => {
|
||||
if (typeof value === 'string') {
|
||||
return value
|
||||
}
|
||||
else {
|
||||
const dark = useDark()
|
||||
return dark.value ? value.dark : value.light
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function useThemeColor(colorFrom: () => string | Promise<string>) {
|
||||
async function updateThemeColor() {
|
||||
if (!('document' in globalThis && globalThis.document != null))
|
||||
return
|
||||
if (!('window' in globalThis && globalThis.window != null))
|
||||
return
|
||||
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', new Color(await colorFrom()).to('srgb').toString({ format: 'hex' }))
|
||||
}
|
||||
|
||||
return {
|
||||
updateThemeColor,
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { PageHeader } from '@proj-airi/stage-ui/components'
|
||||
import { useProvidersStore } from '@proj-airi/stage-ui/stores'
|
||||
import { useDark } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed } from 'vue'
|
||||
import { computed, onMounted, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView, useRoute } from 'vue-router'
|
||||
|
||||
import HeaderLink from '../components/Layouts/HeaderLink.vue'
|
||||
|
||||
import { themeColorFromValue, useThemeColor } from '../composables/theme-color'
|
||||
|
||||
const route = useRoute()
|
||||
const dark = useDark()
|
||||
const { t } = useI18n()
|
||||
const providersStore = useProvidersStore()
|
||||
const { allProvidersMetadata } = storeToRefs(providersStore)
|
||||
@@ -108,6 +112,11 @@ const routeHeaderMetadataMap = computed(() => {
|
||||
|
||||
// const activeSettingsTutorial = ref('default')
|
||||
const routeHeaderMetadata = computed(() => routeHeaderMetadataMap.value[route.path])
|
||||
|
||||
const { updateThemeColor } = useThemeColor(themeColorFromValue({ light: 'rgb(255 255 255)', dark: 'rgb(18 18 18)' }))
|
||||
watch(dark, () => updateThemeColor(), { immediate: true })
|
||||
watch(route, () => updateThemeColor(), { immediate: true })
|
||||
onMounted(() => updateThemeColor())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import Color from 'colorjs.io'
|
||||
|
||||
import { withRetry } from '@moeru/std'
|
||||
import { WidgetStage } from '@proj-airi/stage-ui/components/scenes'
|
||||
import { breakpointsTailwind, useBreakpoints, useDark, useMouse } from '@vueuse/core'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
@@ -12,6 +9,8 @@ import InteractiveArea from '../components/Layouts/InteractiveArea.vue'
|
||||
import MobileInteractiveArea from '../components/Layouts/MobileInteractiveArea.vue'
|
||||
import AnimatedWave from '../components/Widgets/AnimatedWave.vue'
|
||||
|
||||
import { themeColorFromPropertyOf, useThemeColor } from '../composables/theme-color'
|
||||
|
||||
const dark = useDark()
|
||||
const paused = ref(false)
|
||||
|
||||
@@ -23,25 +22,7 @@ const positionCursor = useMouse()
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
const isMobile = breakpoints.smaller('md')
|
||||
|
||||
async function updateThemeColor() {
|
||||
if (!('document' in globalThis && globalThis.document != null))
|
||||
return
|
||||
if (!('window' in globalThis && globalThis.window != null))
|
||||
return
|
||||
|
||||
const fetchUntilWidgetMounted = withRetry(() => {
|
||||
const widgets = document.querySelector('.widgets.top-widgets .colored-area') as HTMLDivElement | undefined
|
||||
if (!widgets)
|
||||
throw new Error('Widgets element not found')
|
||||
|
||||
return widgets
|
||||
}, { retry: 10, retryDelay: 1000 })
|
||||
|
||||
const widgets = await fetchUntilWidgetMounted()
|
||||
const backgroundColor = window.getComputedStyle(widgets).getPropertyValue('background-color')
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', new Color(backgroundColor).to('srgb').toString({ format: 'hex' }))
|
||||
}
|
||||
|
||||
const { updateThemeColor } = useThemeColor(themeColorFromPropertyOf('.widgets.top-widgets .colored-area', 'background-color'))
|
||||
watch(dark, () => updateThemeColor(), { immediate: true })
|
||||
onMounted(() => updateThemeColor())
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user