From 1d44f1a705f9044e8cf657940c7e21179d8e0a15 Mon Sep 17 00:00:00 2001 From: Warinyourself Date: Sat, 20 Jun 2026 00:03:18 +0300 Subject: [PATCH] Break circular dependency by extracting theme utils and DOM helpers --- src/store/theme.ts | 3 +- src/utils/constant.ts | 2 +- src/utils/dom.ts | 3 ++ src/utils/helper.ts | 78 ++-------------------------------------- src/utils/hotkeys.ts | 6 ++-- src/utils/themeInputs.ts | 70 ++++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 src/utils/dom.ts create mode 100644 src/utils/themeInputs.ts diff --git a/src/store/theme.ts b/src/store/theme.ts index 34f15cb..c30e2e1 100644 --- a/src/store/theme.ts +++ b/src/store/theme.ts @@ -3,7 +3,8 @@ import { computed, ref } from 'vue' import type { AppTheme, AppSettings, AppInputTheme, AppInputThemeValue } from '@/models/app' -import { randomizeSettingsTheme as buildRandomThemeSettings, setCSSVariable } from '@/utils/helper' +import { randomizeSettingsTheme as buildRandomThemeSettings } from '@/utils/themeInputs' +import { setCSSVariable } from '@/utils/dom' import { AppThemes, defaultTheme } from '@/utils/constant' export const useThemeStore = defineStore('theme', () => { diff --git a/src/utils/constant.ts b/src/utils/constant.ts index d2854ad..4c02f54 100644 --- a/src/utils/constant.ts +++ b/src/utils/constant.ts @@ -6,7 +6,7 @@ import { brightnessSlider, buildInputSlider, buildInvertCheckbox, -} from './helper' +} from './themeInputs' const background = '#22233D' diff --git a/src/utils/dom.ts b/src/utils/dom.ts new file mode 100644 index 0000000..8b0f631 --- /dev/null +++ b/src/utils/dom.ts @@ -0,0 +1,3 @@ +export function setCSSVariable(property: string, value: string) { + document.documentElement.style.setProperty(property, value) +} diff --git a/src/utils/helper.ts b/src/utils/helper.ts index a7b22fc..59d13f3 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -1,4 +1,3 @@ -import type { AppInputButton, AppInputThemeGeneral, AppInputThemePalette, AppInputThemeSlider, AppTheme } from '@/models/app' import type { RouteLocationRaw } from 'vue-router' import router from '@/router' import { LightdmHandler } from '@/utils/lightdm' @@ -7,9 +6,11 @@ import { LightdmHandler } from '@/utils/lightdm' // This is safe thanks to ES module live bindings (no circular dep issue at runtime) import { useAppStore } from '@/store/app' import { usePageStore } from '@/store/page' -import { useThemeStore } from '@/store/theme' + +export { setCSSVariable } from '@/utils/dom' export const modKey = 'ctrl' + export const languageMap: Record = { ru: 'Русский', en: 'English', @@ -33,23 +34,6 @@ export function parseQueryValue(value: string) { return value } -export function randomize(min: number, max: number) { - return Math.random() * (max - min) + min -} - -export function generateRandomSliderValue(input: AppInputThemeSlider) { - const ignoreSliders = ['pxratio', 'brightness'] - if (ignoreSliders.includes(input.name)) return input.value - - const { min, max } = input.options - const decimalPlaces = ((input.options.step + '').split('.')[1] || '').length - return +(randomize(min, max).toFixed(decimalPlaces)) -} - -export function generateRandomColor() { - return '#' + Math.floor(Math.random() * 2 ** 24 - 1).toString(16) -} - export function getDesktopIcon(desktop = '') { const iconMap: Record = { gnome: /gnome/, @@ -116,59 +100,3 @@ export function stopPropagation(event: Event, callback?: () => void): void { export function hasSomeParentClass(element: HTMLElement, tag: string): boolean { return !!element.closest(tag) } - -export function randomizeSettingsTheme(theme: AppTheme) { - const generateValue: Record any> = { - slider: (input: AppInputThemeSlider) => generateRandomSliderValue(input), - checkbox: () => Math.random() > 0.5, - color: () => generateRandomColor(), - palette: (input: AppInputThemePalette) => Math.floor(randomize(0, (input.values?.length || 2) - 1)) - } - - return theme.settings?.map((input) => { - const fn = generateValue[input.type] - if (fn) input.value = fn(input) - return input - }) -} - -export function setCSSVariable(property: string, value: string) { - document.documentElement.style.setProperty(property, value) -} - -export const randomButton: AppInputButton = { - name: 'button', - value: 'button', - label: 'input.random', - type: 'button', - icon: 'random', - callback() { - useThemeStore().randomizeSettingsTheme() - } -} - -export function buildInputSlider({ - name = 'animation-speed', - value = 5, - min = 1, - max = 10, - step = 0.01, - icon = 'time', - changeOnUpdate = true -} = {}): AppInputThemeSlider { - return { name, label: `input.${name}`, value, icon, type: 'slider', options: { changeOnUpdate, max, step, min } } -} - -export function buildInputColor({ name = 'active-color', value = '#00CC99', ...options } = {}): AppInputThemeGeneral { - return { name, value, label: `input.${name}`, type: 'color', ...options } -} - -export const pxratio = () => buildInputSlider({ name: 'pxratio', icon: 'pxratio', min: 0.01, max: 1, value: 0.8 }) -export const hueSlider = () => buildInputSlider({ name: 'hue', min: 1, max: 360, step: 1, value: 0 }) -export const brightnessSlider = () => buildInputSlider({ name: 'brightness', min: 0, max: 1, step: 0.01, value: 1 }) -export const buildInvertCheckbox = (): AppInputThemeGeneral => ({ - name: 'invert', - label: 'input.invert', - type: 'checkbox', - value: false -}) diff --git a/src/utils/hotkeys.ts b/src/utils/hotkeys.ts index 6e5a1aa..4940e95 100644 --- a/src/utils/hotkeys.ts +++ b/src/utils/hotkeys.ts @@ -62,17 +62,17 @@ export const hotkeys = [ { keys: [modKey, 'P'], title: `${prefixTitle}poweroff`, - callback: systemActionsObject.shutdown + callback: systemActionsObject?.shutdown }, { keys: [modKey, 'R'], title: `${prefixTitle}restart`, - callback: systemActionsObject.restart + callback: systemActionsObject?.restart }, { keys: [modKey, 'S'], title: `${prefixTitle}suspend`, - callback: systemActionsObject.suspend + callback: systemActionsObject?.suspend } ] diff --git a/src/utils/themeInputs.ts b/src/utils/themeInputs.ts new file mode 100644 index 0000000..c96f8de --- /dev/null +++ b/src/utils/themeInputs.ts @@ -0,0 +1,70 @@ +import type { AppInputButton, AppInputThemeGeneral, AppInputThemePalette, AppInputThemeSlider, AppTheme } from '@/models/app' + +export function randomize(min: number, max: number) { + return Math.random() * (max - min) + min +} + +export function generateRandomSliderValue(input: AppInputThemeSlider) { + const ignoreSliders = ['pxratio', 'brightness'] + if (ignoreSliders.includes(input.name)) return input.value + + const { min, max } = input.options + const decimalPlaces = ((input.options.step + '').split('.')[1] || '').length + return +(randomize(min, max).toFixed(decimalPlaces)) +} + +export function generateRandomColor() { + return '#' + Math.floor(Math.random() * 2 ** 24 - 1).toString(16) +} + +export function randomizeSettingsTheme(theme: AppTheme) { + const generateValue: Record any> = { + slider: (input: AppInputThemeSlider) => generateRandomSliderValue(input), + checkbox: () => Math.random() > 0.5, + color: () => generateRandomColor(), + palette: (input: AppInputThemePalette) => Math.floor(randomize(0, (input.values?.length || 2) - 1)) + } + + return theme.settings?.map((input) => { + const fn = generateValue[input.type] + if (fn) input.value = fn(input) + return input + }) +} + +export const randomButton: AppInputButton = { + name: 'button', + value: 'button', + label: 'input.random', + type: 'button', + icon: 'random', + callback() { + void import('@/store/theme').then(({ useThemeStore }) => useThemeStore().randomizeSettingsTheme()) + } +} + +export function buildInputSlider({ + name = 'animation-speed', + value = 5, + min = 1, + max = 10, + step = 0.01, + icon = 'time', + changeOnUpdate = true +} = {}): AppInputThemeSlider { + return { name, label: `input.${name}`, value, icon, type: 'slider', options: { changeOnUpdate, max, step, min } } +} + +export function buildInputColor({ name = 'active-color', value = '#00CC99', ...options } = {}): AppInputThemeGeneral { + return { name, value, label: `input.${name}`, type: 'color', ...options } +} + +export const pxratio = () => buildInputSlider({ name: 'pxratio', icon: 'pxratio', min: 0.01, max: 1, value: 0.8 }) +export const hueSlider = () => buildInputSlider({ name: 'hue', min: 1, max: 360, step: 1, value: 0 }) +export const brightnessSlider = () => buildInputSlider({ name: 'brightness', min: 0, max: 1, step: 0.01, value: 1 }) +export const buildInvertCheckbox = (): AppInputThemeGeneral => ({ + name: 'invert', + label: 'input.invert', + type: 'checkbox', + value: false +})