refactor: Theme improve (#6619)

* refactor(IpcChannel): rename theme change event and streamline theme handling

- Updated the IpcChannel enum to rename 'theme:change' to 'theme:updated' for clarity.
- Refactored theme handling in ipc.ts to utilize a new ThemeService, simplifying theme updates and event broadcasting.
- Adjusted various components to consistently use the updated theme variable naming convention.

* refactor(Theme): standardize theme handling across components

- Updated theme retrieval to use 'actualTheme' instead of 'theme' for consistency.
- Changed default theme setting from 'auto' to 'system' in ConfigManager and related components.
- Adjusted theme handling in various components to reflect the new naming convention and ensure proper theme application.

* fix(Theme): improve theme handling and migration logic

- Added a console log for debugging theme transitions in ThemeProvider.
- Updated ThemeService to ensure theme is set correctly when changed.
- Incremented version number in store configuration to reflect changes.
- Enhanced migration logic to convert 'auto' theme setting to 'system' for better consistency.

* feat(Theme): add getTheme IPC channel and improve theme management

- Introduced a new IPC channel 'App_GetTheme' to retrieve the current theme.
- Updated ThemeService to include a method for getting the current theme.
- Refactored theme initialization in WindowService to ensure proper theme setup.
- Enhanced theme handling in various components to utilize the new theme retrieval method.

* fix(ThemeService): improve theme initialization and retrieval logic

- Set default theme to 'system' and updated theme initialization to handle legacy versions.
- Enhanced getTheme method to return both the current theme and the actual theme based on nativeTheme settings.
- Removed redundant initTheme method from ThemeService and ensured themeService is imported in WindowService for proper initialization.
- Updated ThemeProvider to handle the new structure of the theme retrieval response.

* refactor(Settings): remove theme management from settings

- Eliminated theme-related state and actions from the settings slice.
- Updated useSettings hook to remove theme handling functionality.
- Cleaned up imports by removing unused ThemeMode type.

* refactor(Theme): update theme retrieval in GeneralSettings and HomeWindow

- Restored theme retrieval in GeneralSettings and HomeWindow components.
- Adjusted imports to ensure proper theme management.
- Updated theme condition checks to utilize the ThemeMode enumeration for consistency.

* refactor(Theme): update theme terminology and retrieval in Sidebar and DisplaySettings

- Changed theme label from 'auto' to 'system' in multiple localization files for consistency.
- Updated Sidebar component to reflect the new theme terminology.
- Adjusted DisplaySettings to display the updated theme label.

* refactor(ThemeProvider): initialize theme state from API response

* refactor(ThemeProvider): reset theme state to default values and streamline initialization logic

* refactor(Theme): enhance theme management by incorporating 'system' mode and updating state handling

- Updated ThemeService to include 'system' as a valid theme option.
- Refactored ThemeProvider to utilize useSettings for theme state management and ensure proper initialization.
- Adjusted useSettings to include theme setting functionality.
- Modified settings slice to manage theme state effectively.

* refactor(WindowService, ThemeProvider, Messages, HomeWindow): streamline imports and clean up unused variables

- Removed duplicate import of ThemeService in WindowService.
- Adjusted import order in ThemeProvider for clarity.
- Simplified useSettings destructuring in Messages component.
- Cleaned up unused ThemeMode import in HomeWindow.

* refactor(Theme): standardize theme usage across components by replacing 'actualTheme' with 'theme'

- Updated components to consistently use 'theme' instead of 'actualTheme' for better clarity and maintainability.
- Adjusted ThemeProvider to reflect changes in theme state management.
- Ensured all relevant components are aligned with the new theme structure.

* refactor(Theme): remove unused theme retrieval functionality

- Eliminated the App_GetTheme channel and associated methods from ThemeService and IPC handling.
- Updated components to use the new theme structure, replacing 'actualTheme' with 'settedTheme' for consistency.
- Ensured all theme-related functionalities are streamlined and aligned with the latest changes.

* refactor(Theme): update theme variable usage in ChatFlowHistory and GeneralSettings

- Replaced 'theme' with 'settedTheme' in ChatFlowHistory for consistency with recent theme structure changes.
- Simplified theme destructuring in GeneralSettings by removing unused 'themeMode' variable.
- Ensured alignment with the latest theme management updates across components.

* refactor(Theme): update theme variable in GeneralSettings component

- Replaced 'themeMode' with 'theme' in GeneralSettings for consistency with recent theme structure changes.
- Ensured alignment with the latest theme management updates across components.

---------

Co-authored-by: beyondkmp <beyondkmkp@gmail.com>
This commit is contained in:
beyondkmp 2025-05-30 15:10:58 +08:00 committed by GitHub
parent 0df331cf8a
commit 9f49ce6dc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 125 additions and 115 deletions

View File

@ -144,7 +144,7 @@ export enum IpcChannel {
// events
BackupProgress = 'backup-progress',
ThemeChange = 'theme:change',
ThemeUpdated = 'theme:updated',
UpdateDownloadedCancelled = 'update-downloaded-cancelled',
RestoreProgress = 'restore-progress',
UpdateError = 'update-error',

View File

@ -6,11 +6,10 @@ import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/pro
import { handleZoomFactor } from '@main/utils/zoom'
import { IpcChannel } from '@shared/IpcChannel'
import { Shortcut, ThemeMode } from '@types'
import { BrowserWindow, ipcMain, nativeTheme, session, shell } from 'electron'
import { BrowserWindow, ipcMain, session, shell } from 'electron'
import log from 'electron-log'
import { Notification } from 'src/renderer/src/types/notification'
import { titleBarOverlayDark, titleBarOverlayLight } from './config'
import AppUpdater from './services/AppUpdater'
import BackupManager from './services/BackupManager'
import { configManager } from './services/ConfigManager'
@ -28,6 +27,7 @@ import { searchService } from './services/SearchService'
import { SelectionService } from './services/SelectionService'
import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService'
import storeSyncService from './services/StoreSyncService'
import { themeService } from './services/ThemeService'
import { setOpenLinkExternal } from './services/WebviewService'
import { windowService } from './services/WindowService'
import { calculateDirectorySize, getResourcePath } from './utils'
@ -122,34 +122,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
// theme
ipcMain.handle(IpcChannel.App_SetTheme, (_, theme: ThemeMode) => {
const updateTitleBarOverlay = () => {
if (!mainWindow?.setTitleBarOverlay) return
const isDark = nativeTheme.shouldUseDarkColors
mainWindow.setTitleBarOverlay(isDark ? titleBarOverlayDark : titleBarOverlayLight)
}
const broadcastThemeChange = () => {
const isDark = nativeTheme.shouldUseDarkColors
const effectiveTheme = isDark ? ThemeMode.dark : ThemeMode.light
BrowserWindow.getAllWindows().forEach((win) => win.webContents.send(IpcChannel.ThemeChange, effectiveTheme))
}
const notifyThemeChange = () => {
updateTitleBarOverlay()
broadcastThemeChange()
}
if (theme === ThemeMode.auto) {
nativeTheme.themeSource = 'system'
nativeTheme.on('updated', notifyThemeChange)
} else {
nativeTheme.themeSource = theme
nativeTheme.off('updated', notifyThemeChange)
}
updateTitleBarOverlay()
configManager.setTheme(theme)
notifyThemeChange()
themeService.setTheme(theme)
})
ipcMain.handle(IpcChannel.App_HandleZoomFactor, (_, delta: number, reset: boolean = false) => {

View File

@ -43,7 +43,7 @@ export class ConfigManager {
}
getTheme(): ThemeMode {
return this.get(ConfigKeys.Theme, ThemeMode.auto)
return this.get(ConfigKeys.Theme, ThemeMode.system)
}
setTheme(theme: ThemeMode) {

View File

@ -0,0 +1,48 @@
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()
if (this.theme === ThemeMode.dark || this.theme === ThemeMode.light || this.theme === ThemeMode.system) {
nativeTheme.themeSource = this.theme
} else {
// 兼容旧版本
configManager.setTheme(ThemeMode.system)
nativeTheme.themeSource = ThemeMode.system
}
nativeTheme.on('updated', this.themeUpdatadHandler.bind(this))
}
themeUpdatadHandler() {
BrowserWindow.getAllWindows().forEach((win) => {
if (win && !win.isDestroyed() && win.setTitleBarOverlay) {
try {
win.setTitleBarOverlay(nativeTheme.shouldUseDarkColors ? titleBarOverlayDark : titleBarOverlayLight)
} catch (error) {
// don't throw error if setTitleBarOverlay failed
// Because it may be called with some windows have some title bar
}
}
win.webContents.send(IpcChannel.ThemeUpdated, 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()

View File

@ -1,8 +1,10 @@
// just import the themeService to ensure the theme is initialized
import './ThemeService'
import { is } from '@electron-toolkit/utils'
import { isDev, isLinux, isMac, isWin } from '@main/constant'
import { getFilesDir } from '@main/utils/file'
import { IpcChannel } from '@shared/IpcChannel'
import { ThemeMode } from '@types'
import { app, BrowserWindow, nativeTheme, shell } from 'electron'
import Logger from 'electron-log'
import windowStateKeeper from 'electron-window-state'
@ -45,13 +47,6 @@ export class WindowService {
maximize: false
})
const theme = configManager.getTheme()
if (theme === ThemeMode.auto) {
nativeTheme.themeSource = 'system'
} else {
nativeTheme.themeSource = theme
}
this.mainWindow = new BrowserWindow({
x: mainWindowState.x,
y: mainWindowState.y,

View File

@ -1,7 +1,7 @@
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
import { electronAPI } from '@electron-toolkit/preload'
import { IpcChannel } from '@shared/IpcChannel'
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types'
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, ThemeMode, WebDavConfig } from '@types'
import { contextBridge, ipcRenderer, OpenDialogOptions, shell, webUtils } from 'electron'
import { Notification } from 'src/renderer/src/types/notification'
import { CreateDirectoryOptions } from 'webdav'
@ -20,7 +20,7 @@ const api = {
setLaunchToTray: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetLaunchToTray, isActive),
setTray: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetTray, isActive),
setTrayOnClose: (isActive: boolean) => ipcRenderer.invoke(IpcChannel.App_SetTrayOnClose, isActive),
setTheme: (theme: 'light' | 'dark' | 'auto') => 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),

View File

@ -9,6 +9,7 @@ import { useMinapps } from '@renderer/hooks/useMinapps'
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import { ThemeMode } from '@renderer/types'
import { isEmoji } from '@renderer/utils'
import type { MenuProps } from 'antd'
import { Avatar, Dropdown, Tooltip } from 'antd'
@ -44,7 +45,7 @@ const Sidebar: FC = () => {
const { pathname } = useLocation()
const navigate = useNavigate()
const { theme, settingTheme, toggleTheme } = useTheme()
const { theme, settedTheme, toggleTheme } = useTheme()
const avatar = useAvatar()
const { t } = useTranslation()
@ -104,13 +105,13 @@ const Sidebar: FC = () => {
</Icon>
</Tooltip>
<Tooltip
title={t('settings.theme.title') + ': ' + t(`settings.theme.${settingTheme}`)}
title={t('settings.theme.title') + ': ' + t(`settings.theme.${settedTheme}`)}
mouseEnterDelay={0.8}
placement="right">
<Icon theme={theme} onClick={() => toggleTheme()}>
{settingTheme === 'dark' ? (
{settedTheme === ThemeMode.dark ? (
<Moon size={20} className="icon" />
) : settingTheme === 'light' ? (
) : settedTheme === ThemeMode.light ? (
<Sun size={20} className="icon" />
) : (
<SunMoon size={20} className="icon" />

View File

@ -7,13 +7,13 @@ import React, { createContext, PropsWithChildren, use, useEffect, useState } fro
interface ThemeContextType {
theme: ThemeMode
settingTheme: ThemeMode
settedTheme: ThemeMode
toggleTheme: () => void
}
const ThemeContext = createContext<ThemeContextType>({
theme: ThemeMode.auto,
settingTheme: ThemeMode.auto,
theme: ThemeMode.system,
settedTheme: ThemeMode.dark,
toggleTheme: () => {}
})
@ -21,53 +21,50 @@ interface ThemeProviderProps extends PropsWithChildren {
defaultTheme?: ThemeMode
}
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children, defaultTheme }) => {
const { theme, setTheme } = useSettings()
const [effectiveTheme, setEffectiveTheme] = useState(theme)
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
// 用户设置的主题
const { theme: settedTheme, setTheme: setSettedTheme } = useSettings()
const [actualTheme, setActualTheme] = useState<ThemeMode>(
window.matchMedia('(prefers-color-scheme: dark)').matches ? ThemeMode.dark : ThemeMode.light
)
const { initUserTheme } = useUserTheme()
const toggleTheme = () => {
// 主题顺序是light, dark, auto, 所以需要先判断当前主题,然后取下一个主题
switch (theme) {
case ThemeMode.light:
setTheme(ThemeMode.dark)
break
case ThemeMode.dark:
setTheme(ThemeMode.auto)
break
case ThemeMode.auto:
setTheme(ThemeMode.light)
break
}
const nextTheme = {
[ThemeMode.light]: ThemeMode.dark,
[ThemeMode.dark]: ThemeMode.system,
[ThemeMode.system]: ThemeMode.light
}[settedTheme]
setSettedTheme(nextTheme || ThemeMode.system)
}
useEffect(() => {
window.api?.setTheme(defaultTheme || theme)
}, [defaultTheme, theme])
useEffect(() => {
document.body.setAttribute('theme-mode', effectiveTheme)
}, [effectiveTheme])
useEffect(() => {
// Set initial theme and OS attributes on body
document.body.setAttribute('os', isMac ? 'mac' : 'windows')
const themeChangeListenerRemover = window.electron.ipcRenderer.on(
IpcChannel.ThemeChange,
(_, realTheam: ThemeMode) => {
setEffectiveTheme(realTheam)
}
)
return () => {
themeChangeListenerRemover()
}
})
document.body.setAttribute('theme-mode', actualTheme)
// if theme is old auto, then set theme to system
// we can delete this after next big release
if (settedTheme !== ThemeMode.dark && settedTheme !== ThemeMode.light && settedTheme !== ThemeMode.system) {
setSettedTheme(ThemeMode.system)
}
useEffect(() => {
initUserTheme()
// eslint-disable-next-line react-hooks/exhaustive-deps
// listen for theme updates from main process
const cleanup = window.electron.ipcRenderer.on(IpcChannel.ThemeUpdated, (_, actualTheme: ThemeMode) => {
document.body.setAttribute('theme-mode', actualTheme)
setActualTheme(actualTheme)
})
return cleanup
}, [])
return <ThemeContext value={{ theme: effectiveTheme, settingTheme: theme, toggleTheme }}>{children}</ThemeContext>
useEffect(() => {
window.api.setTheme(settedTheme)
}, [settedTheme])
return <ThemeContext value={{ theme: actualTheme, settedTheme, toggleTheme }}>{children}</ThemeContext>
}
export const useTheme = () => use(ThemeContext)

View File

@ -1692,7 +1692,7 @@
"zoom_out": "Zoom Out",
"zoom_reset": "Reset Zoom"
},
"theme.auto": "Auto",
"theme.system": "System",
"theme.dark": "Dark",
"theme.light": "Light",
"theme.title": "Theme",

View File

@ -1681,7 +1681,7 @@
"zoom_out": "ズームアウト",
"zoom_reset": "ズームをリセット"
},
"theme.auto": "自動",
"theme.system": "システム",
"theme.dark": "ダーク",
"theme.light": "ライト",
"theme.title": "テーマ",

View File

@ -1681,7 +1681,7 @@
"zoom_out": "Уменьшить",
"zoom_reset": "Сбросить масштаб"
},
"theme.auto": "Автоматически",
"theme.system": "Системная",
"theme.dark": "Темная",
"theme.light": "Светлая",
"theme.title": "Тема",

View File

@ -1691,7 +1691,7 @@
"zoom_out": "缩小界面",
"zoom_reset": "重置缩放"
},
"theme.auto": "自动",
"theme.system": "系统",
"theme.dark": "深色",
"theme.light": "浅色",
"theme.title": "主题",

View File

@ -1684,7 +1684,7 @@
"zoom_reset": "重設縮放",
"exit_fullscreen": "退出螢幕"
},
"theme.auto": "自動",
"theme.system": "系統",
"theme.dark": "深色",
"theme.light": "淺色",
"theme.title": "主題",

View File

@ -1478,7 +1478,7 @@
"zoom_out": "Σμικρύνση εμφάνισης",
"zoom_reset": "Επαναφορά εμφάνισης"
},
"theme.auto": "Αυτόματο",
"theme.system": "Σύστημα",
"theme.dark": "Σκοτεινό",
"theme.light": "Φωτεινό",
"theme.title": "Θέμα",

View File

@ -1477,7 +1477,7 @@
"zoom_out": "Reducir interfaz",
"zoom_reset": "Restablecer zoom"
},
"theme.auto": "Automático",
"theme.system": "Sistema",
"theme.dark": "Oscuro",
"theme.light": "Claro",
"theme.title": "Tema",

View File

@ -1478,7 +1478,7 @@
"zoom_out": "Réduire l'interface",
"zoom_reset": "Réinitialiser le zoom"
},
"theme.auto": "Automatique",
"theme.system": "Système",
"theme.dark": "Sombre",
"theme.light": "Clair",
"theme.title": "Thème",

View File

@ -1480,7 +1480,7 @@
"zoom_out": "Diminuir interface",
"zoom_reset": "Redefinir zoom"
},
"theme.auto": "Automático",
"theme.system": "Sistema",
"theme.dark": "Escuro",
"theme.light": "Claro",
"theme.title": "Tema",

View File

@ -199,7 +199,7 @@ const ChatFlowHistory: FC<ChatFlowHistoryProps> = ({ conversationId }) => {
const [edges, setEdges, onEdgesChange] = useEdgesState<any>([])
const [loading, setLoading] = useState(true)
const { userName } = useSettings()
const { theme } = useTheme()
const { settedTheme } = useTheme()
const topicId = conversationId
@ -491,7 +491,7 @@ const ChatFlowHistory: FC<ChatFlowHistoryProps> = ({ conversationId }) => {
}}
proOptions={{ hideAttribution: true }}
className="react-flow-container"
colorMode={theme === 'auto' ? 'system' : theme}>
colorMode={settedTheme}>
<Controls showInteractive={false} />
<MiniMap
nodeStrokeWidth={3}

View File

@ -54,8 +54,6 @@ const ColorCircle = styled.div<{ color: string; isActive?: boolean }>`
const DisplaySettings: FC = () => {
const {
setTheme,
theme,
windowStyle,
setWindowStyle,
topicPosition,
@ -65,10 +63,11 @@ const DisplaySettings: FC = () => {
pinTopicsToTop,
customCss,
sidebarIcons,
setTheme,
assistantIconType,
userTheme
} = useSettings()
const { theme: themeMode } = useTheme()
const { theme, settedTheme } = useTheme()
const { t } = useTranslation()
const dispatch = useAppDispatch()
const [currentZoom, setCurrentZoom] = useState(1.0)
@ -121,11 +120,11 @@ const DisplaySettings: FC = () => {
)
},
{
value: ThemeMode.auto,
value: ThemeMode.system,
label: (
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
<SyncOutlined />
<span>{t('settings.theme.auto')}</span>
<span>{t('settings.theme.system')}</span>
</div>
)
}
@ -168,13 +167,13 @@ const DisplaySettings: FC = () => {
)
return (
<SettingContainer theme={themeMode}>
<SettingContainer theme={theme}>
<SettingGroup theme={theme}>
<SettingTitle>{t('settings.display.title')}</SettingTitle>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.theme.title')}</SettingRowTitle>
<Segmented value={theme} shape="round" onChange={setTheme} options={themeOptions} />
<Segmented value={settedTheme} shape="round" onChange={setTheme} options={themeOptions} />
</SettingRow>
<SettingDivider />
<SettingRow>

View File

@ -19,7 +19,6 @@ const GeneralSettings: FC = () => {
const {
language,
proxyUrl: storeProxyUrl,
theme,
setLaunch,
setTray,
launchOnBoot,
@ -30,7 +29,7 @@ const GeneralSettings: FC = () => {
enableDataCollection
} = useSettings()
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
const { theme: themeMode } = useTheme()
const { theme } = useTheme()
const updateTray = (isShowTray: boolean) => {
setTray(isShowTray)
@ -116,7 +115,7 @@ const GeneralSettings: FC = () => {
}
return (
<SettingContainer theme={themeMode}>
<SettingContainer theme={theme}>
<SettingGroup theme={theme}>
<SettingTitle>{t('settings.general.title')}</SettingTitle>
<SettingDivider />

View File

@ -198,7 +198,7 @@ export const initialState: SettingsState = {
launchToTray: false,
trayOnClose: true,
tray: true,
theme: ThemeMode.auto,
theme: ThemeMode.system,
userTheme: {
colorPrimary: '#00b96b'
},

View File

@ -317,7 +317,7 @@ export enum FileTypes {
export enum ThemeMode {
light = 'light',
dark = 'dark',
auto = 'auto'
system = 'system'
}
export type LanguageVarious = 'zh-CN' | 'zh-TW' | 'el-GR' | 'en-US' | 'es-ES' | 'fr-FR' | 'ja-JP' | 'pt-PT' | 'ru-RU'

View File

@ -1,4 +1,5 @@
import { isMac } from '@renderer/config/constant'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useDefaultAssistant, useDefaultModel } from '@renderer/hooks/useAssistant'
import { useSettings } from '@renderer/hooks/useSettings'
import i18n from '@renderer/i18n'
@ -9,6 +10,7 @@ import store from '@renderer/store'
import { upsertManyBlocks } from '@renderer/store/messageBlock'
import { updateOneBlock, upsertOneBlock } from '@renderer/store/messageBlock'
import { newMessagesActions } from '@renderer/store/newMessage'
import { ThemeMode } from '@renderer/types'
import { Chunk, ChunkType } from '@renderer/types/chunk'
import { AssistantMessageStatus } from '@renderer/types/newMessage'
import { MessageBlockStatus } from '@renderer/types/newMessage'
@ -43,7 +45,8 @@ const HomeWindow: FC = () => {
const { defaultModel, quickAssistantModel } = useDefaultModel()
// 如果 quickAssistantModel 未設定,則使用 defaultModel
const model = quickAssistantModel || defaultModel
const { language, readClipboardAtStartup, windowStyle, theme } = useSettings()
const { language, readClipboardAtStartup, windowStyle } = useSettings()
const { theme } = useTheme()
const { t } = useTranslation()
const inputBarRef = useRef<HTMLDivElement>(null)
const featureMenusRef = useRef<FeatureMenusRef>(null)
@ -258,12 +261,7 @@ const HomeWindow: FC = () => {
const backgroundColor = () => {
// ONLY MAC: when transparent style + light theme: use vibrancy effect
// because the dark style under mac's vibrancy effect has not been implemented
if (
isMac &&
windowStyle === 'transparent' &&
theme === 'light' &&
!window.matchMedia('(prefers-color-scheme: dark)').matches
) {
if (isMac && windowStyle === 'transparent' && theme === ThemeMode.light) {
return 'transparent'
}