Files
voidraft/frontend/src/stores/configStore.ts

254 lines
9.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {defineStore} from 'pinia';
import {computed, reactive} from 'vue';
import {ConfigService, StartupService} from '@/../bindings/voidraft/internal/services';
import {AppConfig, AuthMethod, LanguageType, SystemThemeType, TabType} from '@/../bindings/voidraft/internal/models/models';
import {useI18n} from 'vue-i18n';
import {ConfigUtils} from '@/common/utils/configUtils';
import {FONT_OPTIONS} from '@/common/constant/fonts';
import {
CONFIG_KEY_MAP,
CONFIG_LIMITS,
ConfigKey,
ConfigSection,
DEFAULT_CONFIG,
NumberConfigKey
} from '@/common/constant/config';
import * as runtime from '@wailsio/runtime';
export const useConfigStore = defineStore('config', () => {
const {locale} = useI18n();
// 响应式状态
const state = reactive({
config: {...DEFAULT_CONFIG} as AppConfig,
isLoading: false,
configLoaded: false
});
// Font options (no longer localized)
const fontOptions = computed(() => FONT_OPTIONS);
// 统一配置更新方法
const updateConfig = async <K extends ConfigKey>(key: K, value: any): Promise<void> => {
if (!state.configLoaded && !state.isLoading) {
await initConfig();
}
const backendKey = CONFIG_KEY_MAP[key];
if (!backendKey) {
throw new Error(`No backend key mapping found for ${String(key)}`);
}
// 从 backendKey 提取 section例如 'general.alwaysOnTop' -> 'general'
const section = backendKey.split('.')[0] as ConfigSection;
await ConfigService.Set(backendKey, value);
(state.config[section] as any)[key] = value;
};
// 只更新本地状态,不保存到后端
const updateConfigLocal = <K extends ConfigKey>(key: K, value: any): void => {
const backendKey = CONFIG_KEY_MAP[key];
const section = backendKey.split('.')[0] as ConfigSection;
(state.config[section] as any)[key] = value;
};
// 保存指定配置到后端
const saveConfig = async <K extends ConfigKey>(key: K): Promise<void> => {
const backendKey = CONFIG_KEY_MAP[key];
const section = backendKey.split('.')[0] as ConfigSection;
await ConfigService.Set(backendKey, (state.config[section] as any)[key]);
};
// 加载配置
const initConfig = async (): Promise<void> => {
if (state.isLoading) return;
state.isLoading = true;
try {
const appConfig = await ConfigService.GetConfig();
if (appConfig) {
// 合并配置
if (appConfig.general) Object.assign(state.config.general, appConfig.general);
if (appConfig.editing) Object.assign(state.config.editing, appConfig.editing);
if (appConfig.appearance) Object.assign(state.config.appearance, appConfig.appearance);
if (appConfig.updates) Object.assign(state.config.updates, appConfig.updates);
if (appConfig.backup) Object.assign(state.config.backup, appConfig.backup);
if (appConfig.metadata) Object.assign(state.config.metadata, appConfig.metadata);
}
state.configLoaded = true;
} finally {
state.isLoading = false;
}
};
// 重置配置
const resetConfig = async (): Promise<void> => {
if (state.isLoading) return;
state.isLoading = true;
try {
await ConfigService.ResetConfig();
const appConfig = await ConfigService.GetConfig();
if (appConfig) {
state.config = JSON.parse(JSON.stringify(appConfig)) as AppConfig;
}
} finally {
state.isLoading = false;
}
};
// 辅助函数:限制数值范围
const clampValue = (value: number, key: NumberConfigKey): number => {
const limit = CONFIG_LIMITS[key];
return ConfigUtils.clamp(value, limit.min, limit.max);
};
// 计算属性
const fontConfig = computed(() => ({
fontSize: state.config.editing.fontSize,
fontFamily: state.config.editing.fontFamily,
lineHeight: state.config.editing.lineHeight,
fontWeight: state.config.editing.fontWeight
}));
const tabConfig = computed(() => ({
tabSize: state.config.editing.tabSize,
enableTabIndent: state.config.editing.enableTabIndent,
tabType: state.config.editing.tabType
}));
return {
// 状态
config: computed(() => state.config),
configLoaded: computed(() => state.configLoaded),
isLoading: computed(() => state.isLoading),
fontOptions,
fontConfig,
tabConfig,
// 核心方法
initConfig,
resetConfig,
// 语言相关方法
setLanguage: (value: LanguageType) => {
updateConfig('language', value);
locale.value = value as any;
},
// 主题相关方法
setSystemTheme: (value: SystemThemeType) => updateConfig('systemTheme', value),
setCurrentTheme: (value: string) => updateConfig('currentTheme', value),
// 字体大小操作
setFontSize: async (value: number) => {
await updateConfig('fontSize', clampValue(value, 'fontSize'));
},
increaseFontSize: async () => {
const newValue = state.config.editing.fontSize + 1;
await updateConfig('fontSize', clampValue(newValue, 'fontSize'));
},
decreaseFontSize: async () => {
const newValue = state.config.editing.fontSize - 1;
await updateConfig('fontSize', clampValue(newValue, 'fontSize'));
},
resetFontSize: async () => {
await updateConfig('fontSize', CONFIG_LIMITS.fontSize.default);
},
increaseFontSizeLocal: () => {
updateConfigLocal('fontSize', clampValue(state.config.editing.fontSize + 1, 'fontSize'));
},
decreaseFontSizeLocal: () => {
updateConfigLocal('fontSize', clampValue(state.config.editing.fontSize - 1, 'fontSize'));
},
saveFontSize: async () => {
await saveConfig('fontSize');
},
// 字体操作
setFontFamily: (value: string) => updateConfig('fontFamily', value),
setFontWeight: (value: string) => updateConfig('fontWeight', value),
// 行高操作
setLineHeight: async (value: number) => {
await updateConfig('lineHeight', clampValue(value, 'lineHeight'));
},
// Tab操作
setEnableTabIndent: (value: boolean) => updateConfig('enableTabIndent', value),
setTabSize: async (value: number) => {
await updateConfig('tabSize', clampValue(value, 'tabSize'));
},
increaseTabSize: async () => {
const newValue = state.config.editing.tabSize + 1;
await updateConfig('tabSize', clampValue(newValue, 'tabSize'));
},
decreaseTabSize: async () => {
const newValue = state.config.editing.tabSize - 1;
await updateConfig('tabSize', clampValue(newValue, 'tabSize'));
},
toggleTabType: async () => {
const values = CONFIG_LIMITS.tabType.values;
const currentIndex = values.indexOf(state.config.editing.tabType as typeof values[number]);
const nextIndex = (currentIndex + 1) % values.length;
await updateConfig('tabType', values[nextIndex]);
},
// 窗口操作
toggleAlwaysOnTop: async () => {
await updateConfig('alwaysOnTop', !state.config.general.alwaysOnTop);
await runtime.Window.SetAlwaysOnTop(state.config.general.alwaysOnTop);
},
setAlwaysOnTop: (value: boolean) => updateConfig('alwaysOnTop', value),
// 路径操作
setDataPath: (value: string) => updateConfigLocal('dataPath', value),
// 保存配置相关方法
setAutoSaveDelay: (value: number) => updateConfig('autoSaveDelay', value),
// 热键配置相关方法
setEnableGlobalHotkey: (value: boolean) => updateConfig('enableGlobalHotkey', value),
setGlobalHotkey: (hotkey: any) => updateConfig('globalHotkey', hotkey),
// 系统托盘配置相关方法
setEnableSystemTray: (value: boolean) => updateConfig('enableSystemTray', value),
// 开机启动配置相关方法
setStartAtLogin: async (value: boolean) => {
await updateConfig('startAtLogin', value);
await StartupService.SetEnabled(value);
},
// 窗口吸附配置相关方法
setEnableWindowSnap: (value: boolean) => updateConfig('enableWindowSnap', value),
// 加载动画配置相关方法
setEnableLoadingAnimation: (value: boolean) => updateConfig('enableLoadingAnimation', value),
// 标签页配置相关方法
setEnableTabs: (value: boolean) => updateConfig('enableTabs', value),
// 快捷键模式配置相关方法
setKeymapMode: (value: any) => updateConfig('keymapMode', value),
// 更新配置相关方法
setAutoUpdate: (value: boolean) => updateConfig('autoUpdate', value),
// 备份配置相关方法
setEnableBackup: (value: boolean) => updateConfig('enabled', value),
setAutoBackup: (value: boolean) => updateConfig('auto_backup', value),
setRepoUrl: (value: string) => updateConfig('repo_url', value),
setAuthMethod: (value: AuthMethod) => updateConfig('auth_method', value),
setUsername: (value: string) => updateConfig('username', value),
setPassword: (value: string) => updateConfig('password', value),
setToken: (value: string) => updateConfig('token', value),
setSshKeyPath: (value: string) => updateConfig('ssh_key_path', value),
setSshKeyPassphrase: (value: string) => updateConfig('ssh_key_passphrase', value),
setBackupInterval: (value: number) => updateConfig('backup_interval', value),
};
});