refactor: update preference handling and remove unused settings

- Commented out the App_SetDisableHardwareAcceleration IPC channel and related code for hardware acceleration settings.
- Updated preferences to utilize the new WindowStyle type for window style settings.
- Refactored components to use the usePreference hook instead of useSettings for better preference management.
- Cleaned up unused code and comments related to hardware acceleration and window style for improved maintainability.
This commit is contained in:
fullex 2025-09-02 11:45:33 +08:00
parent 7b2570974e
commit 2ce4fabc7d
23 changed files with 107 additions and 82 deletions

View File

@ -42,7 +42,7 @@ export enum IpcChannel {
App_MacRequestProcessTrust = 'app:mac-request-process-trust',
App_QuoteToMain = 'app:quote-to-main',
App_SetDisableHardwareAcceleration = 'app:set-disable-hardware-acceleration',
// App_SetDisableHardwareAcceleration = 'app:set-disable-hardware-acceleration',
Notification_Send = 'notification:send',
Notification_OnClick = 'notification:on-click',

View File

@ -36,3 +36,5 @@ export enum ThemeMode {
/** 有限的UI语言 */
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'el-GR' | 'en-US' | 'es-ES' | 'fr-FR' | 'ja-JP' | 'pt-PT' | 'ru-RU'
export type WindowStyle = 'transparent' | 'opaque'

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preferences configuration
* Generated at: 2025-09-01T16:31:20.203Z
* Generated at: 2025-09-02T02:45:09.198Z
*
* This file is automatically generated from classification.json
* To update this file, modify classification.json and run:
@ -10,7 +10,12 @@
*/
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
import type { SelectionActionItem, SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preferenceTypes'
import type {
SelectionActionItem,
SelectionFilterMode,
SelectionTriggerMode,
WindowStyle
} from '@shared/data/preferenceTypes'
import { LanguageVarious, ThemeMode } from '@shared/data/preferenceTypes'
/* eslint @typescript-eslint/member-ordering: ["error", {
@ -57,7 +62,7 @@ export interface PreferencesType {
// redux/settings/userTheme.colorPrimary
'app.theme.user.color_primary': string
// redux/settings/windowStyle
'app.theme.window_style': string
'app.theme.window_style': WindowStyle
// redux/settings/tray
'app.tray.enabled': boolean
// redux/settings/trayOnClose
@ -74,9 +79,11 @@ export interface PreferencesType {
'chat.code.collapsible': boolean
// redux/settings/codeEditor.autocompletion
'chat.code.editor.autocompletion': boolean
// redux/settings/codeEditor.enabled
'chat.code.editor.enabled': boolean
// redux/settings/codeEditor.foldGutter
'chat.code.editor.fold_gutter': boolean
// redux/settings/codeEditor.enabled
// redux/settings/codeEditor.highlightActiveLine
'chat.code.editor.highlight_active_line': boolean
// redux/settings/codeEditor.keymap
'chat.code.editor.keymap': boolean
@ -397,6 +404,7 @@ export const DefaultPreferences: PreferencesType = {
'app.zoom_factor': 1,
'chat.code.collapsible': false,
'chat.code.editor.autocompletion': true,
'chat.code.editor.enabled': false,
'chat.code.editor.fold_gutter': false,
'chat.code.editor.highlight_active_line': false,
'chat.code.editor.keymap': false,
@ -596,8 +604,8 @@ export const DefaultPreferences: PreferencesType = {
/**
* :
* - 总配置项: 172
* - 总配置项: 173
* - electronStore项: 1
* - redux项: 171
* - redux项: 172
* - localStorage项: 0
*/

View File

@ -356,7 +356,7 @@ export class PreferenceService {
const windowKeys = this.subscriptions.get(windowId)!
keys.forEach((key) => windowKeys.add(key))
logger.debug(`Window ${windowId} subscribed to ${keys.length} preference keys`)
logger.verbose(`Window ${windowId} subscribed to ${keys.length} preference keys: ${keys.join(', ')}`)
}
/**
@ -364,7 +364,9 @@ export class PreferenceService {
*/
public unsubscribeForWindow(windowId: number): void {
this.subscriptions.delete(windowId)
logger.debug(`Window ${windowId} unsubscribed from preference changes`)
logger.verbose(
`Window ${windowId} unsubscribed from preference changes: ${Array.from(this.subscriptions.keys()).join(', ')}`
)
}
/**

View File

@ -36,6 +36,8 @@ const logger = loggerService.withContext('MainEntry')
/**
* Disable hardware acceleration if setting is enabled
*/
//FIXME should not use configManager, use usePreference instead
//TODO 我们需要调整配置管理的加载位置,以保证其在 preferenceService 初始化之前被调用
const disableHardwareAcceleration = configManager.getDisableHardwareAcceleration()
if (disableHardwareAcceleration) {
app.disableHardwareAcceleration()

View File

@ -716,9 +716,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle(IpcChannel.App_QuoteToMain, (_, text: string) => windowService.quoteToMainWindow(text))
ipcMain.handle(IpcChannel.App_SetDisableHardwareAcceleration, (_, isDisable: boolean) => {
configManager.setDisableHardwareAcceleration(isDisable)
})
// ipcMain.handle(IpcChannel.App_SetDisableHardwareAcceleration, (_, isDisable: boolean) => {
// configManager.setDisableHardwareAcceleration(isDisable)
// })
ipcMain.handle(IpcChannel.TRACE_SAVE_DATA, (_, topicId: string) => saveSpans(topicId))
ipcMain.handle(IpcChannel.TRACE_GET_DATA, (_, topicId: string, traceId: string, modelName?: string) =>
getSpans(topicId, traceId, modelName)

View File

@ -222,9 +222,9 @@ export class ConfigManager {
return this.get<boolean>(ConfigKeys.DisableHardwareAcceleration, false)
}
setDisableHardwareAcceleration(value: boolean) {
this.set(ConfigKeys.DisableHardwareAcceleration, value)
}
// setDisableHardwareAcceleration(value: boolean) {
// this.set(ConfigKeys.DisableHardwareAcceleration, value)
// }
setAndNotify(key: string, value: unknown) {
this.set(key, value, true)

View File

@ -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)

View File

@ -47,7 +47,7 @@ const api = {
ipcRenderer.invoke(IpcChannel.App_Proxy, proxy, bypassRules),
checkForUpdate: () => ipcRenderer.invoke(IpcChannel.App_CheckForUpdate),
showUpdateDialog: () => ipcRenderer.invoke(IpcChannel.App_ShowUpdateDialog),
setLanguage: (lang: string) => ipcRenderer.invoke(IpcChannel.App_SetLanguage, lang),
// setLanguage: (lang: string) => ipcRenderer.invoke(IpcChannel.App_SetLanguage, lang),
setEnableSpellCheck: (isEnable: boolean) => ipcRenderer.invoke(IpcChannel.App_SetEnableSpellCheck, isEnable),
setSpellCheckLanguages: (languages: string[]) => ipcRenderer.invoke(IpcChannel.App_SetSpellCheckLanguages, languages),
setLaunchOnBoot: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetLaunchOnBoot, isActive),
@ -396,8 +396,8 @@ const api = {
pinActionWindow: (isPinned: boolean) => ipcRenderer.invoke(IpcChannel.Selection_ActionWindowPin, isPinned)
},
quoteToMainWindow: (text: string) => ipcRenderer.invoke(IpcChannel.App_QuoteToMain, text),
setDisableHardwareAcceleration: (isDisable: boolean) =>
ipcRenderer.invoke(IpcChannel.App_SetDisableHardwareAcceleration, isDisable),
// setDisableHardwareAcceleration: (isDisable: boolean) =>
// ipcRenderer.invoke(IpcChannel.App_SetDisableHardwareAcceleration, isDisable),
trace: {
saveData: (topicId: string) => ipcRenderer.invoke(IpcChannel.TRACE_SAVE_DATA, topicId),
getData: (topicId: string, traceId: string, modelName?: string) =>

View File

@ -1,4 +1,5 @@
import { useSettings } from '@renderer/hooks/useSettings'
import { usePreference } from '@data/hooks/usePreference'
import { defaultLanguage } from '@shared/config/constant'
import { LanguageVarious } from '@shared/data/preferenceTypes'
import { ConfigProvider, theme } from 'antd'
import elGR from 'antd/locale/el_GR'
@ -15,15 +16,13 @@ import { FC, PropsWithChildren } from 'react'
import { useTheme } from './ThemeProvider'
const AntdProvider: FC<PropsWithChildren> = ({ children }) => {
const {
language,
userTheme: { colorPrimary }
} = useSettings()
const [language] = usePreference('app.language')
const [colorPrimary] = usePreference('app.theme.user.color_primary')
const { theme: _theme } = useTheme()
return (
<ConfigProvider
locale={getAntdLocale(language)}
locale={getAntdLocale((language || navigator.language || defaultLanguage) as LanguageVarious)}
theme={{
cssVar: true,
hashed: false,

View File

@ -1,6 +1,6 @@
import { usePreference } from '@data/hooks/usePreference'
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 { getHighlighter, getMarkdownIt, getShiki, loadLanguageIfNeeded, loadThemeIfNeeded } from '@renderer/utils/shiki'
import { ThemeMode } from '@shared/data/preferenceTypes'
@ -8,7 +8,6 @@ import * as cmThemes from '@uiw/codemirror-themes-all'
import type React from 'react'
import { createContext, type PropsWithChildren, use, useCallback, useEffect, useMemo, useState } from 'react'
import type { BundledThemeInfo } from 'shiki/types'
interface CodeStyleContextType {
highlightCodeChunk: (trunk: string, language: string, callerId: string) => Promise<HighlightChunkResult>
highlightStreamingCode: (code: string, language: string, callerId: string) => Promise<HighlightChunkResult>
@ -38,24 +37,29 @@ const defaultCodeStyleContext: CodeStyleContextType = {
const CodeStyleContext = createContext<CodeStyleContextType>(defaultCodeStyleContext)
export const CodeStyleProvider: React.FC<PropsWithChildren> = ({ children }) => {
const { codeEditor, codeViewer } = useSettings()
const [codeEditorEnabled] = usePreference('chat.code.editor.enabled')
const [codeEditorThemeLight] = usePreference('chat.code.editor.theme_light')
const [codeEditorThemeDark] = usePreference('chat.code.editor.theme_dark')
const [codeViewerThemeLight] = usePreference('chat.code.viewer.theme_light')
const [codeViewerThemeDark] = usePreference('chat.code.viewer.theme_dark')
const { theme } = useTheme()
const [shikiThemesInfo, setShikiThemesInfo] = useState<BundledThemeInfo[]>([])
useMermaid()
useEffect(() => {
if (!codeEditor.enabled) {
if (!codeEditorEnabled) {
getShiki().then(({ bundledThemesInfo }) => {
setShikiThemesInfo(bundledThemesInfo)
})
}
}, [codeEditor.enabled])
}, [codeEditorEnabled])
// 获取支持的主题名称列表
const themeNames = useMemo(() => {
// CodeMirror 主题
// 更保险的做法可能是硬编码主题列表
if (codeEditor.enabled) {
if (codeEditorEnabled) {
return ['auto', 'light', 'dark']
.concat(Object.keys(cmThemes))
.filter((item) => typeof cmThemes[item as keyof typeof cmThemes] !== 'function')
@ -64,17 +68,17 @@ export const CodeStyleProvider: React.FC<PropsWithChildren> = ({ children }) =>
// Shiki 主题,取出所有 BundledThemeInfo 的 id 作为主题名
return ['auto', ...shikiThemesInfo.map((info) => info.id)]
}, [codeEditor.enabled, shikiThemesInfo])
}, [codeEditorEnabled, shikiThemesInfo])
// 获取当前使用的 Shiki 主题名称(只用于代码预览)
const activeShikiTheme = useMemo(() => {
const field = theme === ThemeMode.light ? 'themeLight' : 'themeDark'
const codeStyle = codeViewer[field]
const codeStyle = theme === ThemeMode.light ? codeViewerThemeLight : codeViewerThemeDark
if (!codeStyle || codeStyle === 'auto' || !themeNames.includes(codeStyle)) {
return theme === ThemeMode.light ? 'one-light' : 'material-theme-darker'
}
return codeStyle
}, [theme, codeViewer, themeNames])
}, [theme, codeViewerThemeLight, codeViewerThemeDark, themeNames])
const isShikiThemeDark = useMemo(() => {
const themeInfo = shikiThemesInfo.find((info) => info.id === activeShikiTheme)
@ -83,13 +87,13 @@ export const CodeStyleProvider: React.FC<PropsWithChildren> = ({ children }) =>
// 获取当前使用的 CodeMirror 主题对象(只用于编辑器)
const activeCmTheme = useMemo(() => {
const field = theme === ThemeMode.light ? 'themeLight' : 'themeDark'
let themeName = codeEditor[field]
const codeStyle = theme === ThemeMode.light ? codeEditorThemeLight : codeEditorThemeDark
let themeName = codeStyle
if (!themeName || themeName === 'auto' || !themeNames.includes(themeName)) {
themeName = theme === ThemeMode.light ? 'materialLight' : 'dark'
}
return cmThemes[themeName as keyof typeof cmThemes] || themeName
}, [theme, codeEditor, themeNames])
}, [theme, codeEditorThemeLight, codeEditorThemeDark, themeNames])
// 自定义 shiki 语言别名
const languageAliases = useMemo(() => {

View File

@ -357,7 +357,7 @@ export class PreferenceService {
try {
await window.api.preference.subscribe(keysToSubscribe)
keysToSubscribe.forEach((key) => this.subscribedKeys.add(key))
logger.debug(`Subscribed to preference keys: ${keysToSubscribe.join(', ')}`)
logger.verbose(`Subscribed to preference keys: ${keysToSubscribe.join(', ')}`)
} catch (error) {
logger.error(`Failed to subscribe to preference keys ${keysToSubscribe.join(', ')}:`, error as Error)
}

View File

@ -1,3 +1,4 @@
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { isMac } from '@renderer/config/constant'
import { isLocalAi } from '@renderer/config/env'
@ -22,7 +23,6 @@ import useFullScreenNotice from './useFullScreenNotice'
import { useRuntime } from './useRuntime'
import { useSettings } from './useSettings'
import useUpdateHandler from './useUpdateHandler'
const logger = loggerService.withContext('useAppInit')
export function useAppInit() {
@ -31,12 +31,15 @@ export function useAppInit() {
proxyUrl,
proxyBypassRules,
language,
windowStyle,
// windowStyle,
autoCheckUpdate,
proxyMode,
customCss,
// customCss,
enableDataCollection
} = useSettings()
const [windowStyle] = usePreference('app.theme.window_style')
const [customCss] = usePreference('ui.custom_css')
const { minappShow } = useRuntime()
const { setDefaultModel, setQuickModel, setTranslateModel } = useDefaultModel()
const avatar = useLiveQuery(() => db.settings.get('image://avatar'))

View File

@ -1,9 +1,8 @@
import { usePreference } from '@data/hooks/usePreference'
import { isMac } from '@renderer/config/constant'
import { useSettings } from './useSettings'
function useNavBackgroundColor() {
const { windowStyle } = useSettings()
const [windowStyle] = usePreference('app.theme.window_style')
const macTransparentWindow = isMac && windowStyle === 'transparent'

View File

@ -4,7 +4,7 @@ import {
SendMessageShortcut,
setAssistantIconType,
setAutoCheckUpdate as _setAutoCheckUpdate,
setDisableHardwareAcceleration,
// setDisableHardwareAcceleration,
setEnableDeveloperMode,
setLaunchOnBoot,
setLaunchToTray,
@ -18,8 +18,8 @@ import {
SettingsState,
setTopicPosition,
setTray as _setTray,
setTrayOnClose,
setWindowStyle
setTrayOnClose
// setWindowStyle
} from '@renderer/store/settings'
import { SidebarIcon, TranslateLanguageCode } from '@renderer/types'
import { UpgradeChannel } from '@shared/config/constant'
@ -75,9 +75,9 @@ export function useSettings() {
// setTheme(theme: ThemeMode) {
// dispatch(setTheme(theme))
// },
setWindowStyle(windowStyle: 'transparent' | 'opaque') {
dispatch(setWindowStyle(windowStyle))
},
// setWindowStyle(windowStyle: 'transparent' | 'opaque') {
// dispatch(setWindowStyle(windowStyle))
// },
setTargetLanguage(targetLanguage: TranslateLanguageCode) {
dispatch(setTargetLanguage(targetLanguage))
},
@ -101,11 +101,11 @@ export function useSettings() {
},
setShowTokens(showTokens: boolean) {
dispatch(setShowTokens(showTokens))
},
setDisableHardwareAcceleration(disableHardwareAcceleration: boolean) {
dispatch(setDisableHardwareAcceleration(disableHardwareAcceleration))
window.api.setDisableHardwareAcceleration(disableHardwareAcceleration)
}
// setDisableHardwareAcceleration(disableHardwareAcceleration: boolean) {
// dispatch(setDisableHardwareAcceleration(disableHardwareAcceleration))
// window.api.setDisableHardwareAcceleration(disableHardwareAcceleration)
// }
}
}

View File

@ -1,3 +1,4 @@
import { usePreference } from '@data/hooks/usePreference'
import CodeEditor from '@renderer/components/CodeEditor'
import { ResetIcon } from '@renderer/components/Icons'
import { HStack } from '@renderer/components/Layout'
@ -13,7 +14,6 @@ import {
AssistantIconType,
setAssistantIconType,
setClickAssistantToShowTopic,
setCustomCss,
setPinTopicsToTop,
setShowTopicTime,
setSidebarIcons
@ -57,24 +57,26 @@ const ColorCircle = styled.div<{ color: string; isActive?: boolean }>`
const DisplaySettings: FC = () => {
const {
windowStyle,
setWindowStyle,
// windowStyle,
// setWindowStyle,
topicPosition,
setTopicPosition,
clickAssistantToShowTopic,
showTopicTime,
pinTopicsToTop,
customCss,
// customCss,
sidebarIcons,
assistantIconType
} = useSettings()
const [windowStyle, setWindowStyle] = usePreference('app.theme.window_style')
const [customCss, setCustomCss] = usePreference('ui.custom_css')
const { navbarPosition, setNavbarPosition } = useNavbarPosition()
const { theme, settedTheme, setTheme } = useTheme()
const { t } = useTranslation()
const dispatch = useAppDispatch()
const [currentZoom, setCurrentZoom] = useState(1.0)
const { userTheme, setUserTheme } = useUserTheme()
const [visibleIcons, setVisibleIcons] = useState(sidebarIcons?.visible || DEFAULT_SIDEBAR_ICONS)
const [disabledIcons, setDisabledIcons] = useState(sidebarIcons?.disabled || [])
@ -335,7 +337,7 @@ const DisplaySettings: FC = () => {
value={customCss}
language="css"
placeholder={t('settings.display.custom.css.placeholder')}
onChange={(value) => dispatch(setCustomCss(value))}
onChange={(value) => setCustomCss(value)}
height="60vh"
expanded={false}
wrapped

View File

@ -40,9 +40,7 @@ const GeneralSettings: FC = () => {
tray,
proxyMode: storeProxyMode,
enableDataCollection,
enableSpellCheck,
disableHardwareAcceleration,
setDisableHardwareAcceleration
enableSpellCheck
} = useSettings()
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
const [proxyBypassRules, setProxyBypassRules] = useState<string | undefined>(storeProxyBypassRules)
@ -51,6 +49,9 @@ const GeneralSettings: FC = () => {
const { setTimeoutTimer } = useTimer()
const [language, setLanguage] = usePreference('app.language')
const [disableHardwareAcceleration, setDisableHardwareAcceleration] = usePreference(
'app.disable_hardware_acceleration'
)
const updateTray = (isShowTray: boolean) => {
setTray(isShowTray)

View File

@ -9,7 +9,6 @@ import {
SYSTEM_MODELS
} from '@renderer/config/models'
import { BUILTIN_OCR_PROVIDERS, BUILTIN_OCR_PROVIDERS_MAP, DEFAULT_OCR_PROVIDER } from '@renderer/config/ocr'
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
import {
isSupportArrayContentProvider,
isSupportDeveloperRoleProvider,
@ -33,6 +32,7 @@ import {
} from '@renderer/types'
import { getDefaultGroupName, getLeadingEmoji, runAsyncFunction, uuid } from '@renderer/utils'
import { defaultByPassRules, UpgradeChannel } from '@shared/config/constant'
import { TRANSLATE_PROMPT } from '@shared/config/prompts'
import { isEmpty } from 'lodash'
import { createMigrate } from 'redux-persist'

View File

@ -776,9 +776,9 @@ const settingsSlice = createSlice({
setEnableQuickPanelTriggers: (state, action: PayloadAction<boolean>) => {
state.enableQuickPanelTriggers = action.payload
},
setDisableHardwareAcceleration: (state, action: PayloadAction<boolean>) => {
state.disableHardwareAcceleration = action.payload
},
// setDisableHardwareAcceleration: (state, action: PayloadAction<boolean>) => {
// state.disableHardwareAcceleration = action.payload
// },
setOpenAISummaryText: (state, action: PayloadAction<OpenAISummaryText>) => {
state.openAI.summaryText = action.payload
},
@ -956,7 +956,7 @@ export const {
setSpellCheckLanguages,
setExportMenuOptions,
setEnableQuickPanelTriggers,
setDisableHardwareAcceleration,
// setDisableHardwareAcceleration,
setOpenAISummaryText,
setOpenAIVerbosity,
setNotificationSettings,

View File

@ -1,6 +1,6 @@
import '@renderer/databases'
import { useSettings } from '@renderer/hooks/useSettings'
import { usePreference } from '@data/hooks/usePreference'
import store, { persistor } from '@renderer/store'
import { message } from 'antd'
import { useEffect } from 'react'
@ -14,7 +14,7 @@ import HomeWindow from './home/HomeWindow'
// Inner component that uses the hook after Redux is initialized
function MiniWindowContent(): React.ReactElement {
const { customCss } = useSettings()
const [customCss] = usePreference('ui.custom_css')
useEffect(() => {
let customCssElement = document.getElementById('user-defined-custom-css') as HTMLStyleElement

View File

@ -1,4 +1,4 @@
import { useSettings } from '@renderer/hooks/useSettings'
import { usePreference } from '@data/hooks/usePreference'
// import MessageContent from './MessageContent'
import MessageContent from '@renderer/pages/home/Messages/MessageContent'
import MessageErrorBoundary from '@renderer/pages/home/Messages/MessageErrorBoundary'
@ -22,7 +22,8 @@ const MessageItem: FC<Props> = ({ message, index, total, route }) => {
// const [message, setMessage] = useState(_message)
// const [bl, setTextBlock] = useState<MainTextMessageBlock | null>(null)
// const model = useModel(getMessageModelId(message))
const { messageFont, fontSize } = useSettings()
const [messageFont] = usePreference('chat.message.font')
const [fontSize] = usePreference('chat.message.font_size')
const messageContainerRef = useRef<HTMLDivElement>(null)
const isAssistantMessage = message.role === 'assistant'

View File

@ -1,8 +1,8 @@
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { isMac } from '@renderer/config/constant'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useSettings } from '@renderer/hooks/useSettings'
import i18n from '@renderer/i18n'
import { fetchChatCompletion } from '@renderer/services/ApiService'
import { getDefaultTopic } from '@renderer/services/AssistantService'
@ -38,7 +38,9 @@ import InputBar from './components/InputBar'
const logger = loggerService.withContext('HomeWindow')
const HomeWindow: FC<{ draggable?: boolean }> = ({ draggable = true }) => {
const { language, readClipboardAtStartup, windowStyle } = useSettings()
const [readClipboardAtStartup] = usePreference('feature.quick_assistant.read_clipboard_at_startup')
const [language] = usePreference('app.language')
const [windowStyle] = usePreference('app.theme.window_style')
const { theme } = useTheme()
const { t } = useTranslation()

View File

@ -6,7 +6,6 @@ import LanguageSelect from '@renderer/components/LanguageSelect'
import { LanguagesEnum, UNKNOWN } from '@renderer/config/translate'
import db from '@renderer/databases'
import { useTopicMessages } from '@renderer/hooks/useMessageOperations'
import { useSettings } from '@renderer/hooks/useSettings'
import useTranslate from '@renderer/hooks/useTranslate'
import MessageContent from '@renderer/pages/home/Messages/MessageContent'
import { getDefaultTopic, getDefaultTranslateAssistant } from '@renderer/services/AssistantService'
@ -14,6 +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 { defaultLanguage } from '@shared/config/constant'
import type { SelectionActionItem } from '@shared/data/preferenceTypes'
import { Tooltip } from 'antd'
import { ArrowRightFromLine, ArrowRightToLine, ChevronDown, CircleHelp, Globe } from 'lucide-react'
@ -32,8 +32,8 @@ const logger = loggerService.withContext('ActionTranslate')
const ActionTranslate: FC<Props> = ({ action, scrollToBottom }) => {
const { t } = useTranslation()
const { language } = useSettings()
const [language] = usePreference('app.language')
const [translateModelPrompt] = usePreference('feature.translate.model_prompt')
const [targetLanguage, setTargetLanguage] = useState<TranslateLanguage>(LanguagesEnum.enUS)
@ -60,7 +60,7 @@ const ActionTranslate: FC<Props> = ({ action, scrollToBottom }) => {
let alterLang: TranslateLanguage
if (!biDirectionLangPair || !biDirectionLangPair.value[0]) {
const lang = getLanguageByLangcode(language)
const lang = getLanguageByLangcode(language || navigator.language || defaultLanguage)
if (lang !== UNKNOWN) {
targetLang = lang
} else {