diff --git a/src/main/index.ts b/src/main/index.ts index 699074e279..4412c28af2 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -19,7 +19,6 @@ import process from 'node:process' import { registerIpc } from './ipc' import { agentService } from './services/agents' import { apiServerService } from './services/ApiServerService' -import { configManager } from './services/ConfigManager' import mcpService from './services/MCPService' import { nodeTraceService } from './services/NodeTraceService' import { @@ -42,12 +41,12 @@ const logger = loggerService.withContext('MainEntry') /** * Disable hardware acceleration if setting is enabled */ -//FIXME should not use configManager, use usePreference instead +//FIXME should not use preferenceService before initialization //TODO 我们需要调整配置管理的加载位置,以保证其在 preferenceService 初始化之前被调用 -const disableHardwareAcceleration = configManager.getDisableHardwareAcceleration() -if (disableHardwareAcceleration) { - app.disableHardwareAcceleration() -} +// const disableHardwareAcceleration = preferenceService.get('app.disable_hardware_acceleration') +// if (disableHardwareAcceleration) { +// app.disableHardwareAcceleration() +// } /** * Disable chromium's window animations diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 62b1c57527..ac8d469b09 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -169,7 +169,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { windows.forEach((window) => { window.webContents.session.setSpellCheckerLanguages(languages) }) - configManager.set('spellCheckLanguages', languages) + preferenceService.set('app.spell_check.languages', languages) }) // launch on boot @@ -264,12 +264,15 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { } }) - ipcMain.handle(IpcChannel.Config_Set, (_, key: string, value: any, isNotify: boolean = false) => { - configManager.set(key, value, isNotify) + ipcMain.handle(IpcChannel.Config_Set, (_, key: string) => { + // Legacy config handler - will be deprecated + logger.warn(`Legacy Config_Set called for key: ${key}`) }) ipcMain.handle(IpcChannel.Config_Get, (_, key: string) => { - return configManager.get(key) + // Legacy config handler - will be deprecated + logger.warn(`Legacy Config_Get called for key: ${key}`) + return undefined }) // // theme @@ -280,7 +283,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { ipcMain.handle(IpcChannel.App_HandleZoomFactor, (_, delta: number, reset: boolean = false) => { const windows = BrowserWindow.getAllWindows() handleZoomFactor(windows, delta, reset) - return configManager.getZoomFactor() + return preferenceService.get('app.zoom_factor') }) // clear cache diff --git a/src/main/services/AppUpdater.ts b/src/main/services/AppUpdater.ts index a9fcab82e5..d63d7ed60c 100644 --- a/src/main/services/AppUpdater.ts +++ b/src/main/services/AppUpdater.ts @@ -1,9 +1,8 @@ import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { isWin } from '@main/constant' -import { configManager } from '@main/services/ConfigManager' import { getIpCountry } from '@main/utils/ipService' -import { generateUserAgent } from '@main/utils/systemInfo' +import { generateUserAgent, getClientId } from '@main/utils/systemInfo' import { FeedUrl } from '@shared/config/constant' import { UpgradeChannel } from '@shared/data/preference/preferenceTypes' import { IpcChannel } from '@shared/IpcChannel' @@ -39,7 +38,7 @@ export default class AppUpdater { autoUpdater.requestHeaders = { ...autoUpdater.requestHeaders, 'User-Agent': generateUserAgent(), - 'X-Client-Id': configManager.getClientId() + 'X-Client-Id': getClientId() } autoUpdater.on('error', (error) => { diff --git a/src/main/services/NodeTraceService.ts b/src/main/services/NodeTraceService.ts index 70fd92a28b..ec74baee90 100644 --- a/src/main/services/NodeTraceService.ts +++ b/src/main/services/NodeTraceService.ts @@ -1,3 +1,4 @@ +import { preferenceService } from '@data/PreferenceService' import { loggerService } from '@logger' import { isDev } from '@main/constant' import { CacheBatchSpanProcessor, FunctionSpanExporter } from '@mcp-trace/trace-core' @@ -7,7 +8,6 @@ import { context, trace } from '@opentelemetry/api' import { BrowserWindow, ipcMain } from 'electron' import * as path from 'path' -import { ConfigKeys, configManager } from './ConfigManager' import { spanCacheService } from './SpanCacheService' export const TRACER_NAME = 'CherryStudio' @@ -91,8 +91,13 @@ export function openTraceWindow(topicId: string, traceId: string, autoOpen = tru } else { traceWin.loadFile(path.join(__dirname, '../renderer/traceWindow.html')) } + let unsubscribeLanguage: (() => void) | null = null + traceWin.on('closed', () => { - configManager.unsubscribe(ConfigKeys.Language, setLanguageCallback) + if (unsubscribeLanguage) { + unsubscribeLanguage() + unsubscribeLanguage = null + } try { traceWin?.destroy() } finally { @@ -106,13 +111,15 @@ export function openTraceWindow(topicId: string, traceId: string, autoOpen = tru topicId, modelName }) - traceWin!.webContents.send('set-language', { lang: configManager.get(ConfigKeys.Language) }) - configManager.subscribe(ConfigKeys.Language, setLanguageCallback) + traceWin!.webContents.send('set-language', { lang: preferenceService.get('app.language') }) + unsubscribeLanguage = preferenceService.subscribeChange('app.language', setLanguageCallback) }) } -const setLanguageCallback = (lang: string) => { - traceWin!.webContents.send('set-language', { lang }) +const setLanguageCallback = (lang: string | null) => { + if (lang) { + traceWin?.webContents.send('set-language', { lang }) + } } export const setTraceWindowTitle = (title: string) => { diff --git a/src/main/services/WindowService.ts b/src/main/services/WindowService.ts index 6c4ed12db0..ceb977a136 100644 --- a/src/main/services/WindowService.ts +++ b/src/main/services/WindowService.ts @@ -14,7 +14,6 @@ import { join } from 'path' import icon from '../../../build/icon.png?asset' import { titleBarOverlayDark, titleBarOverlayLight } from '../config' -import { configManager } from './ConfigManager' import { contextMenu } from './ContextMenu' import { initSessionUserAgent } from './WebviewService' @@ -87,7 +86,7 @@ export class WindowService { webSecurity: false, webviewTag: true, allowRunningInsecureContent: true, - zoomFactor: configManager.getZoomFactor(), + zoomFactor: preferenceService.get('app.zoom_factor'), backgroundThrottling: false } }) @@ -120,10 +119,10 @@ export class WindowService { } private setupSpellCheck(mainWindow: BrowserWindow) { - const enableSpellCheck = configManager.get('enableSpellCheck', false) + const enableSpellCheck = preferenceService.get('app.spell_check.enabled') if (enableSpellCheck) { try { - const spellCheckLanguages = configManager.get('spellCheckLanguages', []) as string[] + const spellCheckLanguages = preferenceService.get('app.spell_check.languages') spellCheckLanguages.length > 0 && mainWindow.webContents.session.setSpellCheckerLanguages(spellCheckLanguages) } catch (error) { logger.error('Failed to set spell check languages:', error as Error) @@ -175,7 +174,7 @@ export class WindowService { private setupWindowEvents(mainWindow: BrowserWindow) { mainWindow.once('ready-to-show', () => { - mainWindow.webContents.setZoomFactor(configManager.getZoomFactor()) + mainWindow.webContents.setZoomFactor(preferenceService.get('app.zoom_factor')) // show window only when laucn to tray not set const isLaunchToTray = preferenceService.get('app.tray.on_launch') @@ -204,14 +203,14 @@ export class WindowService { // and resize ipc // mainWindow.on('will-resize', () => { - mainWindow.webContents.setZoomFactor(configManager.getZoomFactor()) + mainWindow.webContents.setZoomFactor(preferenceService.get('app.zoom_factor')) mainWindow.webContents.send(IpcChannel.Windows_Resize, mainWindow.getSize()) }) // set the zoom factor again when the window is going to restore // minimize and restore will cause zoom reset mainWindow.on('restore', () => { - mainWindow.webContents.setZoomFactor(configManager.getZoomFactor()) + mainWindow.webContents.setZoomFactor(preferenceService.get('app.zoom_factor')) }) // ARCH: as `will-resize` is only for Win & Mac, @@ -219,7 +218,7 @@ export class WindowService { // but `resize` will fliker the ui if (isLinux) { mainWindow.on('resize', () => { - mainWindow.webContents.setZoomFactor(configManager.getZoomFactor()) + mainWindow.webContents.setZoomFactor(preferenceService.get('app.zoom_factor')) mainWindow.webContents.send(IpcChannel.Windows_Resize, mainWindow.getSize()) }) } diff --git a/src/main/services/__tests__/AppUpdater.test.ts b/src/main/services/__tests__/AppUpdater.test.ts index 2611cf608c..80a9b252f3 100644 --- a/src/main/services/__tests__/AppUpdater.test.ts +++ b/src/main/services/__tests__/AppUpdater.test.ts @@ -40,7 +40,8 @@ vi.mock('@main/utils/locales', () => ({ })) vi.mock('@main/utils/systemInfo', () => ({ - generateUserAgent: vi.fn(() => 'test-user-agent') + generateUserAgent: vi.fn(() => 'test-user-agent'), + getClientId: vi.fn(() => 'test-client-id') })) vi.mock('electron', () => ({ diff --git a/src/main/utils/systemInfo.ts b/src/main/utils/systemInfo.ts index 84db4efed7..427501726a 100644 --- a/src/main/utils/systemInfo.ts +++ b/src/main/utils/systemInfo.ts @@ -1,6 +1,8 @@ +import { preferenceService } from '@data/PreferenceService' import { app } from 'electron' import macosRelease from 'macos-release' import os from 'os' +import { v4 as uuidv4 } from 'uuid' /** * System information interface @@ -90,3 +92,19 @@ export function generateUserAgent(): string { return `Mozilla/5.0 (${systemInfo.osString}; ${systemInfo.archString}) AppleWebKit/537.36 (KHTML, like Gecko) CherryStudio/${systemInfo.appVersion} Chrome/124.0.0.0 Safari/537.36` } + +/** + * Get or generate a unique client ID + * @returns {string} Client ID + */ +export function getClientId(): string { + let clientId = preferenceService.get('app.user.id') + + // If it's the placeholder value, generate a new UUID + if (!clientId || clientId.length === 0) { + clientId = uuidv4() + preferenceService.set('app.user.id', clientId) + } + + return clientId +} diff --git a/src/main/utils/zoom.ts b/src/main/utils/zoom.ts index d75b31724e..969859a7f9 100644 --- a/src/main/utils/zoom.ts +++ b/src/main/utils/zoom.ts @@ -1,13 +1,12 @@ +import { preferenceService } from '@data/PreferenceService' import type { BrowserWindow } from 'electron' -import { configManager } from '../services/ConfigManager' - export function handleZoomFactor(wins: BrowserWindow[], delta: number, reset: boolean = false) { if (reset) { wins.forEach((win) => { win.webContents.setZoomFactor(1) }) - configManager.setZoomFactor(1) + preferenceService.set('app.zoom_factor', 1) return } @@ -15,12 +14,12 @@ export function handleZoomFactor(wins: BrowserWindow[], delta: number, reset: bo return } - const currentZoom = configManager.getZoomFactor() + const currentZoom = preferenceService.get('app.zoom_factor') const newZoom = Number((currentZoom + delta).toFixed(1)) if (newZoom >= 0.5 && newZoom <= 2.0) { wins.forEach((win) => { win.webContents.setZoomFactor(newZoom) }) - configManager.setZoomFactor(newZoom) + preferenceService.set('app.zoom_factor', newZoom) } }