import { defineStore } from 'pinia' import { ref, watch, computed } from 'vue' import { translations } from '../utils/i18n' // Settings persisted in localStorage under 'llm-in-text-settings' const SETTINGS_KEY = 'llm-in-text-settings' export const useSettingsStore = defineStore('settings', () => { // --- Reactive state (all auto-tracked by watch below) --- const theme = ref('system') // 'light' | 'dark' | 'system' const modelThinking = ref('low') // 'low' | 'medium' | 'high' const debounceMs = ref(1000) // 1000 - 5000 const proThinking = ref('medium') // 'low' | 'medium' | 'high' const privacyMode = ref(true) const language = ref('auto') const currency = ref('auto') const backgroundType = ref('default') // 'default' | 'warm' | 'reading' | 'image' const backgroundImage = ref('') const backgroundOpacity = ref(0.2) // 0.05 - 0.50 const ttsInstruct = ref('') // --- Computed getters (derived from reactive state) --- const uiLanguage = computed(() => { if (language.value !== 'auto') return language.value const sysLang = (navigator.language || navigator.userLanguage || 'en').split('-')[0] return ['zh', 'en', 'ja', 'ko', 'de', 'fr'].includes(sysLang) ? sysLang : 'en' }) const detectedTimezone = computed(() => Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC') const t = computed(() => ({ ...translations['en'], ...(translations[uiLanguage.value] || {}) })) const initialMarkdown = computed(() => translations[uiLanguage.value]?.initialMarkdown || translations['en']?.initialMarkdown || '') // --- localStorage persistence --- const loadSettings = () => { try { const stored = localStorage.getItem(SETTINGS_KEY) if (!stored) return const data = JSON.parse(stored) // Restore each field with type guards if (data.theme) theme.value = data.theme if (data.modelThinking) modelThinking.value = data.modelThinking if (data.debounceMs) debounceMs.value = data.debounceMs if (data.proThinking) proThinking.value = data.proThinking if (typeof data.privacyMode === 'boolean') privacyMode.value = data.privacyMode if (data.language) language.value = data.language if (data.currency) currency.value = data.currency if (data.backgroundType === 'color') backgroundType.value = 'default' else if (data.backgroundType) backgroundType.value = data.backgroundType if (data.backgroundImage) backgroundImage.value = data.backgroundImage if (data.backgroundOpacity) backgroundOpacity.value = data.backgroundOpacity if (typeof data.ttsInstruct === 'string') ttsInstruct.value = data.ttsInstruct } catch { /* use defaults */ } } const saveSettings = () => { try { localStorage.setItem(SETTINGS_KEY, JSON.stringify({ theme: theme.value, modelThinking: modelThinking.value, debounceMs: debounceMs.value, proThinking: proThinking.value, privacyMode: privacyMode.value, language: language.value, currency: currency.value, backgroundType: backgroundType.value, backgroundImage: backgroundImage.value, backgroundOpacity: backgroundOpacity.value, ttsInstruct: ttsInstruct.value, })) } catch { /* silently fail */ } } const resetSettings = () => { theme.value = 'system'; modelThinking.value = 'low'; debounceMs.value = 1000 proThinking.value = 'medium'; privacyMode.value = false; language.value = 'auto' currency.value = 'auto'; backgroundType.value = 'default'; backgroundImage.value = '' backgroundOpacity.value = 0.2; ttsInstruct.value = ''; saveSettings() } // Watch all reactive refs and auto-save on change watch([theme, modelThinking, debounceMs, proThinking, privacyMode, language, currency , backgroundType, backgroundImage, backgroundOpacity, ttsInstruct], saveSettings) loadSettings() // Initialize from localStorage return { theme, modelThinking, debounceMs, proThinking, privacyMode, language , currency, backgroundType, backgroundImage, backgroundOpacity, ttsInstruct , detectedTimezone, uiLanguage, t, initialMarkdown, resetSettings } })