import { ref, computed, watch } from 'vue' import { defineStore } from 'pinia' import type { ContentTab } from '@/composables/contentFiltering' const STORAGE_KEY = 'aiui-settings' export interface AppSettings { // M15.1 — Accent colour accentColor: string // M15.2 — Glass intensity glassIntensity: 'subtle' | 'default' | 'strong' // M15.3 — Font size fontSize: 'compact' | 'default' | 'large' // M15.4 — Content type visibility hiddenContentTabs: ContentTab[] // M15.5 — Keyboard shortcuts shortcuts: Record // M15.6 — Push notifications notificationsEnabled: boolean // M15.7 — Auto-archive autoArchiveDays: number // 0 = never, 7/30/90 // M15.10 — Default conversation settings defaultModel: string defaultPersonaId: string defaultWebSearch: boolean defaultShowTokens: boolean } const DEFAULT_SETTINGS: AppSettings = { accentColor: '#F7931A', glassIntensity: 'default', fontSize: 'default', hiddenContentTabs: [], shortcuts: { 'send-message': 'Enter', 'new-line': 'Shift+Enter', 'search': 'Cmd+F', 'new-chat': 'Cmd+N', 'settings': 'Cmd+,', 'close-panel': 'Escape', }, notificationsEnabled: false, autoArchiveDays: 0, defaultModel: '', defaultPersonaId: '', defaultWebSearch: false, defaultShowTokens: false, } export const useSettingsStore = defineStore('settings', () => { const settings = ref(loadSettings()) function loadSettings(): AppSettings { try { const stored = localStorage.getItem(STORAGE_KEY) if (stored) return { ...DEFAULT_SETTINGS, ...JSON.parse(stored) } } catch { /* ignore */ } return { ...DEFAULT_SETTINGS } } function save() { localStorage.setItem(STORAGE_KEY, JSON.stringify(settings.value)) } // Apply CSS variables when settings change function applyCssVars() { const root = document.documentElement // Accent colour root.style.setProperty('--color-accent', settings.value.accentColor) // Glass intensity const glass = { subtle: { blur: '12px', opacity: '0.25' }, default: { blur: '18px', opacity: '0.35' }, strong: { blur: '28px', opacity: '0.50' }, }[settings.value.glassIntensity] root.style.setProperty('--glass-blur', glass.blur) root.style.setProperty('--glass-opacity', glass.opacity) // Font size const sizes = { compact: '13px', default: '15px', large: '17px' } root.style.setProperty('--font-size-base', sizes[settings.value.fontSize]) } // Watch for changes and persist + apply watch(settings, () => { save() applyCssVars() }, { deep: true }) // Apply on init applyCssVars() const accentColor = computed({ get: () => settings.value.accentColor, set: (v) => { settings.value.accentColor = v }, }) const glassIntensity = computed({ get: () => settings.value.glassIntensity, set: (v) => { settings.value.glassIntensity = v }, }) const fontSize = computed({ get: () => settings.value.fontSize, set: (v) => { settings.value.fontSize = v }, }) const hiddenContentTabs = computed({ get: () => settings.value.hiddenContentTabs, set: (v) => { settings.value.hiddenContentTabs = v }, }) const notificationsEnabled = computed({ get: () => settings.value.notificationsEnabled, set: (v) => { settings.value.notificationsEnabled = v }, }) const autoArchiveDays = computed({ get: () => settings.value.autoArchiveDays, set: (v) => { settings.value.autoArchiveDays = v }, }) function isTabVisible(tab: ContentTab): boolean { return !settings.value.hiddenContentTabs.includes(tab) } function toggleTabVisibility(tab: ContentTab) { const idx = settings.value.hiddenContentTabs.indexOf(tab) if (idx >= 0) { settings.value.hiddenContentTabs.splice(idx, 1) } else { settings.value.hiddenContentTabs.push(tab) } } function setShortcut(action: string, binding: string) { settings.value.shortcuts[action] = binding } function resetSettings() { settings.value = { ...DEFAULT_SETTINGS } } return { settings, accentColor, glassIntensity, fontSize, hiddenContentTabs, notificationsEnabled, autoArchiveDays, isTabVisible, toggleTabVisibility, setShortcut, resetSettings, applyCssVars, } })