diff --git a/packages/shared/config/constant.ts b/packages/shared/config/constant.ts index 18246cd1e7..11e6bd829c 100644 --- a/packages/shared/config/constant.ts +++ b/packages/shared/config/constant.ts @@ -197,11 +197,11 @@ export enum FeedUrl { GITHUB_LATEST = 'https://github.com/CherryHQ/cherry-studio/releases/latest/download' } -export enum UpgradeChannel { - LATEST = 'latest', // 最新稳定版本 - RC = 'rc', // 公测版本 - BETA = 'beta' // 预览版本 -} +// export enum UpgradeChannel { +// LATEST = 'latest', // 最新稳定版本 +// RC = 'rc', // 公测版本 +// BETA = 'beta' // 预览版本 +// } export const defaultTimeout = 10 * 1000 * 60 diff --git a/packages/shared/data/preferenceTypes.ts b/packages/shared/data/preferenceTypes.ts index b5f635b1d1..c9fa7af058 100644 --- a/packages/shared/data/preferenceTypes.ts +++ b/packages/shared/data/preferenceTypes.ts @@ -59,3 +59,9 @@ export type AssistantIconType = 'model' | 'emoji' | 'none' export type ProxyMode = 'system' | 'custom' | 'none' export type MultiModelFoldDisplayMode = 'expanded' | 'compact' + +export enum UpgradeChannel { + LATEST = 'latest', // 最新稳定版本 + RC = 'rc', // 公测版本 + BETA = 'beta' // 预览版本 +} diff --git a/packages/shared/data/preferences.ts b/packages/shared/data/preferences.ts index d1668e9122..d44284a37d 100644 --- a/packages/shared/data/preferences.ts +++ b/packages/shared/data/preferences.ts @@ -1,6 +1,6 @@ /** * Auto-generated preferences configuration - * Generated at: 2025-09-02T11:59:32.955Z + * Generated at: 2025-09-03T04:46:03.708Z * * This file is automatically generated from classification.json * To update this file, modify classification.json and run: @@ -22,7 +22,7 @@ import type { SidebarIcon, WindowStyle } from '@shared/data/preferenceTypes' -import { LanguageVarious, ThemeMode } from '@shared/data/preferenceTypes' +import { LanguageVarious, ThemeMode, UpgradeChannel } from '@shared/data/preferenceTypes' /* eslint @typescript-eslint/member-ordering: ["error", { "interfaces": { "order": "alphabetically" }, @@ -38,7 +38,7 @@ export interface PreferencesType { // redux/settings/autoCheckUpdate 'app.dist.auto_update.enabled': boolean // redux/settings/testChannel - 'app.dist.test_plan.channel': string + 'app.dist.test_plan.channel': UpgradeChannel // redux/settings/testPlan 'app.dist.test_plan.enabled': boolean // redux/settings/language @@ -180,17 +180,17 @@ export interface PreferencesType { // redux/settings/localBackupSyncInterval 'data.backup.local.sync_interval': number // redux/nutstore/nutstoreAutoSync - 'data.backup.nutstore.auto_sync': boolean | null + 'data.backup.nutstore.auto_sync': boolean + // redux/nutstore/nutstoreMaxBackups + 'data.backup.nutstore.max_backups': number // redux/nutstore/nutstorePath - 'data.backup.nutstore.path': string | null + 'data.backup.nutstore.path': string // redux/nutstore/nutstoreSkipBackupFile - 'data.backup.nutstore.skip_backup_file': boolean | null + 'data.backup.nutstore.skip_backup_file': boolean // redux/nutstore/nutstoreSyncInterval - 'data.backup.nutstore.sync_interval': number | null - // redux/nutstore/nutstoreSyncState - 'data.backup.nutstore.sync_state': Record | null + 'data.backup.nutstore.sync_interval': number // redux/nutstore/nutstoreToken - 'data.backup.nutstore.token': string | null + 'data.backup.nutstore.token': string // redux/settings/s3.accessKeyId 'data.backup.s3.access_key_id': string // redux/settings/s3.autoSync @@ -278,7 +278,7 @@ export interface PreferencesType { // redux/settings/notionPageNameKey 'data.integration.notion.page_name_key': string // redux/settings/defaultObsidianVault - 'data.integration.obsidian.default_vault': string | null + 'data.integration.obsidian.default_vault': string // redux/settings/siyuanApiUrl 'data.integration.siyuan.api_url': string | null // redux/settings/siyuanBoxId @@ -408,7 +408,7 @@ export const DefaultPreferences: PreferencesType = { 'app.developer_mode.enabled': false, 'app.disable_hardware_acceleration': false, 'app.dist.auto_update.enabled': true, - 'app.dist.test_plan.channel': 'UpgradeChannel.LATEST', + 'app.dist.test_plan.channel': UpgradeChannel.LATEST, 'app.dist.test_plan.enabled': false, 'app.language': null, 'app.launch_on_boot': false, @@ -479,12 +479,12 @@ export const DefaultPreferences: PreferencesType = { 'data.backup.local.max_backups': 0, 'data.backup.local.skip_backup_file': false, 'data.backup.local.sync_interval': 0, - 'data.backup.nutstore.auto_sync': null, - 'data.backup.nutstore.path': null, - 'data.backup.nutstore.skip_backup_file': null, - 'data.backup.nutstore.sync_interval': null, - 'data.backup.nutstore.sync_state': null, - 'data.backup.nutstore.token': null, + 'data.backup.nutstore.auto_sync': false, + 'data.backup.nutstore.max_backups': 0, + 'data.backup.nutstore.path': '/cherry-studio', + 'data.backup.nutstore.skip_backup_file': false, + 'data.backup.nutstore.sync_interval': 0, + 'data.backup.nutstore.token': '', 'data.backup.s3.access_key_id': '', 'data.backup.s3.auto_sync': false, 'data.backup.s3.bucket': '', @@ -528,7 +528,7 @@ export const DefaultPreferences: PreferencesType = { 'data.integration.notion.database_id': '', 'data.integration.notion.export_reasoning': false, 'data.integration.notion.page_name_key': 'Name', - 'data.integration.obsidian.default_vault': null, + 'data.integration.obsidian.default_vault': '', 'data.integration.siyuan.api_url': null, 'data.integration.siyuan.box_id': null, 'data.integration.siyuan.root_path': null, diff --git a/src/main/index.ts b/src/main/index.ts index 642e231cb2..e45ab55f25 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -157,6 +157,8 @@ if (!app.requestSingleInstanceLock()) { return } + // DATA REFACTOR USE + // TODO: remove when data refactor is stable //************FOR TESTING ONLY START****************/ await preferenceService.initialize() @@ -177,7 +179,7 @@ if (!app.requestSingleInstanceLock()) { electronApp.setAppUserModelId(import.meta.env.VITE_MAIN_BUNDLE_ID || 'com.kangfenmao.CherryStudio') // Mac: Hide dock icon before window creation when launch to tray is set - const isLaunchToTray = configManager.getLaunchToTray() + const isLaunchToTray = preferenceService.get('app.tray.on_launch') if (isLaunchToTray) { app.dock?.hide() } diff --git a/src/main/ipc.ts b/src/main/ipc.ts index f7ef702e20..069b160e4d 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -3,13 +3,15 @@ import { arch } from 'node:os' import path from 'node:path' import { PreferenceService } from '@data/PreferenceService' +import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { isLinux, isMac, isPortable, isWin } from '@main/constant' import { generateSignature } from '@main/integration/cherryin' import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process' import { handleZoomFactor } from '@main/utils/zoom' import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core' -import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, UpgradeChannel } from '@shared/config/constant' +import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH } from '@shared/config/constant' +import { UpgradeChannel } from '@shared/data/preferenceTypes' import { IpcChannel } from '@shared/IpcChannel' import { FileMetadata, Provider, Shortcut } from '@types' import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron' @@ -159,40 +161,38 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { appService.setAppLaunchOnBoot(isLaunchOnBoot) }) - // launch to tray - ipcMain.handle(IpcChannel.App_SetLaunchToTray, (_, isActive: boolean) => { - configManager.setLaunchToTray(isActive) - }) + // // launch to tray + // ipcMain.handle(IpcChannel.App_SetLaunchToTray, (_, isActive: boolean) => { + // configManager.setLaunchToTray(isActive) + // }) - // tray - ipcMain.handle(IpcChannel.App_SetTray, (_, isActive: boolean) => { - configManager.setTray(isActive) - }) + // // tray + // ipcMain.handle(IpcChannel.App_SetTray, (_, isActive: boolean) => { + // configManager.setTray(isActive) + // }) - // to tray on close - ipcMain.handle(IpcChannel.App_SetTrayOnClose, (_, isActive: boolean) => { - configManager.setTrayOnClose(isActive) - }) + // // to tray on close + // ipcMain.handle(IpcChannel.App_SetTrayOnClose, (_, isActive: boolean) => { + // configManager.setTrayOnClose(isActive) + // }) - // auto update - ipcMain.handle(IpcChannel.App_SetAutoUpdate, (_, isActive: boolean) => { - appUpdater.setAutoUpdate(isActive) - configManager.setAutoUpdate(isActive) - }) + // // auto update + // ipcMain.handle(IpcChannel.App_SetAutoUpdate, (_, isActive: boolean) => { + // appUpdater.setAutoUpdate(isActive) + // configManager.setAutoUpdate(isActive) + // }) ipcMain.handle(IpcChannel.App_SetTestPlan, async (_, isActive: boolean) => { logger.info(`set test plan: ${isActive}`) - if (isActive !== configManager.getTestPlan()) { + if (isActive !== preferenceService.get('app.dist.test_plan.enabled')) { appUpdater.cancelDownload() - configManager.setTestPlan(isActive) } }) ipcMain.handle(IpcChannel.App_SetTestChannel, async (_, channel: UpgradeChannel) => { logger.info(`set test channel: ${channel}`) - if (channel !== configManager.getTestChannel()) { + if (channel !== preferenceService.get('app.dist.test_plan.channel')) { appUpdater.cancelDownload() - configManager.setTestChannel(channel) } }) diff --git a/src/main/services/AppUpdater.ts b/src/main/services/AppUpdater.ts index a38b2e087d..37733e2ec9 100644 --- a/src/main/services/AppUpdater.ts +++ b/src/main/services/AppUpdater.ts @@ -1,9 +1,11 @@ +import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { isWin } from '@main/constant' import { getIpCountry } from '@main/utils/ipService' import { getI18n } from '@main/utils/language' import { generateUserAgent } from '@main/utils/systemInfo' -import { FeedUrl, UpgradeChannel } from '@shared/config/constant' +import { FeedUrl } from '@shared/config/constant' +import { UpgradeChannel } from '@shared/data/preferenceTypes' import { IpcChannel } from '@shared/IpcChannel' import { CancellationToken, UpdateInfo } from 'builder-util-runtime' import { app, BrowserWindow, dialog, net } from 'electron' @@ -12,7 +14,6 @@ import path from 'path' import semver from 'semver' import icon from '../../../build/icon.png?asset' -import { configManager } from './ConfigManager' import { windowService } from './WindowService' const logger = loggerService.withContext('AppUpdater') @@ -26,8 +27,8 @@ export default class AppUpdater { constructor() { autoUpdater.logger = logger as Logger autoUpdater.forceDevUpdateConfig = !app.isPackaged - autoUpdater.autoDownload = configManager.getAutoUpdate() - autoUpdater.autoInstallOnAppQuit = configManager.getAutoUpdate() + autoUpdater.autoDownload = preferenceService.get('app.dist.auto_update.enabled') + autoUpdater.autoInstallOnAppQuit = preferenceService.get('app.dist.auto_update.enabled') autoUpdater.requestHeaders = { ...autoUpdater.requestHeaders, 'User-Agent': generateUserAgent() @@ -139,7 +140,7 @@ export default class AppUpdater { private _getTestChannel() { const currentChannel = this._getChannelByVersion(app.getVersion()) - const savedChannel = configManager.getTestChannel() + const savedChannel = preferenceService.get('app.dist.test_plan.channel') if (currentChannel === UpgradeChannel.LATEST) { return savedChannel || UpgradeChannel.RC @@ -164,7 +165,7 @@ export default class AppUpdater { } private async _setFeedUrl() { - const testPlan = configManager.getTestPlan() + const testPlan = preferenceService.get('app.dist.test_plan.enabled') if (testPlan) { const channel = this._getTestChannel() diff --git a/src/main/services/ConfigManager.ts b/src/main/services/ConfigManager.ts index a9d180e49b..599ea23ac7 100644 --- a/src/main/services/ConfigManager.ts +++ b/src/main/services/ConfigManager.ts @@ -1,4 +1,4 @@ -import { UpgradeChannel, ZOOM_SHORTCUTS } from '@shared/config/constant' +import { ZOOM_SHORTCUTS } from '@shared/config/constant' import { Shortcut } from '@types' import Store from 'electron-store' @@ -52,29 +52,29 @@ export class ConfigManager { // this.set(ConfigKeys.Theme, theme) // } - getLaunchToTray(): boolean { - return !!this.get(ConfigKeys.LaunchToTray, false) - } + // getLaunchToTray(): boolean { + // return !!this.get(ConfigKeys.LaunchToTray, false) + // } - setLaunchToTray(value: boolean) { - this.set(ConfigKeys.LaunchToTray, value) - } + // setLaunchToTray(value: boolean) { + // this.set(ConfigKeys.LaunchToTray, value) + // } - getTray(): boolean { - return !!this.get(ConfigKeys.Tray, true) - } + // getTray(): boolean { + // return !!this.get(ConfigKeys.Tray, true) + // } - setTray(value: boolean) { - this.setAndNotify(ConfigKeys.Tray, value) - } + // setTray(value: boolean) { + // this.setAndNotify(ConfigKeys.Tray, value) + // } - getTrayOnClose(): boolean { - return !!this.get(ConfigKeys.TrayOnClose, true) - } + // getTrayOnClose(): boolean { + // return !!this.get(ConfigKeys.TrayOnClose, true) + // } - setTrayOnClose(value: boolean) { - this.set(ConfigKeys.TrayOnClose, value) - } + // setTrayOnClose(value: boolean) { + // this.set(ConfigKeys.TrayOnClose, value) + // } getZoomFactor(): number { return this.get(ConfigKeys.ZoomFactor, 1) @@ -119,104 +119,104 @@ export class ConfigManager { ) } - getClickTrayToShowQuickAssistant(): boolean { - return this.get(ConfigKeys.ClickTrayToShowQuickAssistant, false) - } + // getClickTrayToShowQuickAssistant(): boolean { + // return this.get(ConfigKeys.ClickTrayToShowQuickAssistant, false) + // } - setClickTrayToShowQuickAssistant(value: boolean) { - this.set(ConfigKeys.ClickTrayToShowQuickAssistant, value) - } + // setClickTrayToShowQuickAssistant(value: boolean) { + // this.set(ConfigKeys.ClickTrayToShowQuickAssistant, value) + // } - getEnableQuickAssistant(): boolean { - return this.get(ConfigKeys.EnableQuickAssistant, false) - } + // getEnableQuickAssistant(): boolean { + // return this.get(ConfigKeys.EnableQuickAssistant, false) + // } - setEnableQuickAssistant(value: boolean) { - this.setAndNotify(ConfigKeys.EnableQuickAssistant, value) - } + // setEnableQuickAssistant(value: boolean) { + // this.setAndNotify(ConfigKeys.EnableQuickAssistant, value) + // } - getAutoUpdate(): boolean { - return this.get(ConfigKeys.AutoUpdate, true) - } + // getAutoUpdate(): boolean { + // return this.get(ConfigKeys.AutoUpdate, true) + // } - setAutoUpdate(value: boolean) { - this.set(ConfigKeys.AutoUpdate, value) - } + // setAutoUpdate(value: boolean) { + // this.set(ConfigKeys.AutoUpdate, value) + // } - getTestPlan(): boolean { - return this.get(ConfigKeys.TestPlan, false) - } + // getTestPlan(): boolean { + // return this.get(ConfigKeys.TestPlan, false) + // } - setTestPlan(value: boolean) { - this.set(ConfigKeys.TestPlan, value) - } + // setTestPlan(value: boolean) { + // this.set(ConfigKeys.TestPlan, value) + // } - getTestChannel(): UpgradeChannel { - return this.get(ConfigKeys.TestChannel) - } + // getTestChannel(): UpgradeChannel { + // return this.get(ConfigKeys.TestChannel) + // } - setTestChannel(value: UpgradeChannel) { - this.set(ConfigKeys.TestChannel, value) - } + // setTestChannel(value: UpgradeChannel) { + // this.set(ConfigKeys.TestChannel, value) + // } - getEnableDataCollection(): boolean { - return this.get(ConfigKeys.EnableDataCollection, true) - } + // getEnableDataCollection(): boolean { + // return this.get(ConfigKeys.EnableDataCollection, true) + // } - setEnableDataCollection(value: boolean) { - this.set(ConfigKeys.EnableDataCollection, value) - } + // setEnableDataCollection(value: boolean) { + // this.set(ConfigKeys.EnableDataCollection, value) + // } - // Selection Assistant: is enabled the selection assistant - getSelectionAssistantEnabled(): boolean { - return this.get(ConfigKeys.SelectionAssistantEnabled, false) - } + // // Selection Assistant: is enabled the selection assistant + // getSelectionAssistantEnabled(): boolean { + // return this.get(ConfigKeys.SelectionAssistantEnabled, false) + // } - setSelectionAssistantEnabled(value: boolean) { - this.setAndNotify(ConfigKeys.SelectionAssistantEnabled, value) - } + // setSelectionAssistantEnabled(value: boolean) { + // this.setAndNotify(ConfigKeys.SelectionAssistantEnabled, value) + // } - // Selection Assistant: trigger mode (selected, ctrlkey) - getSelectionAssistantTriggerMode(): string { - return this.get(ConfigKeys.SelectionAssistantTriggerMode, 'selected') - } + // // Selection Assistant: trigger mode (selected, ctrlkey) + // getSelectionAssistantTriggerMode(): string { + // return this.get(ConfigKeys.SelectionAssistantTriggerMode, 'selected') + // } - setSelectionAssistantTriggerMode(value: string) { - this.setAndNotify(ConfigKeys.SelectionAssistantTriggerMode, value) - } + // setSelectionAssistantTriggerMode(value: string) { + // this.setAndNotify(ConfigKeys.SelectionAssistantTriggerMode, value) + // } - // Selection Assistant: if action window position follow toolbar - getSelectionAssistantFollowToolbar(): boolean { - return this.get(ConfigKeys.SelectionAssistantFollowToolbar, true) - } + // // Selection Assistant: if action window position follow toolbar + // getSelectionAssistantFollowToolbar(): boolean { + // return this.get(ConfigKeys.SelectionAssistantFollowToolbar, true) + // } - setSelectionAssistantFollowToolbar(value: boolean) { - this.setAndNotify(ConfigKeys.SelectionAssistantFollowToolbar, value) - } + // setSelectionAssistantFollowToolbar(value: boolean) { + // this.setAndNotify(ConfigKeys.SelectionAssistantFollowToolbar, value) + // } - getSelectionAssistantRemeberWinSize(): boolean { - return this.get(ConfigKeys.SelectionAssistantRemeberWinSize, false) - } + // getSelectionAssistantRemeberWinSize(): boolean { + // return this.get(ConfigKeys.SelectionAssistantRemeberWinSize, false) + // } - setSelectionAssistantRemeberWinSize(value: boolean) { - this.setAndNotify(ConfigKeys.SelectionAssistantRemeberWinSize, value) - } + // setSelectionAssistantRemeberWinSize(value: boolean) { + // this.setAndNotify(ConfigKeys.SelectionAssistantRemeberWinSize, value) + // } - getSelectionAssistantFilterMode(): string { - return this.get(ConfigKeys.SelectionAssistantFilterMode, 'default') - } + // getSelectionAssistantFilterMode(): string { + // return this.get(ConfigKeys.SelectionAssistantFilterMode, 'default') + // } - setSelectionAssistantFilterMode(value: string) { - this.setAndNotify(ConfigKeys.SelectionAssistantFilterMode, value) - } + // setSelectionAssistantFilterMode(value: string) { + // this.setAndNotify(ConfigKeys.SelectionAssistantFilterMode, value) + // } - getSelectionAssistantFilterList(): string[] { - return this.get(ConfigKeys.SelectionAssistantFilterList, []) - } + // getSelectionAssistantFilterList(): string[] { + // return this.get(ConfigKeys.SelectionAssistantFilterList, []) + // } - setSelectionAssistantFilterList(value: string[]) { - this.setAndNotify(ConfigKeys.SelectionAssistantFilterList, value) - } + // setSelectionAssistantFilterList(value: string[]) { + // this.setAndNotify(ConfigKeys.SelectionAssistantFilterList, value) + // } getDisableHardwareAcceleration(): boolean { return this.get(ConfigKeys.DisableHardwareAcceleration, false) @@ -230,13 +230,13 @@ export class ConfigManager { this.set(key, value, true) } - getEnableDeveloperMode(): boolean { - return this.get(ConfigKeys.EnableDeveloperMode, false) - } + // getEnableDeveloperMode(): boolean { + // return this.get(ConfigKeys.EnableDeveloperMode, false) + // } - setEnableDeveloperMode(value: boolean) { - this.set(ConfigKeys.EnableDeveloperMode, value) - } + // setEnableDeveloperMode(value: boolean) { + // this.set(ConfigKeys.EnableDeveloperMode, value) + // } set(key: string, value: unknown, isNotify: boolean = false) { this.store.set(key, value) diff --git a/src/main/services/ShortcutService.ts b/src/main/services/ShortcutService.ts index 97216e6a65..308617a33a 100644 --- a/src/main/services/ShortcutService.ts +++ b/src/main/services/ShortcutService.ts @@ -1,3 +1,4 @@ +import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { handleZoomFactor } from '@main/utils/zoom' import { Shortcut } from '@types' @@ -6,7 +7,6 @@ import { BrowserWindow, globalShortcut } from 'electron' import { configManager } from './ConfigManager' import selectionService from './SelectionService' import { windowService } from './WindowService' - const logger = loggerService.withContext('ShortcutService') let showAppAccelerator: string | null = null @@ -137,7 +137,7 @@ const convertShortcutFormat = (shortcut: string | string[]): string => { export function registerShortcuts(window: BrowserWindow) { if (isRegisterOnBoot) { window.once('ready-to-show', () => { - if (configManager.getLaunchToTray()) { + if (preferenceService.get('app.tray.on_launch')) { registerOnlyUniversalShortcuts() } }) @@ -190,7 +190,7 @@ export function registerShortcuts(window: BrowserWindow) { case 'mini_window': //available only when QuickAssistant enabled - if (!configManager.getEnableQuickAssistant()) { + if (!preferenceService.get('feature.quick_assistant.enabled')) { return } showMiniWindowAccelerator = formatShortcutKey(shortcut.shortcut) diff --git a/src/main/services/SpanCacheService.ts b/src/main/services/SpanCacheService.ts index 98ff36d298..bafc310781 100644 --- a/src/main/services/SpanCacheService.ts +++ b/src/main/services/SpanCacheService.ts @@ -1,3 +1,4 @@ +import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { Attributes, convertSpanToSpanEntity, SpanEntity, TokenUsage, TraceCache } from '@mcp-trace/trace-core' import { SpanStatusCode } from '@opentelemetry/api' @@ -6,8 +7,6 @@ import fs from 'fs/promises' import * as os from 'os' import * as path from 'path' -import { configManager } from './ConfigManager' - const logger = loggerService.withContext('SpanCacheService') class SpanCacheService implements TraceCache { @@ -21,7 +20,7 @@ class SpanCacheService implements TraceCache { } createSpan: (span: ReadableSpan) => void = (span: ReadableSpan) => { - if (!configManager.getEnableDeveloperMode()) { + if (!preferenceService.get('app.developer_mode.enabled')) { return } const spanEntity = convertSpanToSpanEntity(span) @@ -31,7 +30,7 @@ class SpanCacheService implements TraceCache { } endSpan: (span: ReadableSpan) => void = (span: ReadableSpan) => { - if (!configManager.getEnableDeveloperMode()) { + if (!preferenceService.get('app.developer_mode.enabled')) { return } const spanId = span.spanContext().spanId @@ -87,7 +86,7 @@ class SpanCacheService implements TraceCache { } async saveSpans(topicId: string) { - if (!configManager.getEnableDeveloperMode()) { + if (!preferenceService.get('app.developer_mode.enabled')) { return } let traceId: string | undefined @@ -138,7 +137,7 @@ class SpanCacheService implements TraceCache { } saveEntity(entity: SpanEntity) { - if (!configManager.getEnableDeveloperMode()) { + if (!preferenceService.get('app.developer_mode.enabled')) { return } if (this.cache.has(entity.id)) { diff --git a/src/main/services/WindowService.ts b/src/main/services/WindowService.ts index 8fcbebc642..80f5baffb7 100644 --- a/src/main/services/WindowService.ts +++ b/src/main/services/WindowService.ts @@ -1,6 +1,7 @@ // just import the themeService to ensure the theme is initialized import './ThemeService' +import { preferenceService } from '@data/PreferenceService' import { is } from '@electron-toolkit/utils' import { loggerService } from '@logger' import { isDev, isLinux, isMac, isWin } from '@main/constant' @@ -86,7 +87,7 @@ export class WindowService { this.setupMainWindow(this.mainWindow, mainWindowState) //preload miniWindow to resolve series of issues about miniWindow in Mac - const enableQuickAssistant = configManager.getEnableQuickAssistant() + const enableQuickAssistant = preferenceService.get('feature.quick_assistant.enabled') if (enableQuickAssistant && !this.miniWindow) { this.miniWindow = this.createMiniWindow(true) } @@ -141,7 +142,7 @@ export class WindowService { private setupMaximize(mainWindow: BrowserWindow, isMaximized: boolean) { if (isMaximized) { // 如果是从托盘启动,则需要延迟最大化,否则显示的就不是重启前的最大化窗口了 - configManager.getLaunchToTray() + preferenceService.get('app.tray.on_launch') ? mainWindow.once('show', () => { mainWindow.maximize() }) @@ -169,7 +170,7 @@ export class WindowService { mainWindow.webContents.setZoomFactor(configManager.getZoomFactor()) // show window only when laucn to tray not set - const isLaunchToTray = configManager.getLaunchToTray() + const isLaunchToTray = preferenceService.get('app.tray.on_launch') if (!isLaunchToTray) { //[mac]hacky-fix: miniWindow set visibleOnFullScreen:true will cause dock icon disappeared app.dock?.show() @@ -342,8 +343,8 @@ export class WindowService { } // 托盘及关闭行为设置 - const isShowTray = configManager.getTray() - const isTrayOnClose = configManager.getTrayOnClose() + const isShowTray = preferenceService.get('app.tray.enabled') + const isTrayOnClose = preferenceService.get('app.tray.on_close') // 没有开启托盘,或者开启了托盘,但设置了直接关闭,应执行直接退出 if (!isShowTray || (isShowTray && !isTrayOnClose)) { @@ -444,7 +445,7 @@ export class WindowService { if (this.mainWindow && !this.mainWindow.isDestroyed() && this.mainWindow.isVisible()) { if (this.mainWindow.isFocused()) { // if tray is enabled, hide the main window, else do nothing - if (configManager.getTray()) { + if (preferenceService.get('app.tray.on_close')) { this.mainWindow.hide() app.dock?.hide() } @@ -547,7 +548,7 @@ export class WindowService { } public showMiniWindow() { - const enableQuickAssistant = configManager.getEnableQuickAssistant() + const enableQuickAssistant = preferenceService.get('feature.quick_assistant.enabled') if (!enableQuickAssistant) { return diff --git a/src/preload/index.ts b/src/preload/index.ts index 1d8e77ba2d..fca54e0403 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -2,10 +2,10 @@ import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces' import { electronAPI } from '@electron-toolkit/preload' import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core' import { SpanContext } from '@opentelemetry/api' -import { UpgradeChannel } from '@shared/config/constant' import type { LogLevel, LogSourceWithContext } from '@shared/config/logger' import type { FileChangeEvent } from '@shared/config/types' import type { PreferenceDefaultScopeType, PreferenceKeyType, SelectionActionItem } from '@shared/data/preferenceTypes' +import { UpgradeChannel } from '@shared/data/preferenceTypes' import { IpcChannel } from '@shared/IpcChannel' import { AddMemoryOptions, diff --git a/src/renderer/src/pages/settings/AboutSettings.tsx b/src/renderer/src/pages/settings/AboutSettings.tsx index 30ec91e045..0ab352b046 100644 --- a/src/renderer/src/pages/settings/AboutSettings.tsx +++ b/src/renderer/src/pages/settings/AboutSettings.tsx @@ -10,7 +10,7 @@ import i18n from '@renderer/i18n' import { handleSaveData, useAppDispatch } from '@renderer/store' import { setUpdateState } from '@renderer/store/runtime' import { runAsyncFunction } from '@renderer/utils' -import { UpgradeChannel } from '@shared/config/constant' +import { UpgradeChannel } from '@shared/data/preferenceTypes' import { ThemeMode } from '@shared/data/preferenceTypes' import { Avatar, Button, Progress, Radio, Row, Switch, Tag, Tooltip } from 'antd' import { debounce } from 'lodash' diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index ace64ab25f..08a4f0c091 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -5,6 +5,7 @@ import { LoadingOutlined, YuqueOutlined } from '@ant-design/icons' +import { usePreference } from '@data/hooks/usePreference' import DividerWithText from '@renderer/components/DividerWithText' import { NutstoreIcon } from '@renderer/components/Icons/NutstoreIcons' import { HStack } from '@renderer/components/Layout' @@ -15,8 +16,6 @@ import { useTheme } from '@renderer/context/ThemeProvider' import { useKnowledgeFiles } from '@renderer/hooks/useKnowledgeFiles' import { useTimer } from '@renderer/hooks/useTimer' import { reset } from '@renderer/services/BackupService' -import store, { useAppDispatch } from '@renderer/store' -import { setSkipBackupFile as _setSkipBackupFile } from '@renderer/store/settings' import { AppInfo } from '@renderer/types' import { formatFileSize } from '@renderer/utils' import { occupiedDirs } from '@shared/config/constant' @@ -49,6 +48,8 @@ import WebDavSettings from './WebDavSettings' import YuqueSettings from './YuqueSettings' const DataSettings: FC = () => { + const [skipBackupFile, setSkipBackupFile] = usePreference('data.backup.general.skip_backup_file') + const { t } = useTranslation() const [appInfo, setAppInfo] = useState() const [cacheSize, setCacheSize] = useState('') @@ -57,11 +58,6 @@ const DataSettings: FC = () => { const [menu, setMenu] = useState('data') const { setTimeoutTimer } = useTimer() - const _skipBackupFile = store.getState().settings.skipBackupFile - const [skipBackupFile, setSkipBackupFile] = useState(_skipBackupFile) - - const dispatch = useAppDispatch() - //joplin icon needs to be updated into iconfont const JoplinIcon = () => ( @@ -578,7 +574,6 @@ const DataSettings: FC = () => { const onSkipBackupFilesChange = (value: boolean) => { setSkipBackupFile(value) - dispatch(_setSkipBackupFile(value)) } return ( diff --git a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx index e040b13ccc..f62a8aa806 100644 --- a/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/NutstoreSettings.tsx @@ -1,4 +1,5 @@ import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' +import { usePreference } from '@data/hooks/usePreference' import { HStack } from '@renderer/components/Layout' import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup' import Selector from '@renderer/components/Selector' @@ -15,15 +16,7 @@ import { startNutstoreAutoSync, stopNutstoreAutoSync } from '@renderer/services/NutstoreService' -import { useAppDispatch, useAppSelector } from '@renderer/store' -import { - setNutstoreAutoSync, - setNutstoreMaxBackups, - setNutstorePath, - setNutstoreSkipBackupFile, - setNutstoreSyncInterval, - setNutstoreToken -} from '@renderer/store/nutstore' +import { useAppSelector } from '@renderer/store' import { modalConfirm } from '@renderer/utils' import { NUTSTORE_HOST } from '@shared/config/nutstore' import { Button, Input, Switch, Tooltip, Typography } from 'antd' @@ -37,25 +30,24 @@ import { SettingDivider, SettingGroup, SettingHelpText, SettingRow, SettingRowTi const NutstoreSettings: FC = () => { const { theme } = useTheme() const { t } = useTranslation() - const { - nutstoreToken, - nutstorePath, - nutstoreSyncInterval, - nutstoreAutoSync, - nutstoreSyncState, - nutstoreSkipBackupFile, - nutstoreMaxBackups - } = useAppSelector((state) => state.nutstore) + const { nutstoreSyncState } = useAppSelector((state) => state.nutstore) - const dispatch = useAppDispatch() + const [nutstoreAutoSync, setNutstoreAutoSync] = usePreference('data.backup.nutstore.auto_sync') + const [nutstoreMaxBackups, setNutstoreMaxBackups] = usePreference('data.backup.nutstore.max_backups') + const [nutstorePath, setNutstorePath] = usePreference('data.backup.nutstore.path') + const [nutstoreSkipBackupFile, setNutstoreSkipBackupFile] = usePreference('data.backup.nutstore.skip_backup_file') + const [nutstoreSyncInterval, setNutstoreSyncInterval] = usePreference('data.backup.nutstore.sync_interval') + const [nutstoreToken, setNutstoreToken] = usePreference('data.backup.nutstore.token') const [nutstoreUsername, setNutstoreUsername] = useState(undefined) const [nutstorePass, setNutstorePass] = useState(undefined) - const [storagePath, setStoragePath] = useState(nutstorePath) + // const [storagePath, setStoragePath] = useState(nutstorePath) const [checkConnectionLoading, setCheckConnectionLoading] = useState(false) const [nsConnected, setNsConnected] = useState(false) - const [syncInterval, setSyncInterval] = useState(nutstoreSyncInterval) - const [nutSkipBackupFile, setNutSkipBackupFile] = useState(nutstoreSkipBackupFile) + + // const [syncInterval, setSyncInterval] = useState(nutstoreSyncInterval) + // const [nutSkipBackupFile, setNutSkipBackupFile] = useState(nutstoreSkipBackupFile) + const [backupManagerVisible, setBackupManagerVisible] = useState(false) const nutstoreSSOHandler = useNutstoreSSO() @@ -66,8 +58,8 @@ const NutstoreSettings: FC = () => { window.open(ssoUrl, '_blank') const nutstoreToken = await nutstoreSSOHandler() - dispatch(setNutstoreToken(nutstoreToken)) - }, [dispatch, nutstoreSSOHandler]) + setNutstoreToken(nutstoreToken) + }, [nutstoreSSOHandler, setNutstoreToken]) useEffect(() => { async function decryptTokenEffect() { @@ -78,14 +70,14 @@ const NutstoreSettings: FC = () => { setNutstoreUsername(decrypted.username) setNutstorePass(decrypted.access_token) if (!nutstorePath) { - dispatch(setNutstorePath('/cherry-studio')) - setStoragePath('/cherry-studio') + setNutstorePath('/cherry-studio') + // setStoragePath('/cherry-studio') } } } } decryptTokenEffect() - }, [nutstoreToken, dispatch, nutstorePath]) + }, [nutstoreToken, setNutstorePath, nutstorePath]) const handleLayout = useCallback(async () => { const confirmedLogout = await modalConfirm({ @@ -93,13 +85,12 @@ const NutstoreSettings: FC = () => { content: t('settings.data.nutstore.logout.content') }) if (confirmedLogout) { - dispatch(setNutstoreToken('')) - dispatch(setNutstorePath('')) - dispatch(setNutstoreAutoSync(false)) + setNutstoreToken('') + setNutstorePath('') + setNutstoreAutoSync(false) setNutstoreUsername('') - setStoragePath(undefined) } - }, [dispatch, t]) + }, [setNutstorePath, setNutstoreToken, setNutstoreAutoSync, t]) const handleCheckConnection = async () => { if (!nutstoreToken) return @@ -126,25 +117,23 @@ const NutstoreSettings: FC = () => { backupMethod: backupToNutstore }) - const onSyncIntervalChange = (value: number) => { - setSyncInterval(value) - dispatch(setNutstoreSyncInterval(value)) + const onSyncIntervalChange = async (value: number) => { + await setNutstoreSyncInterval(value) if (value === 0) { - dispatch(setNutstoreAutoSync(false)) + await setNutstoreAutoSync(false) stopNutstoreAutoSync() } else { - dispatch(setNutstoreAutoSync(true)) + await setNutstoreAutoSync(true) startNutstoreAutoSync() } } const onSkipBackupFilesChange = (value: boolean) => { - setNutSkipBackupFile(value) - dispatch(setNutstoreSkipBackupFile(value)) + setNutstoreSkipBackupFile(value) } const onMaxBackupsChange = (value: number) => { - dispatch(setNutstoreMaxBackups(value)) + setNutstoreMaxBackups(value) } const handleClickPathChange = async () => { @@ -174,8 +163,7 @@ const NutstoreSettings: FC = () => { return } - setStoragePath(targetPath) - dispatch(setNutstorePath(targetPath)) + setNutstorePath(targetPath) } const renderSyncStatus = () => { @@ -260,8 +248,7 @@ const NutstoreSettings: FC = () => { style={{ width: 250 }} value={nutstorePath} onChange={(e) => { - setStoragePath(e.target.value) - dispatch(setNutstorePath(e.target.value)) + setNutstorePath(e.target.value) }} />