-
-
Notifications
You must be signed in to change notification settings - Fork 424
Expand file tree
/
Copy pathuseSettings.ts
More file actions
127 lines (110 loc) · 3.29 KB
/
useSettings.ts
File metadata and controls
127 lines (110 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import type { RemovableRef } from '@vueuse/core'
import { useLocalStorage } from '@vueuse/core'
import { ACCENT_COLORS } from '#shared/utils/constants'
import { BACKGROUND_THEMES } from '#shared/utils/constants'
import type { AccentColorId, BackgroundThemeId, AppSettings } from '#shared/schemas/app-settings'
const DEFAULT_SETTINGS: AppSettings = {
theme: 'system',
relativeDates: false,
includeTypesInInstall: true,
accentColorId: null,
hidePlatformPackages: true,
selectedLocale: null,
preferredBackgroundTheme: null,
sidebar: {
collapsed: [],
},
}
export const syncSettings = async (settings: AppSettings) => {
// DO some error handling
await $fetch('/api/auth/settings', {
method: 'POST',
body: settings,
})
}
const STORAGE_KEY = 'npmx-settings'
// Shared settings instance (singleton per app)
let settingsRef: RemovableRef<AppSettings> | null = null
/**
* Composable for managing application settings with localStorage persistence.
* Settings are shared across all components that use this composable.
*/
export function useSettings() {
if (!settingsRef) {
settingsRef = useLocalStorage<AppSettings>(STORAGE_KEY, DEFAULT_SETTINGS, {
mergeDefaults: true,
})
}
return {
settings: settingsRef,
}
}
/**
* Composable for accessing just the relative dates setting.
* Useful for components that only need to read this specific setting.
*/
export function useRelativeDates() {
const { settings } = useSettings()
return computed(() => settings.value.relativeDates)
}
/**
* Composable for managing accent color.
*/
export function useAccentColor() {
const { settings } = useSettings()
const colorMode = useColorMode()
const accentColors = computed(() => {
const isDark = colorMode.value === 'dark'
const colors = isDark ? ACCENT_COLORS.dark : ACCENT_COLORS.light
return Object.entries(colors).map(([id, value]) => ({
id: id as AccentColorId,
name: id,
value,
}))
})
function setAccentColor(id: AccentColorId | null) {
if (id) {
const isDark = colorMode.value === 'dark'
const color = isDark ? ACCENT_COLORS.dark[id] : ACCENT_COLORS.light[id]
document.documentElement.style.setProperty('--accent-color', color)
} else {
document.documentElement.style.removeProperty('--accent-color')
}
settings.value.accentColorId = id
}
// Update accent color when color mode changes
watch(
() => colorMode.value,
() => {
if (settings.value.accentColorId) {
setAccentColor(settings.value.accentColorId)
}
},
)
return {
accentColors,
selectedAccentColor: computed(() => settings.value.accentColorId),
setAccentColor,
}
}
export function useBackgroundTheme() {
const backgroundThemes = Object.entries(BACKGROUND_THEMES).map(([id, value]) => ({
id: id as BackgroundThemeId,
name: id,
value,
}))
const { settings } = useSettings()
function setBackgroundTheme(id: BackgroundThemeId | null) {
if (id) {
document.documentElement.dataset.bgTheme = id
} else {
document.documentElement.removeAttribute('data-bg-theme')
}
settings.value.preferredBackgroundTheme = id
}
return {
backgroundThemes,
selectedBackgroundTheme: computed(() => settings.value.preferredBackgroundTheme),
setBackgroundTheme,
}
}