mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 23:59:45 +08:00
refactor: update theme handling and preference types
- Removed the App_SetTheme IPC channel and related theme management code. - Updated imports to use preferenceTypes for theme and selection action items. - Refactored preference service to preload preferences and adjusted related components. - Cleaned up unused code and comments related to theme management. - Enhanced the organization of preference-related types and actions for better maintainability.
This commit is contained in:
parent
0dce1c57fc
commit
0ef3852029
@ -13,7 +13,7 @@ export enum IpcChannel {
|
||||
App_SetLaunchToTray = 'app:set-launch-to-tray',
|
||||
App_SetTray = 'app:set-tray',
|
||||
App_SetTrayOnClose = 'app:set-tray-on-close',
|
||||
App_SetTheme = 'app:set-theme',
|
||||
// App_SetTheme = 'app:set-theme',
|
||||
App_SetAutoUpdate = 'app:set-auto-update',
|
||||
App_SetTestPlan = 'app:set-test-plan',
|
||||
App_SetTestChannel = 'app:set-test-channel',
|
||||
@ -234,7 +234,7 @@ export enum IpcChannel {
|
||||
// events
|
||||
BackupProgress = 'backup-progress',
|
||||
DataMigrateProgress = 'data-migrate-progress',
|
||||
ThemeUpdated = 'theme:updated',
|
||||
NativeThemeUpdated = 'native-theme:updated',
|
||||
UpdateDownloadedCancelled = 'update-downloaded-cancelled',
|
||||
RestoreProgress = 'restore-progress',
|
||||
UpdateError = 'update-error',
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* 数据重构,临时存放的默认值,需在全部完成后重新整理
|
||||
* 数据重构,临时存放的默认值,需在全部完成后重新整理,并整理到preferences.ts中
|
||||
*/
|
||||
|
||||
import type { SelectionActionItem } from './types'
|
||||
import type { SelectionActionItem } from './preferenceTypes'
|
||||
|
||||
export const defaultActionItems: SelectionActionItem[] = [
|
||||
{ id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
|
||||
|
||||
@ -3,7 +3,7 @@ import { PreferencesType } from './preferences'
|
||||
export type PreferenceDefaultScopeType = PreferencesType['default']
|
||||
export type PreferenceKeyType = keyof PreferenceDefaultScopeType
|
||||
|
||||
export interface PreferenceUpdateOptions {
|
||||
export type PreferenceUpdateOptions = {
|
||||
optimistic: boolean
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ export type PreferenceShortcutType = {
|
||||
|
||||
export type SelectionTriggerMode = 'selected' | 'ctrlkey' | 'shortcut'
|
||||
export type SelectionFilterMode = 'default' | 'whitelist' | 'blacklist'
|
||||
export interface SelectionActionItem {
|
||||
export type SelectionActionItem = {
|
||||
id: string
|
||||
name: string
|
||||
enabled: boolean
|
||||
@ -27,3 +27,9 @@ export interface SelectionActionItem {
|
||||
selectedText?: string
|
||||
searchEngine?: string
|
||||
}
|
||||
|
||||
export enum ThemeMode {
|
||||
light = 'light',
|
||||
dark = 'dark',
|
||||
system = 'system'
|
||||
}
|
||||
@ -1,9 +1,6 @@
|
||||
import { defaultActionItems } from './pending_default_values'
|
||||
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from './types'
|
||||
|
||||
/**
|
||||
* Auto-generated preferences configuration
|
||||
* Generated at: 2025-08-15T03:23:46.568Z
|
||||
* Generated at: 2025-09-01T14:36:18.273Z
|
||||
*
|
||||
* This file is automatically generated from classification.json
|
||||
* To update this file, modify classification.json and run:
|
||||
@ -12,10 +9,14 @@ import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } f
|
||||
* === AUTO-GENERATED CONTENT START ===
|
||||
*/
|
||||
|
||||
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from './preferenceTypes'
|
||||
import { ThemeMode } from './preferenceTypes'
|
||||
|
||||
/* eslint @typescript-eslint/member-ordering: ["error", {
|
||||
"interfaces": { "order": "alphabetically" },
|
||||
"typeLiterals": { "order": "alphabetically" }
|
||||
}] */
|
||||
|
||||
export interface PreferencesType {
|
||||
default: {
|
||||
// redux/settings/enableDeveloperMode
|
||||
@ -51,9 +52,9 @@ export interface PreferencesType {
|
||||
// redux/settings/spellCheckLanguages
|
||||
'app.spell_check.languages': unknown[]
|
||||
// redux/settings/theme
|
||||
'app.theme.mode': string
|
||||
// redux/settings/userTheme
|
||||
'app.theme.user_defined': Record<string, unknown>
|
||||
'app.theme.mode': ThemeMode
|
||||
// redux/settings/userTheme.colorPrimary
|
||||
'app.theme.user.color_primary': string
|
||||
// redux/settings/windowStyle
|
||||
'app.theme.window_style': string
|
||||
// redux/settings/tray
|
||||
@ -100,8 +101,6 @@ export interface PreferencesType {
|
||||
'chat.code.viewer.theme_light': string
|
||||
// redux/settings/codeWrappable
|
||||
'chat.code.wrappable': boolean
|
||||
// redux/settings/enableBackspaceDeleteModel
|
||||
'chat.input.backspace_delete_model': boolean
|
||||
// redux/settings/pasteLongTextAsFile
|
||||
'chat.input.paste_long_text_as_file': boolean
|
||||
// redux/settings/pasteLongTextThreshold
|
||||
@ -312,6 +311,24 @@ export interface PreferencesType {
|
||||
'feature.selection.remember_win_size': boolean
|
||||
// redux/selectionStore/triggerMode
|
||||
'feature.selection.trigger_mode': SelectionTriggerMode
|
||||
// redux/shortcuts/shortcuts.exit_fullscreen
|
||||
'shortcut.app.exit_fullscreen': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.search_message
|
||||
'shortcut.app.search_message': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.show_app
|
||||
'shortcut.app.show_main_window': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.mini_window
|
||||
'shortcut.app.show_mini_window': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.show_settings
|
||||
'shortcut.app.show_settings': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.toggle_show_assistants
|
||||
'shortcut.app.toggle_show_assistants': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_in
|
||||
'shortcut.app.zoom_in': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_out
|
||||
'shortcut.app.zoom_out': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_reset
|
||||
'shortcut.app.zoom_reset': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.clear_topic
|
||||
'shortcut.chat.clear': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.copy_last_message
|
||||
@ -320,26 +337,12 @@ export interface PreferencesType {
|
||||
'shortcut.chat.search_message': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.toggle_new_context
|
||||
'shortcut.chat.toggle_new_context': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.exit_fullscreen
|
||||
'shortcut.exit_fullscreen': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.search_message
|
||||
'shortcut.global.search_message': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.show_app
|
||||
'shortcut.main_window.show': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.mini_window
|
||||
'shortcut.mini_window.show': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.show_settings
|
||||
'shortcut.show_settings': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.toggle_show_assistants
|
||||
'shortcut.toggle_show_assistants': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.selection_assistant_select_text
|
||||
'shortcut.selection.get_text': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.selection_assistant_toggle
|
||||
'shortcut.selection.toggle_enabled': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.new_topic
|
||||
'shortcut.topic.new': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_in
|
||||
'shortcut.zoom_in': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_out
|
||||
'shortcut.zoom_out': Record<string, unknown>
|
||||
// redux/shortcuts/shortcuts.zoom_reset
|
||||
'shortcut.zoom_reset': Record<string, unknown>
|
||||
// redux/settings/enableTopicNaming
|
||||
'topic.naming.enabled': boolean
|
||||
// redux/settings/topicNamingPrompt
|
||||
@ -357,7 +360,7 @@ export interface PreferencesType {
|
||||
// redux/settings/customCss
|
||||
'ui.custom_css': string
|
||||
// redux/settings/navbarPosition
|
||||
'ui.navbar.position': string
|
||||
'ui.navbar.position': 'left' | 'top'
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,8 +383,8 @@ export const DefaultPreferences: PreferencesType = {
|
||||
'app.proxy.url': null,
|
||||
'app.spell_check.enabled': false,
|
||||
'app.spell_check.languages': [],
|
||||
'app.theme.mode': 'ThemeMode.system',
|
||||
'app.theme.user_defined': { colorPrimary: '#00b96b' },
|
||||
'app.theme.mode': ThemeMode.system,
|
||||
'app.theme.user.color_primary': '#00b96b',
|
||||
'app.theme.window_style': 'opaque',
|
||||
'app.tray.enabled': true,
|
||||
'app.tray.on_close': true,
|
||||
@ -405,7 +408,6 @@ export const DefaultPreferences: PreferencesType = {
|
||||
'chat.code.viewer.theme_dark': 'auto',
|
||||
'chat.code.viewer.theme_light': 'auto',
|
||||
'chat.code.wrappable': false,
|
||||
'chat.input.backspace_delete_model': true,
|
||||
'chat.input.paste_long_text_as_file': false,
|
||||
'chat.input.paste_long_text_threshold': 1500,
|
||||
'chat.input.quick_panel.triggers_enabled': false,
|
||||
@ -500,7 +502,34 @@ export const DefaultPreferences: PreferencesType = {
|
||||
'feature.quick_assistant.click_tray_to_show': false,
|
||||
'feature.quick_assistant.enabled': false,
|
||||
'feature.quick_assistant.read_clipboard_at_startup': true,
|
||||
'feature.selection.action_items': defaultActionItems,
|
||||
'feature.selection.action_items': [
|
||||
{
|
||||
enabled: true,
|
||||
icon: 'languages',
|
||||
id: 'translate',
|
||||
isBuiltIn: true,
|
||||
name: 'selection.action.builtin.translate'
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
icon: 'file-question',
|
||||
id: 'explain',
|
||||
isBuiltIn: true,
|
||||
name: 'selection.action.builtin.explain'
|
||||
},
|
||||
{ enabled: true, icon: 'scan-text', id: 'summary', isBuiltIn: true, name: 'selection.action.builtin.summary' },
|
||||
{
|
||||
enabled: true,
|
||||
icon: 'search',
|
||||
id: 'search',
|
||||
isBuiltIn: true,
|
||||
name: 'selection.action.builtin.search',
|
||||
searchEngine: 'Google|https://www.google.com/search?q={{queryString}}'
|
||||
},
|
||||
{ enabled: true, icon: 'clipboard-copy', id: 'copy', isBuiltIn: true, name: 'selection.action.builtin.copy' },
|
||||
{ enabled: false, icon: 'wand-sparkles', id: 'refine', isBuiltIn: true, name: 'selection.action.builtin.refine' },
|
||||
{ enabled: false, icon: 'quote', id: 'quote', isBuiltIn: true, name: 'selection.action.builtin.quote' }
|
||||
],
|
||||
'feature.selection.action_window_opacity': 100,
|
||||
'feature.selection.auto_close': false,
|
||||
'feature.selection.auto_pin': false,
|
||||
@ -511,6 +540,25 @@ export const DefaultPreferences: PreferencesType = {
|
||||
'feature.selection.follow_toolbar': true,
|
||||
'feature.selection.remember_win_size': false,
|
||||
'feature.selection.trigger_mode': 'selected',
|
||||
'shortcut.app.exit_fullscreen': { editable: false, enabled: true, key: ['Escape'], system: true },
|
||||
'shortcut.app.search_message': {
|
||||
editable: true,
|
||||
enabled: true,
|
||||
key: ['CommandOrControl', 'Shift', 'F'],
|
||||
system: false
|
||||
},
|
||||
'shortcut.app.show_main_window': { editable: true, enabled: true, key: [], system: true },
|
||||
'shortcut.app.show_mini_window': { editable: true, enabled: false, key: ['CommandOrControl', 'E'], system: true },
|
||||
'shortcut.app.show_settings': { editable: false, enabled: true, key: ['CommandOrControl', ','], system: true },
|
||||
'shortcut.app.toggle_show_assistants': {
|
||||
editable: true,
|
||||
enabled: true,
|
||||
key: ['CommandOrControl', '['],
|
||||
system: false
|
||||
},
|
||||
'shortcut.app.zoom_in': { editable: false, enabled: true, key: ['CommandOrControl', '='], system: true },
|
||||
'shortcut.app.zoom_out': { editable: false, enabled: true, key: ['CommandOrControl', '-'], system: true },
|
||||
'shortcut.app.zoom_reset': { editable: false, enabled: true, key: ['CommandOrControl', '0'], system: true },
|
||||
'shortcut.chat.clear': { editable: true, enabled: true, key: ['CommandOrControl', 'L'], system: false },
|
||||
'shortcut.chat.copy_last_message': {
|
||||
editable: true,
|
||||
@ -525,21 +573,9 @@ export const DefaultPreferences: PreferencesType = {
|
||||
key: ['CommandOrControl', 'K'],
|
||||
system: false
|
||||
},
|
||||
'shortcut.exit_fullscreen': { editable: false, enabled: true, key: ['Escape'], system: true },
|
||||
'shortcut.global.search_message': {
|
||||
editable: true,
|
||||
enabled: true,
|
||||
key: ['CommandOrControl', 'Shift', 'F'],
|
||||
system: false
|
||||
},
|
||||
'shortcut.main_window.show': { editable: true, enabled: true, key: [], system: true },
|
||||
'shortcut.mini_window.show': { editable: true, enabled: false, key: ['CommandOrControl', 'E'], system: true },
|
||||
'shortcut.show_settings': { editable: false, enabled: true, key: ['CommandOrControl', ','], system: true },
|
||||
'shortcut.toggle_show_assistants': { editable: true, enabled: true, key: ['CommandOrControl', '['], system: false },
|
||||
'shortcut.selection.get_text': { editable: true, enabled: false, key: [], system: true },
|
||||
'shortcut.selection.toggle_enabled': { editable: true, enabled: false, key: [], system: true },
|
||||
'shortcut.topic.new': { editable: true, enabled: true, key: ['CommandOrControl', 'N'], system: false },
|
||||
'shortcut.zoom_in': { editable: false, enabled: true, key: ['CommandOrControl', '='], system: true },
|
||||
'shortcut.zoom_out': { editable: false, enabled: true, key: ['CommandOrControl', '-'], system: true },
|
||||
'shortcut.zoom_reset': { editable: false, enabled: true, key: ['CommandOrControl', '0'], system: true },
|
||||
'topic.naming.enabled': true,
|
||||
'topic.naming.prompt': '',
|
||||
'topic.pin_to_top': false,
|
||||
@ -556,8 +592,8 @@ export const DefaultPreferences: PreferencesType = {
|
||||
|
||||
/**
|
||||
* 生成统计:
|
||||
* - 总配置项: 170
|
||||
* - 总配置项: 171
|
||||
* - electronStore项: 2
|
||||
* - redux项: 168
|
||||
* - redux项: 169
|
||||
* - localStorage项: 0
|
||||
*/
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { dbService } from '@data/db/DbService'
|
||||
import { loggerService } from '@logger'
|
||||
import { DefaultPreferences } from '@shared/data/preferences'
|
||||
import type { PreferenceDefaultScopeType, PreferenceKeyType } from '@shared/data/types'
|
||||
import type { PreferenceDefaultScopeType, PreferenceKeyType } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { BrowserWindow, ipcMain } from 'electron'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Auto-generated preference mappings from classification.json
|
||||
* Generated at: 2025-08-10T12:47:40.247Z
|
||||
* Generated at: 2025-09-01T14:38:08.063Z
|
||||
*
|
||||
* This file contains pure mapping relationships without default values.
|
||||
* Default values are managed in packages/shared/data/preferences.ts
|
||||
@ -131,8 +131,8 @@ export const REDUX_STORE_MAPPINGS = {
|
||||
targetKey: 'app.launch_on_boot'
|
||||
},
|
||||
{
|
||||
originalKey: 'userTheme',
|
||||
targetKey: 'app.theme.user_defined'
|
||||
originalKey: 'userTheme.colorPrimary',
|
||||
targetKey: 'app.theme.user.color_primary'
|
||||
},
|
||||
{
|
||||
originalKey: 'windowStyle',
|
||||
@ -446,10 +446,6 @@ export const REDUX_STORE_MAPPINGS = {
|
||||
originalKey: 'enableQuickPanelTriggers',
|
||||
targetKey: 'chat.input.quick_panel.triggers_enabled'
|
||||
},
|
||||
{
|
||||
originalKey: 'enableBackspaceDeleteModel',
|
||||
targetKey: 'chat.input.backspace_delete_model'
|
||||
},
|
||||
{
|
||||
originalKey: 'exportMenuOptions.image',
|
||||
targetKey: 'data.export.menus.image'
|
||||
@ -654,6 +650,72 @@ export const REDUX_STORE_MAPPINGS = {
|
||||
originalKey: 'nutstoreSkipBackupFile',
|
||||
targetKey: 'data.backup.nutstore.skip_backup_file'
|
||||
}
|
||||
],
|
||||
shortcuts: [
|
||||
{
|
||||
originalKey: 'shortcuts.zoom_in',
|
||||
targetKey: 'shortcut.app.zoom_in'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.zoom_out',
|
||||
targetKey: 'shortcut.app.zoom_out'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.zoom_reset',
|
||||
targetKey: 'shortcut.app.zoom_reset'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.show_settings',
|
||||
targetKey: 'shortcut.app.show_settings'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.show_app',
|
||||
targetKey: 'shortcut.app.show_main_window'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.mini_window',
|
||||
targetKey: 'shortcut.app.show_mini_window'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.selection_assistant_toggle',
|
||||
targetKey: 'shortcut.selection.toggle_enabled'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.selection_assistant_select_text',
|
||||
targetKey: 'shortcut.selection.get_text'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.new_topic',
|
||||
targetKey: 'shortcut.topic.new'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.toggle_show_assistants',
|
||||
targetKey: 'shortcut.app.toggle_show_assistants'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.copy_last_message',
|
||||
targetKey: 'shortcut.chat.copy_last_message'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.search_message_in_chat',
|
||||
targetKey: 'shortcut.chat.search_message'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.search_message',
|
||||
targetKey: 'shortcut.app.search_message'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.clear_topic',
|
||||
targetKey: 'shortcut.chat.clear'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.toggle_new_context',
|
||||
targetKey: 'shortcut.chat.toggle_new_context'
|
||||
},
|
||||
{
|
||||
originalKey: 'shortcuts.exit_fullscreen',
|
||||
targetKey: 'shortcut.app.exit_fullscreen'
|
||||
}
|
||||
]
|
||||
} as const
|
||||
|
||||
@ -662,9 +724,9 @@ export const REDUX_STORE_MAPPINGS = {
|
||||
/**
|
||||
* 映射统计:
|
||||
* - ElectronStore项: 2
|
||||
* - Redux Store项: 154
|
||||
* - Redux分类: settings, selectionStore, nutstore
|
||||
* - 总配置项: 156
|
||||
* - Redux Store项: 169
|
||||
* - Redux分类: settings, selectionStore, nutstore, shortcuts
|
||||
* - 总配置项: 171
|
||||
*
|
||||
* 使用说明:
|
||||
* 1. ElectronStore读取: configManager.get(mapping.originalKey)
|
||||
|
||||
@ -11,7 +11,7 @@ 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 { IpcChannel } from '@shared/IpcChannel'
|
||||
import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types'
|
||||
import { FileMetadata, Provider, Shortcut } from '@types'
|
||||
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
|
||||
import { Notification } from 'src/renderer/src/types/notification'
|
||||
|
||||
@ -53,7 +53,6 @@ import {
|
||||
tokenUsage
|
||||
} from './services/SpanCacheService'
|
||||
import storeSyncService from './services/StoreSyncService'
|
||||
import { themeService } from './services/ThemeService'
|
||||
import VertexAIService from './services/VertexAIService'
|
||||
import { setOpenLinkExternal } from './services/WebviewService'
|
||||
import { windowService } from './services/WindowService'
|
||||
@ -225,10 +224,10 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
return configManager.get(key)
|
||||
})
|
||||
|
||||
// theme
|
||||
ipcMain.handle(IpcChannel.App_SetTheme, (_, theme: ThemeMode) => {
|
||||
themeService.setTheme(theme)
|
||||
})
|
||||
// // theme
|
||||
// ipcMain.handle(IpcChannel.App_SetTheme, (_, theme: ThemeMode) => {
|
||||
// themeService.setTheme(theme)
|
||||
// })
|
||||
|
||||
ipcMain.handle(IpcChannel.App_HandleZoomFactor, (_, delta: number, reset: boolean = false) => {
|
||||
const windows = BrowserWindow.getAllWindows()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { defaultLanguage, UpgradeChannel, ZOOM_SHORTCUTS } from '@shared/config/constant'
|
||||
import { LanguageVarious, Shortcut, ThemeMode } from '@types'
|
||||
import { LanguageVarious, Shortcut } from '@types'
|
||||
import { app } from 'electron'
|
||||
import Store from 'electron-store'
|
||||
|
||||
@ -47,13 +47,13 @@ export class ConfigManager {
|
||||
this.setAndNotify(ConfigKeys.Language, lang)
|
||||
}
|
||||
|
||||
getTheme(): ThemeMode {
|
||||
return this.get(ConfigKeys.Theme, ThemeMode.system)
|
||||
}
|
||||
// getTheme(): ThemeMode {
|
||||
// return this.get(ConfigKeys.Theme, ThemeMode.system)
|
||||
// }
|
||||
|
||||
setTheme(theme: ThemeMode) {
|
||||
this.set(ConfigKeys.Theme, theme)
|
||||
}
|
||||
// setTheme(theme: ThemeMode) {
|
||||
// this.set(ConfigKeys.Theme, theme)
|
||||
// }
|
||||
|
||||
getLaunchToTray(): boolean {
|
||||
return !!this.get(ConfigKeys.LaunchToTray, false)
|
||||
|
||||
@ -2,7 +2,7 @@ import { preferenceService } from '@data/PreferenceService'
|
||||
import { loggerService } from '@logger'
|
||||
import { SELECTION_FINETUNED_LIST, SELECTION_PREDEFINED_BLACKLIST } from '@main/configs/SelectionConfig'
|
||||
import { isDev, isMac, isWin } from '@main/constant'
|
||||
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from '@shared/data/types'
|
||||
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { app, BrowserWindow, ipcMain, screen, systemPreferences } from 'electron'
|
||||
import { join } from 'path'
|
||||
@ -470,11 +470,11 @@ export class SelectionService {
|
||||
})
|
||||
|
||||
/** uncomment to open dev tools in dev mode */
|
||||
// if (isDev) {
|
||||
// this.toolbarWindow.once('ready-to-show', () => {
|
||||
// this.toolbarWindow!.webContents.openDevTools({ mode: 'detach' })
|
||||
// })
|
||||
// }
|
||||
if (isDev) {
|
||||
this.toolbarWindow.once('ready-to-show', () => {
|
||||
this.toolbarWindow!.webContents.openDevTools({ mode: 'detach' })
|
||||
})
|
||||
}
|
||||
|
||||
if (readyCallback) {
|
||||
this.toolbarWindow.once('ready-to-show', readyCallback)
|
||||
|
||||
@ -1,23 +1,28 @@
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { ThemeMode } from '@types'
|
||||
import { BrowserWindow, nativeTheme } from 'electron'
|
||||
|
||||
import { titleBarOverlayDark, titleBarOverlayLight } from '../config'
|
||||
import { configManager } from './ConfigManager'
|
||||
|
||||
class ThemeService {
|
||||
private theme: ThemeMode = ThemeMode.system
|
||||
constructor() {
|
||||
this.theme = configManager.getTheme()
|
||||
this.theme = preferenceService.get('app.theme.mode')
|
||||
|
||||
if (this.theme === ThemeMode.dark || this.theme === ThemeMode.light || this.theme === ThemeMode.system) {
|
||||
nativeTheme.themeSource = this.theme
|
||||
} else {
|
||||
// 兼容旧版本
|
||||
configManager.setTheme(ThemeMode.system)
|
||||
preferenceService.set('app.theme.mode', ThemeMode.system)
|
||||
nativeTheme.themeSource = ThemeMode.system
|
||||
}
|
||||
nativeTheme.on('updated', this.themeUpdatadHandler.bind(this))
|
||||
|
||||
preferenceService.subscribeChange('app.theme.mode', (newTheme) => {
|
||||
this.theme = newTheme
|
||||
nativeTheme.themeSource = newTheme
|
||||
})
|
||||
}
|
||||
|
||||
themeUpdatadHandler() {
|
||||
@ -30,19 +35,12 @@ class ThemeService {
|
||||
// Because it may be called with some windows have some title bar
|
||||
}
|
||||
}
|
||||
win.webContents.send(IpcChannel.ThemeUpdated, nativeTheme.shouldUseDarkColors ? ThemeMode.dark : ThemeMode.light)
|
||||
win.webContents.send(
|
||||
IpcChannel.NativeThemeUpdated,
|
||||
nativeTheme.shouldUseDarkColors ? ThemeMode.dark : ThemeMode.light
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
setTheme(theme: ThemeMode) {
|
||||
if (theme === this.theme) {
|
||||
return
|
||||
}
|
||||
|
||||
this.theme = theme
|
||||
nativeTheme.themeSource = theme
|
||||
configManager.setTheme(theme)
|
||||
}
|
||||
}
|
||||
|
||||
export const themeService = new ThemeService()
|
||||
|
||||
@ -4,8 +4,8 @@ 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 { PreferenceDefaultScopeType, PreferenceKeyType, SelectionActionItem } from '@shared/data/types'
|
||||
import type { FileChangeEvent } from '@shared/config/types'
|
||||
import type { PreferenceDefaultScopeType, PreferenceKeyType, SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import {
|
||||
AddMemoryOptions,
|
||||
@ -25,7 +25,6 @@ import {
|
||||
S3Config,
|
||||
Shortcut,
|
||||
SupportedOcrFile,
|
||||
ThemeMode,
|
||||
WebDavConfig
|
||||
} from '@types'
|
||||
import { contextBridge, ipcRenderer, OpenDialogOptions, shell, webUtils } from 'electron'
|
||||
@ -57,7 +56,7 @@ const api = {
|
||||
setTrayOnClose: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetTrayOnClose, isActive),
|
||||
setTestPlan: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetTestPlan, isActive),
|
||||
setTestChannel: (channel: UpgradeChannel) => ipcRenderer.invoke(IpcChannel.App_SetTestChannel, channel),
|
||||
setTheme: (theme: ThemeMode) => ipcRenderer.invoke(IpcChannel.App_SetTheme, theme),
|
||||
// setTheme: (theme: ThemeMode) => ipcRenderer.invoke(IpcChannel.App_SetTheme, theme),
|
||||
handleZoomFactor: (delta: number, reset: boolean = false) =>
|
||||
ipcRenderer.invoke(IpcChannel.App_HandleZoomFactor, delta, reset),
|
||||
setAutoUpdate: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetAutoUpdate, isActive),
|
||||
|
||||
@ -17,7 +17,7 @@ import Router from './Router'
|
||||
|
||||
const logger = loggerService.withContext('App.tsx')
|
||||
|
||||
preferenceService.loadAll()
|
||||
preferenceService.preloadAll()
|
||||
|
||||
// 创建 React Query 客户端
|
||||
const queryClient = new QueryClient({
|
||||
|
||||
@ -7,7 +7,7 @@ import Sidebar from './components/app/Sidebar'
|
||||
import { ErrorBoundary } from './components/ErrorBoundary'
|
||||
import TabsContainer from './components/Tab/TabContainer'
|
||||
import NavigationHandler from './handler/NavigationHandler'
|
||||
import { useNavbarPosition } from './hooks/useSettings'
|
||||
import { useNavbarPosition } from './hooks/useNavbar'
|
||||
import AgentsPage from './pages/agents/AgentsPage'
|
||||
import CodeToolsPage from './pages/code/CodeToolsPage'
|
||||
import FilesPage from './pages/files/FilesPage'
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { CodeOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { extractHtmlTitle, getFileNameFromHtmlTitle } from '@renderer/utils/formats'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button } from 'antd'
|
||||
import { Code, DownloadIcon, Globe, LinkIcon, Sparkles } from 'lucide-react'
|
||||
import { FC, useState } from 'react'
|
||||
|
||||
@ -4,8 +4,8 @@ import IndicatorLight from '@renderer/components/IndicatorLight'
|
||||
import { loadCustomMiniApp, ORIGIN_DEFAULT_MIN_APPS, updateDefaultMinApps } from '@renderer/config/minapps'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import { setOpenedKeepAliveMinapps } from '@renderer/store/runtime'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import type { MenuProps } from 'antd'
|
||||
|
||||
@ -17,8 +17,9 @@ import { useBridge } from '@renderer/hooks/useBridge'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setMinappsOpenLinkExternal } from '@renderer/store/settings'
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { WebviewTag } from 'electron'
|
||||
import { memo, useEffect, useRef } from 'react'
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@ import tabsService from '@renderer/services/TabsService'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import type { Tab } from '@renderer/store/tabs'
|
||||
import { addTab, removeTab, setActiveTab } from '@renderer/store/tabs'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Tooltip } from 'antd'
|
||||
import {
|
||||
FileSearch,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { isLinux, isMac, isWin } from '@renderer/config/constant'
|
||||
import { useFullscreen } from '@renderer/hooks/useFullscreen'
|
||||
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import type { FC, PropsWithChildren } from 'react'
|
||||
import type { HTMLAttributes } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
|
||||
@ -10,8 +10,8 @@ import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { getSidebarIconLabel, getThemeModeLabel } from '@renderer/i18n/label'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { isEmoji } from '@renderer/utils'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Avatar, Tooltip } from 'antd'
|
||||
import {
|
||||
Code,
|
||||
|
||||
@ -2,8 +2,8 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMermaid } from '@renderer/hooks/useMermaid'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { HighlightChunkResult, ShikiPreProperties, shikiStreamService } from '@renderer/services/ShikiStreamService'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { getHighlighter, getMarkdownIt, getShiki, loadLanguageIfNeeded, loadThemeIfNeeded } from '@renderer/utils/shiki'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import * as cmThemes from '@uiw/codemirror-themes-all'
|
||||
import type React from 'react'
|
||||
import { createContext, type PropsWithChildren, use, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { isMac, isWin } from '@renderer/config/constant'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import useUserTheme from '@renderer/hooks/useUserTheme'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import React, { createContext, PropsWithChildren, use, useEffect, useState } from 'react'
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: ThemeMode
|
||||
settedTheme: ThemeMode
|
||||
@ -25,7 +25,10 @@ interface ThemeProviderProps extends PropsWithChildren {
|
||||
|
||||
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
||||
// 用户设置的主题
|
||||
const { theme: settedTheme, setTheme: setSettedTheme } = useSettings()
|
||||
// const { theme: settedTheme, setTheme: setSettedTheme } = useSettings()
|
||||
|
||||
const [settedTheme, setSettedTheme] = usePreference('app.theme.mode')
|
||||
|
||||
const [actualTheme, setActualTheme] = useState<ThemeMode>(
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches ? ThemeMode.dark : ThemeMode.light
|
||||
)
|
||||
@ -56,18 +59,14 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
||||
initUserTheme()
|
||||
|
||||
// listen for theme updates from main process
|
||||
return window.electron.ipcRenderer.on(IpcChannel.ThemeUpdated, (_, actualTheme: ThemeMode) => {
|
||||
return window.electron.ipcRenderer.on(IpcChannel.NativeThemeUpdated, (_, actualTheme: ThemeMode) => {
|
||||
document.body.setAttribute('theme-mode', actualTheme)
|
||||
setActualTheme(actualTheme)
|
||||
})
|
||||
}, [actualTheme, initUserTheme, navbarPosition, setSettedTheme, settedTheme])
|
||||
|
||||
useEffect(() => {
|
||||
window.api.setTheme(settedTheme)
|
||||
}, [settedTheme])
|
||||
|
||||
return (
|
||||
<ThemeContext value={{ theme: actualTheme, settedTheme, toggleTheme, setTheme: setSettedTheme }}>
|
||||
<ThemeContext value={{ theme: actualTheme, settedTheme: settedTheme, toggleTheme, setTheme: setSettedTheme }}>
|
||||
{children}
|
||||
</ThemeContext>
|
||||
)
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
import { loggerService } from '@logger'
|
||||
import { DefaultPreferences } from '@shared/data/preferences'
|
||||
import type { PreferenceDefaultScopeType, PreferenceKeyType, PreferenceUpdateOptions } from '@shared/data/types'
|
||||
import type {
|
||||
PreferenceDefaultScopeType,
|
||||
PreferenceKeyType,
|
||||
PreferenceUpdateOptions
|
||||
} from '@shared/data/preferenceTypes'
|
||||
|
||||
const logger = loggerService.withContext('PreferenceService')
|
||||
/**
|
||||
@ -100,6 +104,8 @@ export class PreferenceService {
|
||||
return this.cache[key] as PreferenceDefaultScopeType[K]
|
||||
}
|
||||
|
||||
logger.verbose(`get: ${key} not found in cache`)
|
||||
|
||||
try {
|
||||
// Fetch from main process if not cached
|
||||
const value = await window.api.preference.get(key)
|
||||
@ -215,6 +221,7 @@ export class PreferenceService {
|
||||
if (key in this.cache && this.cache[key] !== undefined) {
|
||||
cachedResults[key] = this.cache[key]
|
||||
} else {
|
||||
logger.verbose(`getMultiple: ${key} not found in cache`)
|
||||
uncachedKeys.push(key)
|
||||
}
|
||||
}
|
||||
@ -408,7 +415,7 @@ export class PreferenceService {
|
||||
* Load all preferences from main process at once
|
||||
* Provides optimal performance by loading complete preference set into memory
|
||||
*/
|
||||
public async loadAll(): Promise<PreferenceDefaultScopeType> {
|
||||
public async preloadAll(): Promise<PreferenceDefaultScopeType> {
|
||||
try {
|
||||
const allPreferences = await window.api.preference.getAll()
|
||||
|
||||
@ -442,7 +449,7 @@ export class PreferenceService {
|
||||
/**
|
||||
* Preload specific preferences into cache
|
||||
*/
|
||||
async preload(keys: PreferenceKeyType[]): Promise<void> {
|
||||
public async preload(keys: PreferenceKeyType[]): Promise<void> {
|
||||
const uncachedKeys = keys.filter((key) => !this.isCached(key))
|
||||
|
||||
if (uncachedKeys.length > 0) {
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import { loggerService } from '@logger'
|
||||
import { DefaultPreferences } from '@shared/data/preferences'
|
||||
import type { PreferenceDefaultScopeType, PreferenceKeyType, PreferenceUpdateOptions } from '@shared/data/types'
|
||||
import type {
|
||||
PreferenceDefaultScopeType,
|
||||
PreferenceKeyType,
|
||||
PreferenceUpdateOptions
|
||||
} from '@shared/data/preferenceTypes'
|
||||
import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'
|
||||
|
||||
const logger = loggerService.withContext('usePreference')
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
// 跟踪 mermaid 模块状态,单例模式
|
||||
|
||||
12
src/renderer/src/hooks/useNavbar.ts
Normal file
12
src/renderer/src/hooks/useNavbar.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
|
||||
export const useNavbarPosition = () => {
|
||||
const [navbarPosition, setNavbarPosition] = usePreference('ui.navbar.position')
|
||||
|
||||
return {
|
||||
navbarPosition,
|
||||
isLeftNavbar: navbarPosition === 'left',
|
||||
isTopNavbar: navbarPosition === 'top',
|
||||
setNavbarPosition: (position: 'left' | 'top') => setNavbarPosition(position)
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,6 @@ import {
|
||||
setEnableDeveloperMode,
|
||||
setLaunchOnBoot,
|
||||
setLaunchToTray,
|
||||
setNavbarPosition,
|
||||
setPinTopicsToTop,
|
||||
setSendMessageShortcut as _setSendMessageShortcut,
|
||||
setShowTokens,
|
||||
@ -23,8 +22,9 @@ import {
|
||||
setTrayOnClose,
|
||||
setWindowStyle
|
||||
} from '@renderer/store/settings'
|
||||
import { SidebarIcon, ThemeMode, TranslateLanguageCode } from '@renderer/types'
|
||||
import { SidebarIcon, TranslateLanguageCode } from '@renderer/types'
|
||||
import { UpgradeChannel } from '@shared/config/constant'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
|
||||
export function useSettings() {
|
||||
const settings = useAppSelector((state) => state.settings)
|
||||
@ -140,15 +140,3 @@ export const useEnableDeveloperMode = () => {
|
||||
export const getEnableDeveloperMode = () => {
|
||||
return store.getState().settings.enableDeveloperMode
|
||||
}
|
||||
|
||||
export const useNavbarPosition = () => {
|
||||
const navbarPosition = useAppSelector((state) => state.settings.navbarPosition)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return {
|
||||
navbarPosition,
|
||||
isLeftNavbar: navbarPosition === 'left',
|
||||
isTopNavbar: navbarPosition === 'top',
|
||||
setNavbarPosition: (position: 'left' | 'top') => dispatch(setNavbarPosition(position))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { setUserTheme, UserTheme } from '@renderer/store/settings'
|
||||
// import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
// import { setUserTheme, UserTheme } from '@renderer/store/settings'
|
||||
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import Color from 'color'
|
||||
|
||||
export default function useUserTheme() {
|
||||
const userTheme = useAppSelector((state) => state.settings.userTheme)
|
||||
const [colorPrimary, setColorPrimary] = usePreference('app.theme.user.color_primary')
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const initUserTheme = (theme: UserTheme = userTheme) => {
|
||||
const initUserTheme = (theme: { colorPrimary: string } = { colorPrimary }) => {
|
||||
const colorPrimary = Color(theme.colorPrimary)
|
||||
|
||||
document.body.style.setProperty('--color-primary', colorPrimary.toString())
|
||||
@ -16,13 +16,14 @@ export default function useUserTheme() {
|
||||
}
|
||||
|
||||
return {
|
||||
colorPrimary: Color(userTheme.colorPrimary),
|
||||
colorPrimary: Color(colorPrimary),
|
||||
|
||||
initUserTheme,
|
||||
|
||||
setUserTheme(userTheme: UserTheme) {
|
||||
dispatch(setUserTheme(userTheme))
|
||||
userTheme: { colorPrimary },
|
||||
|
||||
setUserTheme(userTheme: { colorPrimary: string }) {
|
||||
setColorPrimary(userTheme.colorPrimary)
|
||||
initUserTheme(userTheme)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import ListItem from '@renderer/components/ListItem'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
|
||||
import { Agent } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
|
||||
@ -5,7 +5,8 @@ import MultiSelectActionPopup from '@renderer/components/Popups/MultiSelectionPo
|
||||
import { QuickPanelProvider } from '@renderer/components/QuickPanel'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ErrorBoundary } from '@renderer/components/ErrorBoundary'
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useActiveTopic } from '@renderer/hooks/useTopic'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import NavigationService from '@renderer/services/NavigationService'
|
||||
|
||||
@ -2,7 +2,7 @@ import { FormOutlined } from '@ant-design/icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { EventEmitter } from '@renderer/services/EventService'
|
||||
import { EVENT_NAMES } from '@renderer/services/EventService'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button as AntdButton } from 'antd'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -43,9 +43,10 @@ import {
|
||||
setShowTranslateConfirm,
|
||||
setThoughtAutoCollapse
|
||||
} from '@renderer/store/settings'
|
||||
import { Assistant, AssistantSettings, CodeStyleVarious, MathEngine, ThemeMode } from '@renderer/types'
|
||||
import { Assistant, AssistantSettings, CodeStyleVarious, MathEngine } from '@renderer/types'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { getSendMessageShortcutLabel } from '@renderer/utils/input'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Col, InputNumber, Row, Slider, Switch, Tooltip } from 'antd'
|
||||
import { CircleHelp, Settings2 } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShowTopics } from '@renderer/hooks/useStore'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
|
||||
@ -2,7 +2,7 @@ import { Navbar, NavbarMain } from '@renderer/components/app/Navbar'
|
||||
import App from '@renderer/components/MinApp/MinApp'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { Button, Input } from 'antd'
|
||||
import { Search, SettingsIcon } from 'lucide-react'
|
||||
import React, { FC, useState } from 'react'
|
||||
|
||||
@ -9,9 +9,9 @@ import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { handleSaveData, useAppDispatch } from '@renderer/store'
|
||||
import { setUpdateState } from '@renderer/store/runtime'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { runAsyncFunction } from '@renderer/utils'
|
||||
import { UpgradeChannel } from '@shared/config/constant'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Avatar, Button, Progress, Radio, Row, Switch, Tag, Tooltip } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
import { Bug, FileCheck, Github, Globe, Mail, Rss } from 'lucide-react'
|
||||
|
||||
@ -5,7 +5,8 @@ import TextBadge from '@renderer/components/TextBadge'
|
||||
import { isMac, THEME_COLOR_PRESETS } from '@renderer/config/constant'
|
||||
import { DEFAULT_SIDEBAR_ICONS } from '@renderer/config/sidebar'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import useUserTheme from '@renderer/hooks/useUserTheme'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import {
|
||||
@ -17,7 +18,7 @@ import {
|
||||
setShowTopicTime,
|
||||
setSidebarIcons
|
||||
} from '@renderer/store/settings'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, ColorPicker, Segmented, Switch } from 'antd'
|
||||
import { Minus, Monitor, Moon, Plus, Sun } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
@ -65,16 +66,14 @@ const DisplaySettings: FC = () => {
|
||||
pinTopicsToTop,
|
||||
customCss,
|
||||
sidebarIcons,
|
||||
setTheme,
|
||||
assistantIconType,
|
||||
userTheme
|
||||
assistantIconType
|
||||
} = useSettings()
|
||||
const { navbarPosition, setNavbarPosition } = useNavbarPosition()
|
||||
const { theme, settedTheme } = useTheme()
|
||||
const { theme, settedTheme, setTheme } = useTheme()
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useAppDispatch()
|
||||
const [currentZoom, setCurrentZoom] = useState(1.0)
|
||||
const { setUserTheme } = useUserTheme()
|
||||
const { userTheme, setUserTheme } = useUserTheme()
|
||||
|
||||
const [visibleIcons, setVisibleIcons] = useState(sidebarIcons?.visible || DEFAULT_SIDEBAR_ICONS)
|
||||
const [disabledIcons, setDisabledIcons] = useState(sidebarIcons?.disabled || [])
|
||||
|
||||
@ -3,7 +3,7 @@ import { isMac, isWin } from '@renderer/config/constant'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { getSelectionDescriptionLabel } from '@renderer/i18n/label'
|
||||
import SelectionToolbar from '@renderer/windows/selection/toolbar/SelectionToolbar'
|
||||
import type { SelectionFilterMode, SelectionTriggerMode } from '@shared/data/types'
|
||||
import type { SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Radio, Row, Slider, Switch, Tooltip } from 'antd'
|
||||
import { CircleHelp, Edit2 } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { DroppableProvided } from '@hello-pangea/dnd'
|
||||
import { Draggable, Droppable } from '@hello-pangea/dnd'
|
||||
import type { ActionItem as ActionItemType } from '@renderer/types/selectionTypes'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { memo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -8,9 +8,9 @@ import ActionsListItemComponent from './ActionsListItem'
|
||||
|
||||
interface ActionListProps {
|
||||
droppableId: 'enabled' | 'disabled'
|
||||
items: ActionItemType[]
|
||||
items: SelectionActionItem[]
|
||||
isLastEnabledItem: boolean
|
||||
onEdit: (item: ActionItemType) => void
|
||||
onEdit: (item: SelectionActionItem) => void
|
||||
onDelete: (id: string) => void
|
||||
getSearchEngineInfo: (engine: string) => { icon: any; name: string } | null
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { DraggableProvided } from '@hello-pangea/dnd'
|
||||
import type { ActionItem as ActionItemType } from '@renderer/types/selectionTypes'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { Button } from 'antd'
|
||||
import { Pencil, Settings2, Trash } from 'lucide-react'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
@ -8,11 +8,11 @@ import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface ActionItemProps {
|
||||
item: ActionItemType
|
||||
item: SelectionActionItem
|
||||
provided: DraggableProvided
|
||||
listType: 'enabled' | 'disabled'
|
||||
isLastEnabledItem: boolean
|
||||
onEdit: (item: ActionItemType) => void
|
||||
onEdit: (item: SelectionActionItem) => void
|
||||
onDelete: (id: string) => void
|
||||
getSearchEngineInfo: (engine: string) => { icon: any; name: string } | null
|
||||
}
|
||||
@ -49,8 +49,8 @@ const ActionsListItem = memo(
|
||||
)
|
||||
|
||||
interface ActionOperationsProps {
|
||||
item: ActionItemType
|
||||
onEdit: (item: ActionItemType) => void
|
||||
item: SelectionActionItem
|
||||
onEdit: (item: SelectionActionItem) => void
|
||||
onDelete: (id: string) => void
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { loggerService } from '@logger'
|
||||
import type { ActionItem } from '@renderer/types/selectionTypes'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { Button, Form, Input, Modal, Select } from 'antd'
|
||||
import { Globe } from 'lucide-react'
|
||||
import { FC, useEffect } from 'react'
|
||||
@ -79,7 +79,7 @@ interface SelectionActionSearchModalProps {
|
||||
isModalOpen: boolean
|
||||
onOk: (searchEngine: string) => void
|
||||
onCancel: () => void
|
||||
currentAction?: ActionItem
|
||||
currentAction?: SelectionActionItem
|
||||
}
|
||||
|
||||
const SelectionActionSearchModal: FC<SelectionActionSearchModalProps> = ({
|
||||
|
||||
@ -2,7 +2,7 @@ import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import CopyButton from '@renderer/components/CopyButton'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import type { ActionItem } from '@renderer/types/selectionTypes'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { Col, Input, Modal, Radio, Row, Select, Space, Tooltip } from 'antd'
|
||||
import { CircleHelp, Dices, OctagonX } from 'lucide-react'
|
||||
import { DynamicIcon, iconNames } from 'lucide-react/dynamic'
|
||||
@ -12,8 +12,8 @@ import styled from 'styled-components'
|
||||
|
||||
interface SelectionActionUserModalProps {
|
||||
isModalOpen: boolean
|
||||
editingAction: ActionItem | null
|
||||
onOk: (data: ActionItem) => void
|
||||
editingAction: SelectionActionItem | null
|
||||
onOk: (data: SelectionActionItem) => void
|
||||
onCancel: () => void
|
||||
}
|
||||
|
||||
@ -27,8 +27,8 @@ const SelectionActionUserModal: FC<SelectionActionUserModalProps> = ({
|
||||
const { assistants: userPredefinedAssistants } = useAssistants()
|
||||
const { defaultAssistant } = useDefaultAssistant()
|
||||
|
||||
const [formData, setFormData] = useState<Partial<ActionItem>>({})
|
||||
const [errors, setErrors] = useState<Partial<Record<keyof ActionItem, string>>>({})
|
||||
const [formData, setFormData] = useState<Partial<SelectionActionItem>>({})
|
||||
const [errors, setErrors] = useState<Partial<Record<keyof SelectionActionItem, string>>>({})
|
||||
|
||||
useEffect(() => {
|
||||
if (isModalOpen) {
|
||||
@ -46,7 +46,7 @@ const SelectionActionUserModal: FC<SelectionActionUserModalProps> = ({
|
||||
}, [isModalOpen, editingAction])
|
||||
|
||||
const validateForm = (): boolean => {
|
||||
const newErrors: Partial<Record<keyof ActionItem, string>> = {}
|
||||
const newErrors: Partial<Record<keyof SelectionActionItem, string>> = {}
|
||||
|
||||
if (!formData.name?.trim()) {
|
||||
newErrors.name = t('selection.settings.user_modal.name.hint')
|
||||
@ -66,7 +66,7 @@ const SelectionActionUserModal: FC<SelectionActionUserModalProps> = ({
|
||||
}
|
||||
|
||||
// 构建完整的 ActionItem
|
||||
const actionItem: ActionItem = {
|
||||
const actionItem: SelectionActionItem = {
|
||||
id: editingAction?.id || `user-${Date.now()}`,
|
||||
name: formData.name || 'USER',
|
||||
enabled: editingAction?.enabled || false,
|
||||
@ -79,7 +79,7 @@ const SelectionActionUserModal: FC<SelectionActionUserModalProps> = ({
|
||||
onOk(actionItem)
|
||||
}
|
||||
|
||||
const handleInputChange = (field: keyof ActionItem, value: string) => {
|
||||
const handleInputChange = (field: keyof SelectionActionItem, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }))
|
||||
// Clear error when user starts typing
|
||||
if (errors[field]) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { DragDropContext } from '@hello-pangea/dnd'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { defaultActionItems } from '@renderer/store/selectionStore'
|
||||
import type { ActionItem } from '@renderer/types/selectionTypes'
|
||||
import SelectionToolbar from '@renderer/windows/selection/toolbar/SelectionToolbar'
|
||||
import { DefaultPreferences } from '@shared/data/preferences'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { Row } from 'antd'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -20,8 +20,8 @@ import SettingsActionsListHeader from './SettingsActionsListHeader'
|
||||
|
||||
// Props for the main component
|
||||
interface SelectionActionsListProps {
|
||||
actionItems: ActionItem[] | undefined // List of all available actions
|
||||
setActionItems: (items: ActionItem[]) => void // Function to update action items
|
||||
actionItems: SelectionActionItem[] | undefined // List of all available actions
|
||||
setActionItems: (items: SelectionActionItem[]) => void // Function to update action items
|
||||
}
|
||||
|
||||
const SelectionActionsList: FC<SelectionActionsListProps> = ({ actionItems, setActionItems }) => {
|
||||
@ -49,7 +49,7 @@ const SelectionActionsList: FC<SelectionActionsListProps> = ({ actionItems, setA
|
||||
const { theme } = useTheme()
|
||||
|
||||
if (!actionItems || actionItems.length === 0) {
|
||||
setActionItems(defaultActionItems)
|
||||
setActionItems(DefaultPreferences.default['feature.selection.action_items'])
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { DropResult } from '@hello-pangea/dnd'
|
||||
import { loggerService } from '@logger'
|
||||
import { defaultActionItems } from '@renderer/store/selectionStore'
|
||||
import type { ActionItem } from '@renderer/types/selectionTypes'
|
||||
import { DefaultPreferences } from '@shared/data/preferences'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -13,19 +13,19 @@ const MAX_CUSTOM_ITEMS = 8
|
||||
const MAX_ENABLED_ITEMS = 6
|
||||
|
||||
export const useActionItems = (
|
||||
initialItems: ActionItem[] | undefined,
|
||||
setActionItems: (items: ActionItem[]) => void
|
||||
initialItems: SelectionActionItem[] | undefined,
|
||||
setActionItems: (items: SelectionActionItem[]) => void
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const [isUserModalOpen, setIsUserModalOpen] = useState(false)
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false)
|
||||
const [userEditingAction, setUserEditingAction] = useState<ActionItem | null>(null)
|
||||
const [userEditingAction, setUserEditingAction] = useState<SelectionActionItem | null>(null)
|
||||
|
||||
const enabledItems = useMemo(() => initialItems?.filter((item) => item.enabled) ?? [], [initialItems])
|
||||
const disabledItems = useMemo(() => initialItems?.filter((item) => !item.enabled) ?? [], [initialItems])
|
||||
const customItemsCount = useMemo(() => initialItems?.filter((item) => !item.isBuiltIn).length ?? 0, [initialItems])
|
||||
|
||||
const handleEditActionItem = (item: ActionItem) => {
|
||||
const handleEditActionItem = (item: SelectionActionItem) => {
|
||||
if (item.isBuiltIn) {
|
||||
if (item.id === 'search') {
|
||||
setIsSearchModalOpen(true)
|
||||
@ -43,7 +43,7 @@ export const useActionItems = (
|
||||
setIsUserModalOpen(true)
|
||||
}
|
||||
|
||||
const handleUserModalOk = (actionItem: ActionItem) => {
|
||||
const handleUserModalOk = (actionItem: SelectionActionItem) => {
|
||||
if (userEditingAction && initialItems) {
|
||||
const updatedItems = initialItems.map((item) => (item.id === userEditingAction.id ? actionItem : item))
|
||||
setActionItems(updatedItems)
|
||||
@ -83,7 +83,7 @@ export const useActionItems = (
|
||||
content: t('selection.settings.actions.reset.confirm'),
|
||||
onOk: () => {
|
||||
const userItems = initialItems.filter((item) => !item.isBuiltIn).map((item) => ({ ...item, enabled: false }))
|
||||
setActionItems([...defaultActionItems, ...userItems])
|
||||
setActionItems([...DefaultPreferences.default['feature.selection.action_items'], ...userItems])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { ChevronDown, ChevronRight } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Divider } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import styled, { CSSProp } from 'styled-components'
|
||||
|
||||
@ -26,7 +26,7 @@ import ocr from './ocr'
|
||||
import paintings from './paintings'
|
||||
import preprocess from './preprocess'
|
||||
import runtime from './runtime'
|
||||
import selectionStore from './selectionStore'
|
||||
// import selectionStore from './selectionStore'
|
||||
import settings from './settings'
|
||||
import shortcuts from './shortcuts'
|
||||
import tabs from './tabs'
|
||||
@ -52,7 +52,7 @@ const rootReducer = combineReducers({
|
||||
mcp,
|
||||
memory,
|
||||
copilot,
|
||||
selectionStore,
|
||||
// selectionStore,
|
||||
tabs,
|
||||
preprocess,
|
||||
messages: newMessagesReducer,
|
||||
|
||||
@ -41,7 +41,7 @@ import { DEFAULT_TOOL_ORDER } from './inputTools'
|
||||
import { initialState as llmInitialState, moveProvider } from './llm'
|
||||
import { mcpSlice } from './mcp'
|
||||
import { initialState as notesInitialState } from './note'
|
||||
import { defaultActionItems } from './selectionStore'
|
||||
// import { defaultActionItems } from './selectionStore'
|
||||
import { initialState as settingsInitialState } from './settings'
|
||||
import { initialState as shortcutsInitialState } from './shortcuts'
|
||||
import { defaultWebSearchProviders } from './websearch'
|
||||
@ -127,14 +127,15 @@ function updateWebSearchProvider(state: RootState, provider: Partial<WebSearchPr
|
||||
}
|
||||
|
||||
function addSelectionAction(state: RootState, id: string) {
|
||||
if (state.selectionStore && state.selectionStore.actionItems) {
|
||||
if (!state.selectionStore.actionItems.some((item) => item.id === id)) {
|
||||
const action = defaultActionItems.find((item) => item.id === id)
|
||||
if (action) {
|
||||
state.selectionStore.actionItems.push(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (state.selectionStore && state.selectionStore.actionItems) {
|
||||
// if (!state.selectionStore.actionItems.some((item) => item.id === id)) {
|
||||
// const action = defaultActionItems.find((item) => item.id === id)
|
||||
// if (action) {
|
||||
// state.selectionStore.actionItems.push(action)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return [state, id]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,89 +1,89 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { ActionItem, FilterMode, SelectionState, TriggerMode } from '@renderer/types/selectionTypes'
|
||||
// import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
// import { SelectionActionItem, FilterMode, SelectionState, TriggerMode } from '@shared/data/preferenceTypes'
|
||||
|
||||
export const defaultActionItems: ActionItem[] = [
|
||||
{ id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
|
||||
{ id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
|
||||
{ id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
|
||||
{
|
||||
id: 'search',
|
||||
name: 'selection.action.builtin.search',
|
||||
enabled: true,
|
||||
isBuiltIn: true,
|
||||
icon: 'search',
|
||||
searchEngine: 'Google|https://www.google.com/search?q={{queryString}}'
|
||||
},
|
||||
{ id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
|
||||
{ id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
|
||||
{ id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
|
||||
]
|
||||
// export const defaultActionItems: ActionItem[] = [
|
||||
// { id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
|
||||
// { id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
|
||||
// { id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
|
||||
// {
|
||||
// id: 'search',
|
||||
// name: 'selection.action.builtin.search',
|
||||
// enabled: true,
|
||||
// isBuiltIn: true,
|
||||
// icon: 'search',
|
||||
// searchEngine: 'Google|https://www.google.com/search?q={{queryString}}'
|
||||
// },
|
||||
// { id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
|
||||
// { id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
|
||||
// { id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
|
||||
// ]
|
||||
|
||||
export const initialState: SelectionState = {
|
||||
selectionEnabled: false,
|
||||
triggerMode: 'selected',
|
||||
isCompact: false,
|
||||
isAutoClose: false,
|
||||
isAutoPin: false,
|
||||
isFollowToolbar: true,
|
||||
isRemeberWinSize: false,
|
||||
filterMode: 'default',
|
||||
filterList: [],
|
||||
actionWindowOpacity: 100,
|
||||
actionItems: defaultActionItems
|
||||
}
|
||||
// export const initialState: SelectionState = {
|
||||
// selectionEnabled: false,
|
||||
// triggerMode: 'selected',
|
||||
// isCompact: false,
|
||||
// isAutoClose: false,
|
||||
// isAutoPin: false,
|
||||
// isFollowToolbar: true,
|
||||
// isRemeberWinSize: false,
|
||||
// filterMode: 'default',
|
||||
// filterList: [],
|
||||
// actionWindowOpacity: 100,
|
||||
// actionItems: defaultActionItems
|
||||
// }
|
||||
|
||||
const selectionSlice = createSlice({
|
||||
name: 'selectionStore',
|
||||
initialState,
|
||||
reducers: {
|
||||
setSelectionEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
state.selectionEnabled = action.payload
|
||||
},
|
||||
setTriggerMode: (state, action: PayloadAction<TriggerMode>) => {
|
||||
state.triggerMode = action.payload
|
||||
},
|
||||
setIsCompact: (state, action: PayloadAction<boolean>) => {
|
||||
state.isCompact = action.payload
|
||||
},
|
||||
setIsAutoClose: (state, action: PayloadAction<boolean>) => {
|
||||
state.isAutoClose = action.payload
|
||||
},
|
||||
setIsAutoPin: (state, action: PayloadAction<boolean>) => {
|
||||
state.isAutoPin = action.payload
|
||||
},
|
||||
setIsFollowToolbar: (state, action: PayloadAction<boolean>) => {
|
||||
state.isFollowToolbar = action.payload
|
||||
},
|
||||
setIsRemeberWinSize: (state, action: PayloadAction<boolean>) => {
|
||||
state.isRemeberWinSize = action.payload
|
||||
},
|
||||
setFilterMode: (state, action: PayloadAction<FilterMode>) => {
|
||||
state.filterMode = action.payload
|
||||
},
|
||||
setFilterList: (state, action: PayloadAction<string[]>) => {
|
||||
state.filterList = action.payload
|
||||
},
|
||||
setActionWindowOpacity: (state, action: PayloadAction<number>) => {
|
||||
state.actionWindowOpacity = action.payload
|
||||
},
|
||||
setActionItems: (state, action: PayloadAction<ActionItem[]>) => {
|
||||
state.actionItems = action.payload
|
||||
}
|
||||
}
|
||||
})
|
||||
// const selectionSlice = createSlice({
|
||||
// name: 'selectionStore',
|
||||
// initialState,
|
||||
// reducers: {
|
||||
// setSelectionEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
// state.selectionEnabled = action.payload
|
||||
// },
|
||||
// setTriggerMode: (state, action: PayloadAction<TriggerMode>) => {
|
||||
// state.triggerMode = action.payload
|
||||
// },
|
||||
// setIsCompact: (state, action: PayloadAction<boolean>) => {
|
||||
// state.isCompact = action.payload
|
||||
// },
|
||||
// setIsAutoClose: (state, action: PayloadAction<boolean>) => {
|
||||
// state.isAutoClose = action.payload
|
||||
// },
|
||||
// setIsAutoPin: (state, action: PayloadAction<boolean>) => {
|
||||
// state.isAutoPin = action.payload
|
||||
// },
|
||||
// setIsFollowToolbar: (state, action: PayloadAction<boolean>) => {
|
||||
// state.isFollowToolbar = action.payload
|
||||
// },
|
||||
// setIsRemeberWinSize: (state, action: PayloadAction<boolean>) => {
|
||||
// state.isRemeberWinSize = action.payload
|
||||
// },
|
||||
// setFilterMode: (state, action: PayloadAction<FilterMode>) => {
|
||||
// state.filterMode = action.payload
|
||||
// },
|
||||
// setFilterList: (state, action: PayloadAction<string[]>) => {
|
||||
// state.filterList = action.payload
|
||||
// },
|
||||
// setActionWindowOpacity: (state, action: PayloadAction<number>) => {
|
||||
// state.actionWindowOpacity = action.payload
|
||||
// },
|
||||
// setActionItems: (state, action: PayloadAction<ActionItem[]>) => {
|
||||
// state.actionItems = action.payload
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
export const {
|
||||
setSelectionEnabled,
|
||||
setTriggerMode,
|
||||
setIsCompact,
|
||||
setIsAutoClose,
|
||||
setIsAutoPin,
|
||||
setIsFollowToolbar,
|
||||
setIsRemeberWinSize,
|
||||
setFilterMode,
|
||||
setFilterList,
|
||||
setActionWindowOpacity,
|
||||
setActionItems
|
||||
} = selectionSlice.actions
|
||||
// export const {
|
||||
// setSelectionEnabled,
|
||||
// setTriggerMode,
|
||||
// setIsCompact,
|
||||
// setIsAutoClose,
|
||||
// setIsAutoPin,
|
||||
// setIsFollowToolbar,
|
||||
// setIsRemeberWinSize,
|
||||
// setFilterMode,
|
||||
// setFilterList,
|
||||
// setActionWindowOpacity,
|
||||
// setActionItems
|
||||
// } = selectionSlice.actions
|
||||
|
||||
export default selectionSlice.reducer
|
||||
// export default selectionSlice.reducer
|
||||
|
||||
@ -13,11 +13,11 @@ import {
|
||||
PaintingProvider,
|
||||
S3Config,
|
||||
SidebarIcon,
|
||||
ThemeMode,
|
||||
TranslateLanguageCode
|
||||
} from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { UpgradeChannel } from '@shared/config/constant'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { OpenAIVerbosity } from '@types'
|
||||
|
||||
import { RemoteSyncState } from './backup'
|
||||
@ -57,7 +57,9 @@ export interface SettingsState {
|
||||
trayOnClose: boolean
|
||||
tray: boolean
|
||||
theme: ThemeMode
|
||||
userTheme: UserTheme
|
||||
userTheme: {
|
||||
colorPrimary: string
|
||||
}
|
||||
windowStyle: 'transparent' | 'opaque'
|
||||
fontSize: number
|
||||
topicPosition: 'left' | 'right'
|
||||
|
||||
@ -532,12 +532,6 @@ export type MinAppType = {
|
||||
type?: 'Custom' | 'Default' // Added the 'type' property
|
||||
}
|
||||
|
||||
export enum ThemeMode {
|
||||
light = 'light',
|
||||
dark = 'dark',
|
||||
system = 'system'
|
||||
}
|
||||
|
||||
/** 有限的UI语言 */
|
||||
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'el-GR' | 'en-US' | 'es-ES' | 'fr-FR' | 'ja-JP' | 'pt-PT' | 'ru-RU'
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { AppLogo } from '@renderer/config/env'
|
||||
import { usePreference } from '@renderer/data/hooks/usePreference'
|
||||
import { loggerService } from '@renderer/services/LoggerService'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Card, Col, Divider, Layout, Row, Space, Typography } from 'antd'
|
||||
import { Database, FlaskConical, Settings, TestTube } from 'lucide-react'
|
||||
import React from 'react'
|
||||
@ -53,7 +54,7 @@ const TestApp: React.FC = () => {
|
||||
const [zoomFactor] = usePreference('app.zoom_factor')
|
||||
|
||||
// Apply theme-based styling
|
||||
const isDarkTheme = theme === 'ThemeMode.dark'
|
||||
const isDarkTheme = theme === ThemeMode.dark
|
||||
const headerBg = isDarkTheme ? '#141414' : '#fff'
|
||||
const borderColor = isDarkTheme ? '#303030' : '#f0f0f0'
|
||||
const textColor = isDarkTheme ? '#fff' : '#000'
|
||||
@ -176,7 +177,7 @@ const TestApp: React.FC = () => {
|
||||
<Button
|
||||
icon={isDarkTheme ? '☀️' : '🌙'}
|
||||
onClick={async () => {
|
||||
await setTheme(isDarkTheme ? 'ThemeMode.light' : 'ThemeMode.dark')
|
||||
await setTheme(isDarkTheme ? ThemeMode.light : ThemeMode.dark)
|
||||
}}
|
||||
style={{
|
||||
backgroundColor: isDarkTheme ? '#434343' : '#f0f0f0',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { usePreference } from '@renderer/data/hooks/usePreference'
|
||||
import type { PreferenceKeyType } from '@shared/data/types'
|
||||
import { type PreferenceKeyType, ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Input, message, Select, Slider, Space, Switch, Typography } from 'antd'
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -21,7 +21,7 @@ const PreferenceBasicTests: React.FC = () => {
|
||||
|
||||
// Add theme monitoring for visual changes
|
||||
const [currentTheme] = usePreference('app.theme.mode')
|
||||
const isDarkTheme = currentTheme === 'ThemeMode.dark'
|
||||
const isDarkTheme = currentTheme === ThemeMode.dark
|
||||
|
||||
const handleSetValue = async () => {
|
||||
try {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { usePreference } from '@renderer/data/hooks/usePreference'
|
||||
import { preferenceService } from '@renderer/data/PreferenceService'
|
||||
import { loggerService } from '@renderer/services/LoggerService'
|
||||
import type { PreferenceKeyType } from '@shared/data/types'
|
||||
import { type PreferenceKeyType, ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Card, message, Space, Typography } from 'antd'
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -77,7 +77,7 @@ const PreferenceHookTests: React.FC = () => {
|
||||
|
||||
// Test batch set
|
||||
await preferenceService.setMultiple({
|
||||
'app.theme.mode': theme1 === 'ThemeMode.dark' ? 'ThemeMode.light' : 'ThemeMode.dark',
|
||||
'app.theme.mode': theme1 === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark,
|
||||
'app.language': language === 'zh-CN' ? 'en-US' : 'zh-CN'
|
||||
})
|
||||
|
||||
@ -102,7 +102,10 @@ const PreferenceHookTests: React.FC = () => {
|
||||
// Test rapid writes
|
||||
const writeStart = performance.now()
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await preferenceService.set('app.theme.mode', `ThemeMode.test_${i}`)
|
||||
await preferenceService.set(
|
||||
'app.theme.mode',
|
||||
i % 3 === 0 ? ThemeMode.light : i % 3 === 1 ? ThemeMode.dark : ThemeMode.system
|
||||
)
|
||||
}
|
||||
const writeTime = performance.now() - writeStart
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { usePreference } from '@renderer/data/hooks/usePreference'
|
||||
import { preferenceService } from '@renderer/data/PreferenceService'
|
||||
import type { PreferenceKeyType } from '@shared/data/types'
|
||||
import { type PreferenceKeyType, ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { Button, Input, message, Space, Typography } from 'antd'
|
||||
import React, { useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -13,13 +13,13 @@ const { Text } = Typography
|
||||
*/
|
||||
const PreferenceServiceTests: React.FC = () => {
|
||||
const [testKey, setTestKey] = useState<string>('app.theme.mode')
|
||||
const [testValue, setTestValue] = useState<string>('ThemeMode.dark')
|
||||
const [testValue, setTestValue] = useState<string>(ThemeMode.dark)
|
||||
const [getResult, setGetResult] = useState<any>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// Theme monitoring for visual changes
|
||||
const [currentTheme] = usePreference('app.theme.mode')
|
||||
const isDarkTheme = currentTheme === 'ThemeMode.dark'
|
||||
const isDarkTheme = currentTheme === ThemeMode.dark
|
||||
|
||||
const handleGet = async () => {
|
||||
try {
|
||||
@ -104,7 +104,7 @@ const PreferenceServiceTests: React.FC = () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
// Use loadAll to get all preferences at once
|
||||
const result = await preferenceService.loadAll()
|
||||
const result = await preferenceService.preloadAll()
|
||||
setGetResult(`All preferences (${Object.keys(result).length} keys):\n${JSON.stringify(result, null, 2)}`)
|
||||
message.success('获取所有偏好设置成功')
|
||||
} catch (error) {
|
||||
@ -174,7 +174,7 @@ const PreferenceServiceTests: React.FC = () => {
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setTestKey('app.theme.mode')
|
||||
setTestValue('ThemeMode.dark')
|
||||
setTestValue(ThemeMode.dark)
|
||||
}}>
|
||||
Test: app.theme.mode
|
||||
</Button>
|
||||
|
||||
@ -11,7 +11,7 @@ import store, { useAppSelector } from '@renderer/store'
|
||||
import { updateOneBlock, upsertManyBlocks, upsertOneBlock } from '@renderer/store/messageBlock'
|
||||
import { newMessagesActions, selectMessagesForTopic } from '@renderer/store/newMessage'
|
||||
import { cancelThrottledBlockUpdate, throttledBlockUpdate } from '@renderer/store/thunk/messageThunk'
|
||||
import { ThemeMode, Topic } from '@renderer/types'
|
||||
import { Topic } from '@renderer/types'
|
||||
import { Chunk, ChunkType } from '@renderer/types/chunk'
|
||||
import { AssistantMessageStatus, MessageBlockStatus } from '@renderer/types/newMessage'
|
||||
import { abortCompletion } from '@renderer/utils/abortController'
|
||||
@ -19,6 +19,7 @@ import { isAbortError } from '@renderer/utils/error'
|
||||
import { createMainTextBlock, createThinkingBlock } from '@renderer/utils/messageUtils/create'
|
||||
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||
import { defaultLanguage } from '@shared/config/constant'
|
||||
import { ThemeMode } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Divider } from 'antd'
|
||||
import { cloneDeep, isEmpty } from 'lodash'
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { defaultLanguage } from '@shared/config/constant'
|
||||
import type { SelectionActionItem } from '@shared/data/types'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Button, Slider, Tooltip } from 'antd'
|
||||
import { Droplet, Minus, Pin, X } from 'lucide-react'
|
||||
@ -16,8 +15,8 @@ import ActionGeneral from './components/ActionGeneral'
|
||||
import ActionTranslate from './components/ActionTranslate'
|
||||
|
||||
const SelectionActionApp: FC = () => {
|
||||
const { language, customCss } = useSettings()
|
||||
|
||||
const [language] = usePreference('app.language')
|
||||
const [customCss] = usePreference('ui.custom_css')
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [action, setAction] = useState<SelectionActionItem | null>(null)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import CopyButton from '@renderer/components/CopyButton'
|
||||
import { useTopicMessages } from '@renderer/hooks/useMessageOperations'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import MessageContent from '@renderer/pages/home/Messages/MessageContent'
|
||||
import {
|
||||
getAssistantById,
|
||||
@ -13,7 +13,7 @@ import {
|
||||
import { pauseTrace } from '@renderer/services/SpanManagerService'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
import { abortCompletion } from '@renderer/utils/abortController'
|
||||
import type { SelectionActionItem } from '@shared/data/types'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -30,7 +30,7 @@ interface Props {
|
||||
|
||||
const ActionGeneral: FC<Props> = React.memo(({ action, scrollToBottom }) => {
|
||||
const { t } = useTranslation()
|
||||
const { language } = useSettings()
|
||||
const [language] = usePreference('app.language')
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [showOriginal, setShowOriginal] = useState(false)
|
||||
const [isContented, setIsContented] = useState(false)
|
||||
|
||||
@ -13,7 +13,7 @@ import { Assistant, Topic, TranslateLanguage, TranslateLanguageCode } from '@ren
|
||||
import { runAsyncFunction } from '@renderer/utils'
|
||||
import { abortCompletion } from '@renderer/utils/abortController'
|
||||
import { detectLanguage } from '@renderer/utils/translate'
|
||||
import type { SelectionActionItem } from '@shared/data/types'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { Tooltip } from 'antd'
|
||||
import { ArrowRightFromLine, ArrowRightToLine, ChevronDown, CircleHelp, Globe } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import '@renderer/assets/styles/index.scss'
|
||||
import '@ant-design/v5-patch-for-react-19'
|
||||
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import KeyvStorage from '@kangfenmao/keyv-storage'
|
||||
import { loggerService } from '@logger'
|
||||
import AntdProvider from '@renderer/context/AntdProvider'
|
||||
@ -17,6 +18,17 @@ import { PersistGate } from 'redux-persist/integration/react'
|
||||
import SelectionActionApp from './SelectionActionApp'
|
||||
|
||||
loggerService.initWindowSource('SelectionActionWindow')
|
||||
|
||||
await preferenceService.preload([
|
||||
'app.language',
|
||||
'ui.custom_css',
|
||||
'app.theme.mode',
|
||||
'app.theme.user.color_primary',
|
||||
'feature.selection.auto_close',
|
||||
'feature.selection.auto_pin',
|
||||
'feature.selection.action_window_opacity'
|
||||
])
|
||||
|
||||
/**
|
||||
* fetchChatCompletion depends on this,
|
||||
* which is not a good design, but we have to add it for now
|
||||
|
||||
@ -3,11 +3,10 @@ import '@renderer/assets/styles/selection-toolbar.scss'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { AppLogo } from '@renderer/config/env'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { defaultLanguage } from '@shared/config/constant'
|
||||
import type { SelectionActionItem } from '@shared/data/types'
|
||||
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Avatar } from 'antd'
|
||||
import { ClipboardCheck, ClipboardCopy, ClipboardX, MessageSquareHeart } from 'lucide-react'
|
||||
@ -99,7 +98,8 @@ const ActionIcons: FC<{
|
||||
* demo is used in the settings page
|
||||
*/
|
||||
const SelectionToolbar: FC<{ demo?: boolean }> = ({ demo = false }) => {
|
||||
const { language, customCss } = useSettings()
|
||||
const [language] = usePreference('app.language')
|
||||
const [customCss] = usePreference('ui.custom_css')
|
||||
const [isCompact] = usePreference('feature.selection.compact')
|
||||
const [actionItems] = usePreference('feature.selection.action_items')
|
||||
const [animateKey, setAnimateKey] = useState(0)
|
||||
|
||||
@ -1,30 +1,28 @@
|
||||
import '@ant-design/v5-patch-for-react-19'
|
||||
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import { loggerService } from '@logger'
|
||||
import { ThemeProvider } from '@renderer/context/ThemeProvider'
|
||||
import storeSyncService from '@renderer/services/StoreSyncService'
|
||||
import store, { persistor } from '@renderer/store'
|
||||
import { FC } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Provider } from 'react-redux'
|
||||
import { PersistGate } from 'redux-persist/integration/react'
|
||||
|
||||
import SelectionToolbar from './SelectionToolbar'
|
||||
|
||||
loggerService.initWindowSource('SelectionToolbar')
|
||||
|
||||
//subscribe to store sync
|
||||
storeSyncService.subscribe()
|
||||
await preferenceService.preload([
|
||||
'app.language',
|
||||
'ui.custom_css',
|
||||
'app.theme.mode',
|
||||
'app.theme.user.color_primary',
|
||||
'feature.selection.compact',
|
||||
'feature.selection.action_items'
|
||||
])
|
||||
|
||||
const App: FC = () => {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<ThemeProvider>
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
<SelectionToolbar />
|
||||
</PersistGate>
|
||||
</ThemeProvider>
|
||||
</Provider>
|
||||
<ThemeProvider>
|
||||
<SelectionToolbar />
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
26
yarn.lock
26
yarn.lock
@ -12682,18 +12682,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dts-resolver@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "dts-resolver@npm:2.1.1"
|
||||
peerDependencies:
|
||||
oxc-resolver: ">=11.0.0"
|
||||
peerDependenciesMeta:
|
||||
oxc-resolver:
|
||||
optional: true
|
||||
checksum: 10c0/bc36d71822d39f23cfe274b6781fae4b1729bd8b0a07e4a011fe243a73c5dbbb30ea067fb0d6248fdfedc29cf4dfc0ff19f0dd38950158444409d109c1c55b7e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"drizzle-kit@npm:^0.31.4":
|
||||
version: 0.31.4
|
||||
resolution: "drizzle-kit@npm:0.31.4"
|
||||
@ -12803,6 +12791,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dts-resolver@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "dts-resolver@npm:2.1.1"
|
||||
peerDependencies:
|
||||
oxc-resolver: ">=11.0.0"
|
||||
peerDependenciesMeta:
|
||||
oxc-resolver:
|
||||
optional: true
|
||||
checksum: 10c0/bc36d71822d39f23cfe274b6781fae4b1729bd8b0a07e4a011fe243a73c5dbbb30ea067fb0d6248fdfedc29cf4dfc0ff19f0dd38950158444409d109c1c55b7e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"duck@npm:^0.1.12":
|
||||
version: 0.1.12
|
||||
resolution: "duck@npm:0.1.12"
|
||||
@ -14732,7 +14732,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.7.5":
|
||||
"get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.7.0, get-tsconfig@npm:^4.7.5":
|
||||
version: 4.10.1
|
||||
resolution: "get-tsconfig@npm:4.10.1"
|
||||
dependencies:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user