// filepath: src/stores/settings.ts import { defineStore } from 'pinia' import { invoke } from '@tauri-apps/api/core' import { ref } from 'vue' import type { RuntimeStatus } from '../types/task' export interface Settings { download_path: string cookies_path?: string theme: 'light' | 'dark' | 'system' last_updated: string | null } export const useSettingsStore = defineStore('settings', () => { const settings = ref({ download_path: '', cookies_path: '', theme: 'system', last_updated: null }) const ytdlpVersion = ref('Checking...') const quickjsVersion = ref('Checking...') const ffmpegVersion = ref('Checking...') const runtimeStatus = ref(null) const isInitializing = ref(true) const hasInitialized = ref(false) let mediaQuery: MediaQueryList | null = null let mediaListener: (() => void) | null = null async function loadSettings() { try { const s = await invoke('get_settings') settings.value = s applyTheme(s.theme) } catch (e) { console.error("Failed to load settings", e) } } async function save() { try { await invoke('save_settings', { settings: settings.value }) applyTheme(settings.value.theme) } catch (e) { console.error("Failed to save settings", e) } } async function initYtdlp() { if (hasInitialized.value) return try { isInitializing.value = true // check/download await invoke('init_ytdlp') await refreshVersions() hasInitialized.value = true } catch (e) { console.error(e) ytdlpVersion.value = 'Error' quickjsVersion.value = 'Error' ffmpegVersion.value = 'Error' } finally { isInitializing.value = false } } async function refreshVersions() { const [ytdlp, quickjs, ffmpeg, runtime] = await Promise.allSettled([ invoke('get_ytdlp_version'), invoke('get_quickjs_version'), invoke('get_ffmpeg_version'), invoke('get_runtime_status') ]) ytdlpVersion.value = ytdlp.status === 'fulfilled' ? ytdlp.value : 'Error' quickjsVersion.value = quickjs.status === 'fulfilled' ? quickjs.value : 'Error' ffmpegVersion.value = ffmpeg.status === 'fulfilled' ? ffmpeg.value : 'Error' runtimeStatus.value = runtime.status === 'fulfilled' ? runtime.value : null } function applyTheme(theme: string) { const root = document.documentElement const isDark = theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) if (isDark) { root.classList.add('dark') } else { root.classList.remove('dark') } } function initThemeListener() { if (mediaQuery) return mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') mediaListener = () => { if (settings.value.theme === 'system') { applyTheme('system') } } mediaQuery.addEventListener('change', mediaListener) } function disposeThemeListener() { if (mediaQuery && mediaListener) { mediaQuery.removeEventListener('change', mediaListener) } mediaQuery = null mediaListener = null } return { settings, loadSettings, save, initYtdlp, refreshVersions, initThemeListener, disposeThemeListener, ytdlpVersion, quickjsVersion, ffmpegVersion, runtimeStatus, isInitializing } })