Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export const CONFIG_EVENTS = {
// OAuth相关事件
OAUTH_LOGIN_START: 'config:oauth-login-start', // OAuth登录开始
OAUTH_LOGIN_SUCCESS: 'config:oauth-login-success', // OAuth登录成功
OAUTH_LOGIN_ERROR: 'config:oauth-login-error' // OAuth登录失败
OAUTH_LOGIN_ERROR: 'config:oauth-login-error', // OAuth登录失败
THEME_CHANGED: 'config:theme-changed' // 主题变更事件
}

// 会话相关事件
Expand Down
12 changes: 9 additions & 3 deletions src/main/presenter/configPresenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -997,27 +997,33 @@ export class ConfigPresenter implements IConfigPresenter {
async initTheme() {
const theme = this.getSetting<string>('appTheme')
if (theme) {
nativeTheme.themeSource = theme as 'dark' | 'light'
nativeTheme.themeSource = theme as 'dark' | 'light' | 'system'
}
// 监听系统主题变化
nativeTheme.on('updated', () => {
// 只有当主题设置为 system 时,才需要通知渲染进程
// 只有当主题设置为 system 时,才需要通知渲染进程系统主题变化
if (nativeTheme.themeSource === 'system') {
eventBus.sendToMain(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, nativeTheme.shouldUseDarkColors)
}
})
Comment on lines 1003 to 1008
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

System theme update is sent to main instead of renderer

You intend to notify renderers on OS theme changes when themeSource === 'system', but eventBus.sendToMain delivers only within main. Use sendToRenderer and broadcast to all windows.

-    nativeTheme.on('updated', () => {
-      // 只有当主题设置为 system 时,才需要通知渲染进程系统主题变化
-      if (nativeTheme.themeSource === 'system') {
-        eventBus.sendToMain(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, nativeTheme.shouldUseDarkColors)
-      }
-    })
+    nativeTheme.on('updated', () => {
+      // Notify renderers only when app is following the system theme
+      if (nativeTheme.themeSource === 'system') {
+        eventBus.sendToRenderer(
+          SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
+          SendTarget.ALL_WINDOWS,
+          nativeTheme.shouldUseDarkColors
+        )
+      }
+    })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
nativeTheme.on('updated', () => {
// 只有当主题设置为 system 时,才需要通知渲染进程
// 只有当主题设置为 system 时,才需要通知渲染进程系统主题变化
if (nativeTheme.themeSource === 'system') {
eventBus.sendToMain(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, nativeTheme.shouldUseDarkColors)
}
})
nativeTheme.on('updated', () => {
// Notify renderers only when app is following the system theme
if (nativeTheme.themeSource === 'system') {
eventBus.sendToRenderer(
SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
SendTarget.ALL_WINDOWS,
nativeTheme.shouldUseDarkColors
)
}
})
🤖 Prompt for AI Agents
In src/main/presenter/configPresenter/index.ts around lines 1003-1008, the
handler currently calls eventBus.sendToMain when the OS theme changes, but that
only sends within the main process; replace that call with the eventBus API that
sends to renderers and ensure the message is broadcast to all renderer windows
(use eventBus.sendToRenderer and/or the eventBus.broadcast helper so every
BrowserWindow receives SYSTEM_EVENTS.SYSTEM_THEME_UPDATED with
nativeTheme.shouldUseDarkColors).

}

async toggleTheme(theme: 'dark' | 'light' | 'system'): Promise<boolean> {
async setTheme(theme: 'dark' | 'light' | 'system'): Promise<boolean> {
nativeTheme.themeSource = theme
this.setSetting('appTheme', theme)
// 通知所有窗口主题已更改
eventBus.sendToRenderer(CONFIG_EVENTS.THEME_CHANGED, SendTarget.ALL_WINDOWS, theme)
return nativeTheme.shouldUseDarkColors
}

async getTheme(): Promise<string> {
return this.getSetting<string>('appTheme') || 'system'
}

async getCurrentThemeIsDark(): Promise<boolean> {
return nativeTheme.shouldUseDarkColors
}

async getSystemTheme(): Promise<'dark' | 'light'> {
return nativeTheme.shouldUseDarkColors ? 'dark' : 'light'
}
Expand Down
8 changes: 6 additions & 2 deletions src/renderer/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,19 @@ const devicePresenter = usePresenter('devicePresenter')
watch(
[() => themeStore.themeMode, () => settingsStore.fontSizeClass],
([newTheme, newFontSizeClass], [oldTheme, oldFontSizeClass]) => {
let newThemeName = newTheme
if (newTheme === 'system') {
newThemeName = themeStore.isDark ? 'dark' : 'light'
}
if (oldTheme) {
Comment on lines +42 to 46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Fix stale CSS classes when switching to/from 'system' theme and align target element

Bug: removing oldTheme (which can be 'system') won’t remove the actually applied 'dark'/'light' class, causing class accumulation and theme flicker. Also, elsewhere you add classes to body, but here you mutate documentElement, leading to inconsistency.

Replace removal with explicit removal of 'dark' and 'light', then add the effective theme. Keep logs in English and prefer debug level.

-    let newThemeName = newTheme
-    if (newTheme === 'system') {
-      newThemeName = themeStore.isDark ? 'dark' : 'light'
-    }
-    if (oldTheme) {
-      document.documentElement.classList.remove(oldTheme)
-    }
+    const effectiveTheme =
+      newTheme === 'system' ? (themeStore.isDark ? 'dark' : 'light') : newTheme
+    // Always normalize classes before applying the new one
+    document.documentElement.classList.remove('dark')
+    document.documentElement.classList.remove('light')
@@
-    document.documentElement.classList.add(newThemeName)
+    document.documentElement.classList.add(effectiveTheme)
@@
-    console.log('newTheme', newThemeName)
+    console.debug('[theme] applied', { themeMode: newTheme, effectiveTheme })

Additionally, align initial mount with the same element and effective theme (outside the changed range):

// onMounted initial classes
const initialEffectiveTheme =
  themeStore.themeMode === 'system' ? (themeStore.isDark ? 'dark' : 'light') : themeStore.themeMode
document.documentElement.classList.add(initialEffectiveTheme)
document.documentElement.classList.add(settingsStore.fontSizeClass)

Also applies to: 52-55

document.documentElement.classList.remove(oldTheme)
}
if (oldFontSizeClass) {
document.documentElement.classList.remove(oldFontSizeClass)
}
document.documentElement.classList.add(newTheme)
document.documentElement.classList.add(newThemeName)
document.documentElement.classList.add(newFontSizeClass)
console.log('newTheme', themeStore.themeMode)
console.log('newTheme', newThemeName)
},
{ immediate: false } // 初始化在 onMounted 中处理
)
Expand Down
7 changes: 6 additions & 1 deletion src/renderer/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export const CONFIG_EVENTS = {
CONTENT_PROTECTION_CHANGED: 'config:content-protection-changed',
LANGUAGE_CHANGED: 'config:language-changed', // 新增:语言变更事件
SOUND_ENABLED_CHANGED: 'config:sound-enabled-changed', // 新增:声音启用状态变更事件
COPY_WITH_COT_CHANGED: 'config:copy-with-cot-enabled-changed'
COPY_WITH_COT_CHANGED: 'config:copy-with-cot-enabled-changed',
THEME_CHANGED: 'config:theme-changed'
}

// 会话相关事件
Expand Down Expand Up @@ -143,3 +144,7 @@ export const DIALOG_EVENTS = {
export const RAG_EVENTS = {
FILE_UPDATED: 'rag:file-updated' // 文件状态更新
}
// 系统相关事件
export const SYSTEM_EVENTS = {
SYSTEM_THEME_UPDATED: 'system:theme-updated'
}
56 changes: 29 additions & 27 deletions src/renderer/src/stores/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useDark, useToggle } from '@vueuse/core'
import { defineStore } from 'pinia'
import { ref, onMounted, onUnmounted } from 'vue'
import type { IpcRendererEvent } from 'electron'
import { CONFIG_EVENTS, SYSTEM_EVENTS } from '@/events'

export type ThemeMode = 'dark' | 'light' | 'system'

Expand All @@ -19,67 +20,68 @@ export const useThemeStore = defineStore('theme', () => {
const currentTheme = (await configPresenter.getTheme()) as ThemeMode
themeMode.value = currentTheme

// 如果是系统主题模式,则根据系统实际深色/浅色设置来设置界面
if (currentTheme === 'system') {
const systemIsDark = await configPresenter.toggleTheme('system')
console.log('initTheme', systemIsDark)
toggleDark(systemIsDark)
} else {
toggleDark(currentTheme === 'dark')
}
// 获取当前实际的深色模式状态
const isDarkMode = await configPresenter.getCurrentThemeIsDark()
console.log('initTheme - theme:', currentTheme, 'isDark:', isDarkMode)
toggleDark(isDarkMode)
}

initTheme()

// 监听系统主题变化事件
const handleSystemThemeChange = (_event: IpcRendererEvent, isDarkMode: boolean) => {
console.log('handleSystemThemeChange', isDarkMode)
// 只有在系统模式下才跟随系统主题变化
if (themeMode.value === 'system') {
toggleDark(isDarkMode)
}
}
// 监听用户主题变化事件
const handleUserThemeChange = (_event: IpcRendererEvent, theme: ThemeMode) => {
if (themeMode.value !== theme) {
configPresenter.getCurrentThemeIsDark().then((isDark) => {
console.log('handleUserThemeChange', theme, isDark)
themeMode.value = theme
toggleDark(isDark)
})
}
}
Comment on lines +40 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid unnecessary IPC and add try/catch in handleUserThemeChange()

Compute isDark locally for 'dark'/'light' and only query main for 'system'. Also switch to await + try/catch for clearer flow and required error handling.

-  const handleUserThemeChange = (_event: IpcRendererEvent, theme: ThemeMode) => {
-    if (themeMode.value !== theme) {
-      configPresenter.getCurrentThemeIsDark().then((isDark) => {
-        console.log('handleUserThemeChange', theme, isDark)
-        themeMode.value = theme
-        toggleDark(isDark)
-      })
-    }
-  }
+  const handleUserThemeChange = async (_event: IpcRendererEvent, theme: ThemeMode) => {
+    if (themeMode.value === theme) return
+    try {
+      const isDark =
+        theme === 'system'
+          ? await configPresenter.getCurrentThemeIsDark()
+          : theme === 'dark'
+      log('INFO', 'handleUserThemeChange', { theme, isDark })
+      themeMode.value = theme
+      toggleDark(isDark)
+    } catch (err) {
+      log('ERROR', 'handleUserThemeChange failed', { theme, err })
+    }
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleUserThemeChange = (_event: IpcRendererEvent, theme: ThemeMode) => {
if (themeMode.value !== theme) {
configPresenter.getCurrentThemeIsDark().then((isDark) => {
console.log('handleUserThemeChange', theme, isDark)
themeMode.value = theme
toggleDark(isDark)
})
}
}
const handleUserThemeChange = async (_event: IpcRendererEvent, theme: ThemeMode) => {
if (themeMode.value === theme) return
try {
const isDark =
theme === 'system'
? await configPresenter.getCurrentThemeIsDark()
: theme === 'dark'
log('INFO', 'handleUserThemeChange', { theme, isDark })
themeMode.value = theme
toggleDark(isDark)
} catch (err) {
log('ERROR', 'handleUserThemeChange failed', { theme, err })
}
}
🤖 Prompt for AI Agents
In src/renderer/src/stores/theme.ts around lines 40 to 48, handleUserThemeChange
currently always calls configPresenter.getCurrentThemeIsDark() via IPC and uses
.then; change it to compute isDark locally when theme is 'dark' or 'light' and
only invoke the IPC call when theme === 'system', use async/await and wrap the
IPC await in try/catch to handle errors, set themeMode.value and then call
toggleDark(isDark) after resolving isDark, and ensure no IPC is invoked when the
incoming theme equals the current theme.


// 注册和清理主题变化监听器
onMounted(() => {
window.electron.ipcRenderer.on('system-theme-updated', handleSystemThemeChange)
window.electron.ipcRenderer.on(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, handleSystemThemeChange)
window.electron.ipcRenderer.on(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
})

onUnmounted(() => {
window.electron.ipcRenderer.removeListener('system-theme-updated', handleSystemThemeChange)
window.electron.ipcRenderer.removeListener(
SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
handleSystemThemeChange
)
window.electron.ipcRenderer.removeListener(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
})
Comment on lines 51 to 62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: Vue lifecycle hooks don’t run inside Pinia stores — IPC listeners won’t register

onMounted/onUnmounted are component hooks; in a Pinia store they are no-ops, so your handlers never get attached. Register listeners once at store creation with an idempotent guard and clean up on HMR.

-  // 注册和清理主题变化监听器
-  onMounted(() => {
-    window.electron.ipcRenderer.on(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, handleSystemThemeChange)
-    window.electron.ipcRenderer.on(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
-  })
-
-  onUnmounted(() => {
-    window.electron.ipcRenderer.removeListener(
-      SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
-      handleSystemThemeChange
-    )
-    window.electron.ipcRenderer.removeListener(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
-  })
+  // Register/unregister IPC listeners once per store instance (no component lifecycle here)
+  let listenersRegistered = false
+  const registerIpcListeners = () => {
+    if (listenersRegistered) return
+    try {
+      window.electron.ipcRenderer.on(
+        SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
+        handleSystemThemeChange
+      )
+      window.electron.ipcRenderer.on(
+        CONFIG_EVENTS.THEME_CHANGED,
+        handleUserThemeChange
+      )
+      listenersRegistered = true
+      log('INFO', 'IPC listeners registered')
+    } catch (err) {
+      log('ERROR', 'Failed to register IPC listeners', { err })
+    }
+  }
+  const unregisterIpcListeners = () => {
+    if (!listenersRegistered) return
+    try {
+      window.electron.ipcRenderer.removeListener(
+        SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
+        handleSystemThemeChange
+      )
+      window.electron.ipcRenderer.removeListener(
+        CONFIG_EVENTS.THEME_CHANGED,
+        handleUserThemeChange
+      )
+    } finally {
+      listenersRegistered = false
+      log('INFO', 'IPC listeners unregistered')
+    }
+  }
+  registerIpcListeners()
+  // Ensure cleanup during HMR
+  if (import.meta.hot) {
+    import.meta.hot.dispose(unregisterIpcListeners)
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onMounted(() => {
window.electron.ipcRenderer.on('system-theme-updated', handleSystemThemeChange)
window.electron.ipcRenderer.on(SYSTEM_EVENTS.SYSTEM_THEME_UPDATED, handleSystemThemeChange)
window.electron.ipcRenderer.on(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
})
onUnmounted(() => {
window.electron.ipcRenderer.removeListener('system-theme-updated', handleSystemThemeChange)
window.electron.ipcRenderer.removeListener(
SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
handleSystemThemeChange
)
window.electron.ipcRenderer.removeListener(CONFIG_EVENTS.THEME_CHANGED, handleUserThemeChange)
})
// Register/unregister IPC listeners once per store instance (no component lifecycle here)
let listenersRegistered = false
const registerIpcListeners = () => {
if (listenersRegistered) return
try {
window.electron.ipcRenderer.on(
SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
handleSystemThemeChange
)
window.electron.ipcRenderer.on(
CONFIG_EVENTS.THEME_CHANGED,
handleUserThemeChange
)
listenersRegistered = true
log('INFO', 'IPC listeners registered')
} catch (err) {
log('ERROR', 'Failed to register IPC listeners', { err })
}
}
const unregisterIpcListeners = () => {
if (!listenersRegistered) return
try {
window.electron.ipcRenderer.removeListener(
SYSTEM_EVENTS.SYSTEM_THEME_UPDATED,
handleSystemThemeChange
)
window.electron.ipcRenderer.removeListener(
CONFIG_EVENTS.THEME_CHANGED,
handleUserThemeChange
)
} finally {
listenersRegistered = false
log('INFO', 'IPC listeners unregistered')
}
}
registerIpcListeners()
// Ensure cleanup during HMR
if (import.meta.hot) {
import.meta.hot.dispose(unregisterIpcListeners)
}
🤖 Prompt for AI Agents
In src/renderer/src/stores/theme.ts around lines 51 to 62, onMounted/onUnmounted
are component hooks and do not run in a Pinia store, so the IPC listeners never
get attached; change to register the listeners at store creation (top-level
inside the store factory) and protect registration with an idempotent guard
(e.g., a module-level or store-scoped boolean) so repeated imports/HMR don't
double-register, use window.electron.ipcRenderer.on(...) to attach and
window.electron.ipcRenderer.removeListener(...) to detach, and add HMR cleanup
(import.meta.hot?.dispose) to remove listeners and reset the guard on module
replacement.


// 监听深色模式变化
// watch(isDark, (value) => {
// // 只有在非系统模式下,才直接切换主题
// if (themeMode.value !== 'system') {
// windowPresenter.toggleTheme(value ? 'dark' : 'light')
// themeMode.value = value ? 'dark' : 'light'
// }
// })

// 设置主题模式
const setThemeMode = async (mode: ThemeMode) => {
themeMode.value = mode
const isDarkMode = await configPresenter.toggleTheme(mode)
const isDarkMode = await configPresenter.setTheme(mode)

// 如果不是系统模式,直接设置深色/浅色状态
// 如果是系统模式,toggleTheme 会返回系统当前的深色状态
// 设置界面深色/浅色状态
toggleDark(isDarkMode)
}
Comment on lines 65 to 71
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Set theme atomically with error handling; update state only on success

Currently themeMode is set before setTheme() resolves. If IPC fails, UI and persisted setting diverge. Move assignment after success and add required structured logging.

-  const setThemeMode = async (mode: ThemeMode) => {
-    themeMode.value = mode
-    const isDarkMode = await configPresenter.setTheme(mode)
-
-    // 设置界面深色/浅色状态
-    toggleDark(isDarkMode)
-  }
+  const setThemeMode = async (mode: ThemeMode) => {
+    try {
+      const isDarkMode = await configPresenter.setTheme(mode)
+      themeMode.value = mode
+      log('INFO', 'setThemeMode', { mode, isDark: isDarkMode })
+      toggleDark(isDarkMode)
+    } catch (err) {
+      log('ERROR', 'setThemeMode failed', { mode, err })
+    }
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const setThemeMode = async (mode: ThemeMode) => {
themeMode.value = mode
const isDarkMode = await configPresenter.toggleTheme(mode)
const isDarkMode = await configPresenter.setTheme(mode)
// 如果不是系统模式,直接设置深色/浅色状态
// 如果是系统模式,toggleTheme 会返回系统当前的深色状态
// 设置界面深色/浅色状态
toggleDark(isDarkMode)
}
const setThemeMode = async (mode: ThemeMode) => {
try {
const isDarkMode = await configPresenter.setTheme(mode)
themeMode.value = mode
log('INFO', 'setThemeMode', { mode, isDark: isDarkMode })
toggleDark(isDarkMode)
} catch (err) {
log('ERROR', 'setThemeMode failed', { mode, err })
}
}
🤖 Prompt for AI Agents
In src/renderer/src/stores/theme.ts around lines 65 to 71, themeMode is
currently assigned before awaiting configPresenter.setTheme, which can lead to
UI and persisted state divergence if the IPC call fails; change the code to
await configPresenter.setTheme first, only update themeMode and call toggleDark
when the call succeeds, and wrap the await in a try/catch that logs structured
error details (e.g., { action: "setTheme", mode, error }) using the existing
logger so failures do not mutate UI state.


// 循环切换主题:light -> dark -> system -> light
const cycleTheme = () => {
const cycleTheme = async () => {
console.log('cycleTheme', themeMode.value)
if (themeMode.value === 'light') setThemeMode('dark')
else if (themeMode.value === 'dark') setThemeMode('system')
else setThemeMode('light')
if (themeMode.value === 'light') await setThemeMode('dark')
else if (themeMode.value === 'dark') await setThemeMode('system')
else await setThemeMode('light')
}

return {
isDark,
toggleDark,
themeMode,
setThemeMode,
cycleTheme
}
Comment on lines 81 to 86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Don’t export toggleDark; expose setThemeMode to keep renderer and main in sync

Exporting toggleDark enables “local-only” toggles that bypass configPresenter and events, causing desync across windows and restarts. Surface setThemeMode instead and keep toggleDark private.

   return {
     isDark,
-    toggleDark,
     themeMode,
-    cycleTheme
+    cycleTheme,
+    setThemeMode
   }

Run to find any direct usages of toggleDark you’ll need to migrate:


🏁 Script executed:

#!/bin/bash
rg -nP -C2 --type=ts --type=tsx --type=vue '\b(useThemeStore\(\)|themeStore)\.toggleDark\b|toggleDark\s*\('

Length of output: 137


🏁 Script executed:

#!/bin/bash
# Re-run search for direct usages of toggleDark across .ts, .tsx, and .vue files
rg -nP -C2 '\b(useThemeStore\(\)|themeStore)\.toggleDark\b|toggleDark\s*\(' --glob '*.ts' --glob '*.tsx' --glob '*.vue'

Length of output: 1750


Action Required: Remove toggleDark from exports and Migrate Its Consumers

Based on the grep search, toggleDark is only used internally within theme.ts (lines 26, 36, 45, 70) and externally in:

  • src/renderer/src/components/SideBar.vue at line 59:
    @click="themeStore.toggleDark()"

After you remove toggleDark from the store’s returned API, that click handler will break. To resolve:

• In src/renderer/src/stores/theme.ts, update the return value as suggested:

  return {
    isDark,
-   toggleDark,
    themeMode,
    cycleTheme,
+   setThemeMode
  }

• In src/renderer/src/components/SideBar.vue, replace the direct toggle call with one of:

- @click="themeStore.toggleDark()"
+ @click="themeStore.setThemeMode(themeStore.isDark ? 'light' : 'dark')"

—or, if you prefer cycling through modes (including system):

- @click="themeStore.toggleDark()"
+ @click="themeStore.cycleTheme()"

No other external usages of toggleDark were found.
Please update the component(s) accordingly before removing the exported toggleDark.

🤖 Prompt for AI Agents
In src/renderer/src/stores/theme.ts around lines 81-86 and
src/renderer/src/components/SideBar.vue at line 59: remove toggleDark from the
store's returned API (so it is no longer exported) and update any external
callers (SideBar.vue) to use either themeStore.cycleTheme() or directly flip the
mode by assigning themeStore.themeMode = themeStore.themeMode === 'dark' ?
'light' : 'dark' (or set to a specific string), then test the click handler to
ensure it still toggles theme; do not change internal uses inside theme.ts that
remain private.

})
3 changes: 2 additions & 1 deletion src/shared/presenter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,9 @@ export interface IConfigPresenter {
getNotificationsEnabled(): boolean
// 主题设置
initTheme(): void
toggleTheme(theme: 'dark' | 'light' | 'system'): Promise<boolean>
setTheme(theme: 'dark' | 'light' | 'system'): Promise<boolean>
getTheme(): Promise<string>
getCurrentThemeIsDark(): Promise<boolean>
getSystemTheme(): Promise<'dark' | 'light'>
getCustomPrompts(): Promise<Prompt[]>
setCustomPrompts(prompts: Prompt[]): Promise<void>
Expand Down