From 37067da07357db5d7fc3d25213193494fcb4a6bc Mon Sep 17 00:00:00 2001 From: Warinyourself Date: Sun, 14 Jun 2026 01:53:13 +0300 Subject: [PATCH] Move query sync to a reactive useQuerySync composable --- src/App.tsx | 2 + .../base/settings/SettingsCustom.tsx | 6 +-- src/composables/useQuerySync.ts | 49 +++++++++++++++++++ src/store/app.ts | 45 +++-------------- 4 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 src/composables/useQuerySync.ts diff --git a/src/App.tsx b/src/App.tsx index 20ec8a8..b92af20 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { defineComponent, watch } from 'vue' import { useMagicKeys, useDebounceFn, whenever } from '@vueuse/core' import { useAppStore } from '@/store/app' import { usePageStore } from '@/store/page' +import { useQuerySync } from '@/composables/useQuerySync' import { focusInputPassword, setCSSVariable } from '@/utils/helper' import { hotkeys, toMagicKeyCombo } from '@/utils/hotkeys' @@ -44,6 +45,7 @@ export default defineComponent({ } appStore.setUpSettings() + useQuerySync() initKeybinds() initZoom() diff --git a/src/components/base/settings/SettingsCustom.tsx b/src/components/base/settings/SettingsCustom.tsx index ea0d401..b33ea5a 100644 --- a/src/components/base/settings/SettingsCustom.tsx +++ b/src/components/base/settings/SettingsCustom.tsx @@ -1,6 +1,5 @@ -import { defineComponent, computed, onUpdated, type VNode } from 'vue' +import { defineComponent, computed, type VNode } from 'vue' import { useI18n } from 'vue-i18n' -import { useDebounceFn } from '@vueuse/core' import { useAppStore } from '@/store/app' import AppSlider from '@/components/app/AppSlider' import AppButton from '@/components/app/AppButton' @@ -24,9 +23,6 @@ export default defineComponent({ const { t } = useI18n() const inputs = computed(() => appStore.activeTheme?.settings || []) - const debouncedSync = useDebounceFn(() => appStore.syncStoreWithQuery(), 300) - - onUpdated(() => debouncedSync()) const buildSlider = (input: AppInputThemeSlider) => { const { label, value, options: { step, min: from, max: to } } = input diff --git a/src/composables/useQuerySync.ts b/src/composables/useQuerySync.ts new file mode 100644 index 0000000..b18644c --- /dev/null +++ b/src/composables/useQuerySync.ts @@ -0,0 +1,49 @@ +import { watch } from 'vue' +import { useDebounceFn } from '@vueuse/core' +import router from '@/router' +import { useAppStore } from '@/store/app' +import { isDifferentRoute, parseQueryValue } from '@/utils/helper' + +export function useQuerySync() { + const appStore = useAppStore() + + const applyQueryToStore = () => { + const query = router.currentRoute.value.query + + if (query.themeName && appStore.getThemeByName(query.themeName as string)) { + appStore.currentTheme = query.themeName as string + } + + appStore.activeTheme.settings = appStore.activeTheme.settings?.map((input) => { + if (!(input.name in query)) return input + return { ...input, value: parseQueryValue(query[input.name] as string) } + }) + } + + const syncQueryFromStore = () => { + const route = router.currentRoute.value + + const inputQuery = appStore.activeTheme.settings?.reduce>((query, input) => { + query[input.name] = input.value + '' + return query + }, {}) + + const bodyClassQuery = Object.entries(appStore.bodyClass).reduce>((query, [key, value]) => { + query[key] = value + '' + return query + }, {}) + + const query = { ...inputQuery, ...bodyClassQuery, themeName: appStore.currentTheme } + const routeTo = { name: route.name || '/', query } + + if (isDifferentRoute(routeTo)) router.replace(routeTo) + } + + applyQueryToStore() + + watch( + () => [appStore.activeTheme.settings, appStore.bodyClass, appStore.currentTheme], + useDebounceFn(syncQueryFromStore, 300), + { deep: true } + ) +} diff --git a/src/store/app.ts b/src/store/app.ts index 4f8d929..1d977e4 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -1,11 +1,9 @@ import { defineStore } from 'pinia' -import type { RouteLocationNormalized } from 'vue-router' -import router from '@/router' import type { AppTheme, AppSettings, AppInputTheme, AppInputThemeValue } from '@/models/app' import type { LightdmSession, LightdmUsers } from '@/models/lightdm' -import { isDifferentRoute, parseQueryValue, randomizeSettingsTheme, setCSSVariable } from '@/utils/helper' +import { randomizeSettingsTheme, setCSSVariable } from '@/utils/helper' import { AppThemes, defaultTheme } from '@/utils/constant' import { LightdmHandler } from '@/utils/lightdm' import { version } from '../../package.json' @@ -73,7 +71,6 @@ export const useAppStore = defineStore('app', { randomizeSettingsTheme() { const theme = this.activeTheme theme.settings = randomizeSettingsTheme(theme as AppTheme) - this.syncStoreWithQuery() }, async changeTheme(themeName: string, themeSettings?: AppTheme['settings']) { @@ -116,7 +113,6 @@ export const useAppStore = defineStore('app', { saveStateApp({ key, value }: { key: string; value: string }) { (this as any)[key] = value localStorage.setItem(key, value) - this.syncStoreWithQuery() }, syncSettingsWithCache() { @@ -128,31 +124,10 @@ export const useAppStore = defineStore('app', { setCSSVariable('--color-bg', color.background) }, - syncStoreWithQuery() { - const route = router.currentRoute.value + syncThemeWithStore(settings: AppSettings) { + const themeName = settings.currentTheme - const inputQuery = this.activeTheme.settings?.reduce>((query, input) => { - query[input.name] = input.value + '' - return query - }, {}) - - const bodyClassQuery = Object.entries(this.bodyClass).reduce>((query, [key, value]) => { - query[key] = value + '' - return query - }, {}) - - const query = { ...inputQuery, ...bodyClassQuery, themeName: this.currentTheme } - const routeTo = { name: route.name || '/', query } - - if (isDifferentRoute(routeTo)) { - router.replace(routeTo) - } - }, - - syncThemeWithStore({ settings, query }: { settings: AppSettings; query: RouteLocationNormalized['query'] }) { - let themeName = (query.themeName as string) || settings.currentTheme - - const syncTheme = this.themes.reduce((themes: AppTheme[], theme, index) => { + const syncTheme = this.themes.reduce((themes: AppTheme[], theme) => { const cachedTheme = settings.themes.find(({ name }) => name === theme.name) const isActiveTheme = theme.name === themeName const hasCachedTheme = cachedTheme && cachedTheme.settings @@ -160,13 +135,7 @@ export const useAppStore = defineStore('app', { if (hasCachedTheme) { theme.settings = theme.settings?.map((input) => { const cachedInput = this.getThemeInput(input.name, cachedTheme) - let value = cachedInput?.value ?? input.value - - if (isActiveTheme) { - const queryInput = input.name in query ? parseQueryValue(query[input.name] as string) : null - value = queryInput ?? value - } - + const value = cachedInput?.value ?? input.value return { ...input, value } }) } @@ -181,12 +150,10 @@ export const useAppStore = defineStore('app', { }, setUpSettings() { - const query = router.currentRoute.value.query - try { const settings: AppSettings = JSON.parse(localStorage.getItem('settings') || '{}') - if (settings.themes) this.syncThemeWithStore({ settings, query }) + if (settings.themes) this.syncThemeWithStore(settings) const isExistDE = window.lightdm?.sessions.find(({ key }) => key === settings.desktop) if (!isExistDE) settings.desktop = window.lightdm?.sessions[0]?.key || 'openbox'