feat: Launch on boot, Minimize to tray on launch & on close / fix: Mac: don't show dock when close to tray (#2871)
* launch/tray feature enhance stashed * feature: Issue #2754. launch on boot(win&mac, linux not supported now), min to tray when launch(not only boot), min to tray when close bug-fix: Issue #2576. In Mac, if tray-on-close is set, MainWindow will not show on the dock when closed bug-fix: MiniWindow will hide MainWindow when it shows first time and won't hide MainWindow later. The user will not open the MainWindow again if the tray is set to not show. The bug fixed by not hiding the MainWindow anytime the MiniWindow showed. * migration version fix * fix: enable universal shortcuts when launch to tray * ✨ feat: add Model Context Protocol (MCP) support (#2809) * ✨ feat: add Model Context Protocol (MCP) server configuration (main) - Added `@modelcontextprotocol/sdk` dependency for MCP integration. - Introduced MCP server configuration UI in settings with add, edit, delete, and activation functionalities. - Created `useMCPServers` hook to manage MCP server state and actions. - Added i18n support for MCP settings with translation keys. - Integrated MCP settings into the application's settings navigation and routing. - Implemented Redux state management for MCP servers. - Updated `yarn.lock` with new dependencies and their resolutions. * 🌟 feat: implement mcp service and integrate with ipc handlers - Added `MCPService` class to manage Model Context Protocol servers. - Implemented various handlers in `ipc.ts` for managing MCP servers including listing, adding, updating, deleting, and activating/deactivating servers. - Integrated MCP related types into existing type declarations for consistency across the application. - Updated `preload` to expose new MCP related APIs to the renderer process. - Enhanced `MCPSettings` component to interact directly with the new MCP service for adding, updating, deleting servers and setting their active states. - Introduced selectors in the MCP Redux slice for fetching active and all servers from the store. - Moved MCP types to a centralized location in `@renderer/types` for reuse across different parts of the application. * feat: enhance MCPService initialization to prevent recursive calls and improve error handling * feat: enhance MCP integration by adding MCPTool type and updating related methods * feat: implement streaming support for tool calls in OpenAIProvider and enhance message processing * fix: finish_reason undefined --------- Co-authored-by: LiuVaayne <10231735+vaayne@users.noreply.github.com> Co-authored-by: kangfenmao <kangfenmao@qq.com>
This commit is contained in:
parent
bc1d6157f6
commit
25c166cb8e
@ -4,6 +4,7 @@ import { app, ipcMain } from 'electron'
|
||||
import installExtension, { REDUX_DEVTOOLS } from 'electron-devtools-installer'
|
||||
|
||||
import { registerIpc } from './ipc'
|
||||
import { configManager } from './services/ConfigManager'
|
||||
import { registerShortcuts } from './services/ShortcutService'
|
||||
import { TrayService } from './services/TrayService'
|
||||
import { windowService } from './services/WindowService'
|
||||
@ -21,6 +22,12 @@ if (!app.requestSingleInstanceLock()) {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId(import.meta.env.VITE_MAIN_BUNDLE_ID || 'com.kangfenmao.CherryStudio')
|
||||
|
||||
// Mac: Hide dock icon before window creation when launch to tray is set
|
||||
const isLaunchToTray = configManager.getLaunchToTray()
|
||||
if (isLaunchToTray) {
|
||||
app.dock?.hide()
|
||||
}
|
||||
|
||||
const mainWindow = windowService.createMainWindow()
|
||||
new TrayService()
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import fs from 'node:fs'
|
||||
|
||||
import { isMac, isWin } from '@main/constant'
|
||||
import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process'
|
||||
import { MCPServer, Shortcut, ThemeMode } from '@types'
|
||||
import { BrowserWindow, ipcMain, session, shell } from 'electron'
|
||||
@ -68,11 +69,38 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
configManager.setLanguage(language)
|
||||
})
|
||||
|
||||
// launch on boot
|
||||
ipcMain.handle('app:set-launch-on-boot', (_, isActive: boolean) => {
|
||||
// Set login item settings for windows and mac
|
||||
// linux is not supported because it requires more file operations
|
||||
if (isWin || isMac) {
|
||||
if (isActive) {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: true
|
||||
})
|
||||
} else {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// launch to tray
|
||||
ipcMain.handle('app:set-launch-to-tray', (_, isActive: boolean) => {
|
||||
configManager.setLaunchToTray(isActive)
|
||||
})
|
||||
|
||||
// tray
|
||||
ipcMain.handle('app:set-tray', (_, isActive: boolean) => {
|
||||
configManager.setTray(isActive)
|
||||
})
|
||||
|
||||
// to tray on close
|
||||
ipcMain.handle('app:set-tray-on-close', (_, isActive: boolean) => {
|
||||
configManager.setTrayOnClose(isActive)
|
||||
})
|
||||
|
||||
ipcMain.handle('app:restart-tray', () => TrayService.getInstance().restartTray())
|
||||
|
||||
ipcMain.handle('config:set', (_, key: string, value: any) => {
|
||||
|
||||
@ -30,6 +30,14 @@ export class ConfigManager {
|
||||
this.store.set('theme', theme)
|
||||
}
|
||||
|
||||
getLaunchToTray(): boolean {
|
||||
return !!this.store.get('launchToTray', false)
|
||||
}
|
||||
|
||||
setLaunchToTray(value: boolean) {
|
||||
this.store.set('launchToTray', value)
|
||||
}
|
||||
|
||||
getTray(): boolean {
|
||||
return !!this.store.get('tray', true)
|
||||
}
|
||||
@ -39,6 +47,14 @@ export class ConfigManager {
|
||||
this.notifySubscribers('tray', value)
|
||||
}
|
||||
|
||||
getTrayOnClose(): boolean {
|
||||
return !!this.store.get('trayOnClose', true)
|
||||
}
|
||||
|
||||
setTrayOnClose(value: boolean) {
|
||||
this.store.set('trayOnClose', value)
|
||||
}
|
||||
|
||||
getZoomFactor(): number {
|
||||
return this.store.get('zoomFactor', 1) as number
|
||||
}
|
||||
|
||||
@ -115,7 +115,20 @@ const convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutForm
|
||||
}
|
||||
|
||||
export function registerShortcuts(window: BrowserWindow) {
|
||||
const register = () => {
|
||||
window.once('ready-to-show', () => {
|
||||
if (configManager.getLaunchToTray()) {
|
||||
registerOnlyUniversalShortcuts()
|
||||
}
|
||||
})
|
||||
|
||||
//only for clearer code
|
||||
const registerOnlyUniversalShortcuts = () => {
|
||||
register(true)
|
||||
}
|
||||
|
||||
//onlyUniversalShortcuts is used to register shortcuts that are not window specific, like show_app & mini_window
|
||||
//onlyUniversalShortcuts is needed when we launch to tray
|
||||
const register = (onlyUniversalShortcuts: boolean = false) => {
|
||||
if (window.isDestroyed()) return
|
||||
|
||||
const shortcuts = configManager.getShortcuts()
|
||||
@ -132,6 +145,11 @@ export function registerShortcuts(window: BrowserWindow) {
|
||||
return
|
||||
}
|
||||
|
||||
// only register universal shortcuts when needed
|
||||
if (onlyUniversalShortcuts && !['show_app', 'mini_window'].includes(shortcut.key)) {
|
||||
return
|
||||
}
|
||||
|
||||
const handler = getShortcutHandler(shortcut)
|
||||
if (!handler) {
|
||||
return
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { is } from '@electron-toolkit/utils'
|
||||
import { isDev, isLinux, isWin } from '@main/constant'
|
||||
import { isDev, isLinux, isMac, isWin } from '@main/constant'
|
||||
import { getFilesDir } from '@main/utils/file'
|
||||
import { app, BrowserWindow, ipcMain, Menu, MenuItem, shell } from 'electron'
|
||||
import Logger from 'electron-log'
|
||||
@ -39,8 +39,6 @@ export class WindowService {
|
||||
})
|
||||
|
||||
const theme = configManager.getTheme()
|
||||
const isMac = process.platform === 'darwin'
|
||||
const isLinux = process.platform === 'linux'
|
||||
|
||||
this.mainWindow = new BrowserWindow({
|
||||
x: mainWindowState.x,
|
||||
@ -146,7 +144,12 @@ export class WindowService {
|
||||
private setupWindowEvents(mainWindow: BrowserWindow) {
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.webContents.setZoomFactor(configManager.getZoomFactor())
|
||||
mainWindow.show()
|
||||
|
||||
// show window only when laucn to tray not set
|
||||
const isLaunchToTray = configManager.getLaunchToTray()
|
||||
if (!isLaunchToTray) {
|
||||
mainWindow.show()
|
||||
}
|
||||
})
|
||||
|
||||
// 处理全屏相关事件
|
||||
@ -255,11 +258,18 @@ export class WindowService {
|
||||
return app.quit()
|
||||
}
|
||||
|
||||
// 没有开启托盘,且是Windows或Linux系统,直接退出
|
||||
const notInTray = !configManager.getTray()
|
||||
if ((isWin || isLinux) && notInTray) {
|
||||
return app.quit()
|
||||
// 托盘及关闭行为设置
|
||||
const isShowTray = configManager.getTray()
|
||||
const isTrayOnClose = configManager.getTrayOnClose()
|
||||
// 没有开启托盘,或者开启了托盘,但设置了直接关闭,应执行直接退出
|
||||
if (!isShowTray || (isShowTray && !isTrayOnClose)) {
|
||||
// 如果是Windows或Linux,直接退出
|
||||
// mac按照系统默认行为,不退出
|
||||
if (isWin || isLinux) {
|
||||
return app.quit()
|
||||
}
|
||||
}
|
||||
//上述逻辑以下,是“开启托盘+设置关闭时最小化到托盘”的情况
|
||||
|
||||
// 如果是Windows或Linux,且处于全屏状态,则退出应用
|
||||
if (this.wasFullScreen) {
|
||||
@ -273,6 +283,7 @@ export class WindowService {
|
||||
}
|
||||
event.preventDefault()
|
||||
mainWindow.hide()
|
||||
app.dock?.hide() //for mac to hide to tray
|
||||
})
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
@ -301,6 +312,8 @@ export class WindowService {
|
||||
this.mainWindow = this.createMainWindow()
|
||||
this.mainWindow.focus()
|
||||
}
|
||||
//for mac users, when window is shown, should show dock icon (dock may be set to hide when launch)
|
||||
app.dock?.show()
|
||||
}
|
||||
|
||||
public showMiniWindow() {
|
||||
@ -310,9 +323,6 @@ export class WindowService {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||
this.mainWindow.hide()
|
||||
}
|
||||
if (this.selectionMenuWindow && !this.selectionMenuWindow.isDestroyed()) {
|
||||
this.selectionMenuWindow.hide()
|
||||
}
|
||||
@ -327,8 +337,6 @@ export class WindowService {
|
||||
return
|
||||
}
|
||||
|
||||
const isMac = process.platform === 'darwin'
|
||||
|
||||
this.miniWindow = new BrowserWindow({
|
||||
width: 500,
|
||||
height: 520,
|
||||
@ -403,7 +411,6 @@ export class WindowService {
|
||||
}
|
||||
|
||||
const theme = configManager.getTheme()
|
||||
const isMac = process.platform === 'darwin'
|
||||
|
||||
this.selectionMenuWindow = new BrowserWindow({
|
||||
width: 280,
|
||||
|
||||
3
src/preload/index.d.ts
vendored
3
src/preload/index.d.ts
vendored
@ -23,7 +23,10 @@ declare global {
|
||||
openWebsite: (url: string) => void
|
||||
setProxy: (proxy: string | undefined) => void
|
||||
setLanguage: (theme: LanguageVarious) => void
|
||||
setLaunchOnBoot: (isActive: boolean) => void
|
||||
setLaunchToTray: (isActive: boolean) => void
|
||||
setTray: (isActive: boolean) => void
|
||||
setTrayOnClose: (isActive: boolean) => void
|
||||
restartTray: () => void
|
||||
setTheme: (theme: 'light' | 'dark') => void
|
||||
minApp: (options: { url: string; windowOptions?: Electron.BrowserWindowConstructorOptions }) => void
|
||||
|
||||
@ -11,7 +11,10 @@ const api = {
|
||||
checkForUpdate: () => ipcRenderer.invoke('app:check-for-update'),
|
||||
showUpdateDialog: () => ipcRenderer.invoke('app:show-update-dialog'),
|
||||
setLanguage: (lang: string) => ipcRenderer.invoke('app:set-language', lang),
|
||||
setLaunchOnBoot: (isActive: boolean) => ipcRenderer.invoke('app:set-launch-on-boot', isActive),
|
||||
setLaunchToTray: (isActive: boolean) => ipcRenderer.invoke('app:set-launch-to-tray', isActive),
|
||||
setTray: (isActive: boolean) => ipcRenderer.invoke('app:set-tray', isActive),
|
||||
setTrayOnClose: (isActive: boolean) => ipcRenderer.invoke('app:set-tray-on-close', isActive),
|
||||
restartTray: () => ipcRenderer.invoke('app:restart-tray'),
|
||||
setTheme: (theme: 'light' | 'dark') => ipcRenderer.invoke('app:set-theme', theme),
|
||||
openWebsite: (url: string) => ipcRenderer.invoke('open:website', url),
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
SendMessageShortcut,
|
||||
setLaunchOnBoot,
|
||||
setLaunchToTray,
|
||||
setSendMessageShortcut as _setSendMessageShortcut,
|
||||
setShowAssistantIcon,
|
||||
setSidebarIcons,
|
||||
@ -8,7 +10,8 @@ import {
|
||||
setTheme,
|
||||
SettingsState,
|
||||
setTopicPosition,
|
||||
setTray,
|
||||
setTray as _setTray,
|
||||
setTrayOnClose,
|
||||
setWindowStyle
|
||||
} from '@renderer/store/settings'
|
||||
import { SidebarIcon, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
@ -22,10 +25,30 @@ export function useSettings() {
|
||||
setSendMessageShortcut(shortcut: SendMessageShortcut) {
|
||||
dispatch(_setSendMessageShortcut(shortcut))
|
||||
},
|
||||
setTray(isActive: boolean) {
|
||||
dispatch(setTray(isActive))
|
||||
window.api.setTray(isActive)
|
||||
|
||||
setLaunch(isLaunchOnBoot: boolean | undefined, isLaunchToTray: boolean | undefined = undefined) {
|
||||
if (isLaunchOnBoot !== undefined) {
|
||||
dispatch(setLaunchOnBoot(isLaunchOnBoot))
|
||||
window.api.setLaunchOnBoot(isLaunchOnBoot)
|
||||
}
|
||||
|
||||
if (isLaunchToTray !== undefined) {
|
||||
dispatch(setLaunchToTray(isLaunchToTray))
|
||||
window.api.setLaunchToTray(isLaunchToTray)
|
||||
}
|
||||
},
|
||||
|
||||
setTray(isShowTray: boolean | undefined, isTrayOnClose: boolean | undefined = undefined) {
|
||||
if (isShowTray !== undefined) {
|
||||
dispatch(_setTray(isShowTray))
|
||||
window.api.setTray(isShowTray)
|
||||
}
|
||||
if (isTrayOnClose !== undefined) {
|
||||
dispatch(setTrayOnClose(isTrayOnClose))
|
||||
window.api.setTrayOnClose(isTrayOnClose)
|
||||
}
|
||||
},
|
||||
|
||||
setTheme(theme: ThemeMode) {
|
||||
dispatch(setTheme(theme))
|
||||
},
|
||||
|
||||
@ -1095,7 +1095,12 @@
|
||||
"topic.position.left": "Left",
|
||||
"topic.position.right": "Right",
|
||||
"topic.show.time": "Show topic time",
|
||||
"tray.title": "Enable System Tray Icon",
|
||||
"tray.title": "Tray",
|
||||
"tray.show": "Show Tray Icon",
|
||||
"tray.onclose": "Minimize to Tray on Close",
|
||||
"launch.title": "Launch",
|
||||
"launch.onboot": "Start Automatically on Boot",
|
||||
"launch.totray": "Minimize to Tray on Launch",
|
||||
"websearch": {
|
||||
"blacklist": "Blacklist",
|
||||
"blacklist_description": "Results from the following websites will not appear in search results",
|
||||
|
||||
@ -1095,7 +1095,12 @@
|
||||
"topic.position.left": "左",
|
||||
"topic.position.right": "右",
|
||||
"topic.show.time": "トピックの時間を表示",
|
||||
"tray.title": "システムトレイアイコンを有効にする",
|
||||
"tray.title": "トレイ",
|
||||
"tray.show": "トレイアイコンを表示",
|
||||
"tray.onclose": "閉じるときにトレイに最小化",
|
||||
"launch.title": "起動",
|
||||
"launch.onboot": "起動時に自動で開始",
|
||||
"launch.totray": "起動時にトレイに最小化",
|
||||
"websearch": {
|
||||
"blacklist": "ブラックリスト",
|
||||
"blacklist_description": "以下のウェブサイトの結果は検索結果に表示されません",
|
||||
|
||||
@ -1095,7 +1095,12 @@
|
||||
"topic.position.left": "Слева",
|
||||
"topic.position.right": "Справа",
|
||||
"topic.show.time": "Показывать время топика",
|
||||
"tray.title": "Включить значок системного трея",
|
||||
"tray.title": "Трей",
|
||||
"tray.show": "Показать значок в трее",
|
||||
"tray.onclose": "Свернуть в трей при закрытии",
|
||||
"launch.title": "Запуск",
|
||||
"launch.onboot": "Автозапуск при включении",
|
||||
"launch.totray": "Свернуть в трей при запуске",
|
||||
"websearch": {
|
||||
"blacklist": "Черный список",
|
||||
"blacklist_description": "Результаты из следующих веб-сайтов не будут отображаться в результатах поиска",
|
||||
|
||||
@ -1095,7 +1095,12 @@
|
||||
"topic.position.left": "左侧",
|
||||
"topic.position.right": "右侧",
|
||||
"topic.show.time": "显示话题时间",
|
||||
"tray.title": "启用系统托盘图标",
|
||||
"tray.title": "托盘",
|
||||
"tray.show": "显示托盘图标",
|
||||
"tray.onclose": "关闭时最小化到托盘",
|
||||
"launch.title": "启动",
|
||||
"launch.onboot": "开机自动启动",
|
||||
"launch.totray": "启动时最小化到托盘",
|
||||
"websearch": {
|
||||
"blacklist": "黑名单",
|
||||
"blacklist_description": "在搜索结果中不会出现以下网站的结果",
|
||||
|
||||
@ -1095,7 +1095,12 @@
|
||||
"topic.position.left": "左側",
|
||||
"topic.position.right": "右側",
|
||||
"topic.show.time": "顯示話題時間",
|
||||
"tray.title": "啟用系統工具列圖示",
|
||||
"tray.title": "系统匣",
|
||||
"tray.show": "顯示系统匣圖示",
|
||||
"tray.onclose": "關閉時最小化到系统匣",
|
||||
"launch.title": "啟動",
|
||||
"launch.onboot": "開機自動啟動",
|
||||
"launch.totray": "啟動時最小化到系统匣",
|
||||
"websearch": {
|
||||
"blacklist": "黑名單",
|
||||
"blacklist_description": "以下網站不會出現在搜尋結果中",
|
||||
|
||||
@ -13,13 +13,47 @@ import { useTranslation } from 'react-i18next'
|
||||
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '.'
|
||||
|
||||
const GeneralSettings: FC = () => {
|
||||
const { language, proxyUrl: storeProxyUrl, theme, setTray, tray, proxyMode: storeProxyMode } = useSettings()
|
||||
const {
|
||||
language,
|
||||
proxyUrl: storeProxyUrl,
|
||||
theme,
|
||||
setLaunch,
|
||||
setTray,
|
||||
launchOnBoot,
|
||||
launchToTray,
|
||||
trayOnClose,
|
||||
tray,
|
||||
proxyMode: storeProxyMode
|
||||
} = useSettings()
|
||||
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
|
||||
const { theme: themeMode } = useTheme()
|
||||
|
||||
const updateTray = (value: boolean) => {
|
||||
setTray(value)
|
||||
window.api.setTray(value)
|
||||
const updateTray = (isShowTray: boolean) => {
|
||||
setTray(isShowTray)
|
||||
//only set tray on close/launch to tray when tray is enabled
|
||||
if (!isShowTray) {
|
||||
updateTrayOnClose(false)
|
||||
updateLaunchToTray(false)
|
||||
}
|
||||
}
|
||||
|
||||
const updateTrayOnClose = (isTrayOnClose: boolean) => {
|
||||
setTray(undefined, isTrayOnClose)
|
||||
//in case tray is not enabled, enable it
|
||||
if (isTrayOnClose && !tray) {
|
||||
updateTray(true)
|
||||
}
|
||||
}
|
||||
|
||||
const updateLaunchOnBoot = (isLaunchOnBoot: boolean) => {
|
||||
setLaunch(isLaunchOnBoot)
|
||||
}
|
||||
|
||||
const updateLaunchToTray = (isLaunchToTray: boolean) => {
|
||||
setLaunch(undefined, isLaunchToTray)
|
||||
if (isLaunchToTray && !tray) {
|
||||
updateTray(true)
|
||||
}
|
||||
}
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
@ -52,8 +86,10 @@ const GeneralSettings: FC = () => {
|
||||
dispatch(setProxyMode(mode))
|
||||
if (mode === 'system') {
|
||||
window.api.setProxy('system')
|
||||
dispatch(_setProxyUrl(undefined))
|
||||
} else if (mode === 'none') {
|
||||
window.api.setProxy(undefined)
|
||||
dispatch(_setProxyUrl(undefined))
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,11 +147,32 @@ const GeneralSettings: FC = () => {
|
||||
</SettingRow>
|
||||
</>
|
||||
)}
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle>{t('settings.launch.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.tray.title')}</SettingRowTitle>
|
||||
<SettingRowTitle>{t('settings.launch.onboot')}</SettingRowTitle>
|
||||
<Switch checked={launchOnBoot} onChange={(checked) => updateLaunchOnBoot(checked)} />
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.launch.totray')}</SettingRowTitle>
|
||||
<Switch checked={launchToTray} onChange={(checked) => updateLaunchToTray(checked)} />
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle>{t('settings.tray.title')}</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.tray.show')}</SettingRowTitle>
|
||||
<Switch checked={tray} onChange={(checked) => updateTray(checked)} />
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.tray.onclose')}</SettingRowTitle>
|
||||
<Switch checked={trayOnClose} onChange={(checked) => updateTrayOnClose(checked)} disabled={!tray} />
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
</SettingContainer>
|
||||
)
|
||||
|
||||
@ -791,6 +791,9 @@ const migrateConfig = {
|
||||
},
|
||||
'83': (state: RootState) => {
|
||||
state.settings.messageNavigation = 'buttons'
|
||||
state.settings.launchOnBoot = false
|
||||
state.settings.launchToTray = false
|
||||
state.settings.trayOnClose = true
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,9 @@ export interface SettingsState {
|
||||
showMessageDivider: boolean
|
||||
messageFont: 'system' | 'serif'
|
||||
showInputEstimatedTokens: boolean
|
||||
launchOnBoot: boolean
|
||||
launchToTray: boolean
|
||||
trayOnClose: boolean
|
||||
tray: boolean
|
||||
theme: ThemeMode
|
||||
windowStyle: 'transparent' | 'opaque'
|
||||
@ -103,6 +106,9 @@ const initialState: SettingsState = {
|
||||
showMessageDivider: true,
|
||||
messageFont: 'system',
|
||||
showInputEstimatedTokens: false,
|
||||
launchOnBoot: false,
|
||||
launchToTray: false,
|
||||
trayOnClose: true,
|
||||
tray: true,
|
||||
theme: ThemeMode.auto,
|
||||
windowStyle: 'transparent',
|
||||
@ -205,9 +211,18 @@ const settingsSlice = createSlice({
|
||||
setShowInputEstimatedTokens: (state, action: PayloadAction<boolean>) => {
|
||||
state.showInputEstimatedTokens = action.payload
|
||||
},
|
||||
setLaunchOnBoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.launchOnBoot = action.payload
|
||||
},
|
||||
setLaunchToTray: (state, action: PayloadAction<boolean>) => {
|
||||
state.launchToTray = action.payload
|
||||
},
|
||||
setTray: (state, action: PayloadAction<boolean>) => {
|
||||
state.tray = action.payload
|
||||
},
|
||||
setTrayOnClose: (state, action: PayloadAction<boolean>) => {
|
||||
state.trayOnClose = action.payload
|
||||
},
|
||||
setTheme: (state, action: PayloadAction<ThemeMode>) => {
|
||||
state.theme = action.payload
|
||||
},
|
||||
@ -386,6 +401,9 @@ export const {
|
||||
setShowMessageDivider,
|
||||
setMessageFont,
|
||||
setShowInputEstimatedTokens,
|
||||
setLaunchOnBoot,
|
||||
setLaunchToTray,
|
||||
setTrayOnClose,
|
||||
setTray,
|
||||
setTheme,
|
||||
setFontSize,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user