diff --git a/src/main/index.ts b/src/main/index.ts index b5d4f46..a503aa8 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,17 +1,15 @@ -import { app, shell, BrowserWindow, Tray, Menu, ipcMain } from 'electron' +import { app, shell, BrowserWindow } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import pngIcon from '../../resources/icon.png?asset' -import icoIcon from '../../resources/icon.ico?asset' +import icon from '../../resources/icon.png?asset' import { registerIpcMainHandlers } from './cmds' -import { initConfig, appConfig, controledMihomoConfig, setControledMihomoConfig } from './config' +import { initConfig, appConfig } from './config' import { stopCore, startCore } from './manager' import { initDirs } from './dirs' -import { mihomoTraffic, patchMihomoConfig } from './mihomo-api' +import { mihomoTraffic } from './mihomo-api' +import { createTray } from './tray' export let window: BrowserWindow | null = null -let tray: Tray | null = null -let trayContextMenu: Menu | null = null const gotTheLock = app.requestSingleInstanceLock() @@ -75,7 +73,7 @@ function createWindow(): void { height: 600, show: false, autoHideMenuBar: true, - ...(process.platform === 'linux' ? { icon: pngIcon } : {}), + ...(process.platform === 'linux' ? { icon: icon } : {}), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false @@ -107,83 +105,3 @@ function createWindow(): void { window.loadFile(join(__dirname, '../renderer/index.html')) } } - -function createTray(): void { - if (process.platform === 'linux') { - tray = new Tray(pngIcon) - } else { - tray = new Tray(icoIcon) - } - trayContextMenu = Menu.buildFromTemplate([ - { - id: 'show', - label: '显示窗口', - type: 'normal', - click: (): void => { - window?.show() - window?.focusOnWebView() - } - }, - { - id: 'rule', - label: '规则模式', - type: 'radio', - checked: controledMihomoConfig.mode === 'rule', - click: (): void => { - setControledMihomoConfig({ mode: 'rule' }) - patchMihomoConfig({ mode: 'rule' }) - window?.webContents.send('controledMihomoConfigUpdated') - } - }, - { - id: 'global', - label: '全局模式', - type: 'radio', - checked: controledMihomoConfig.mode === 'global', - click: (): void => { - setControledMihomoConfig({ mode: 'global' }) - patchMihomoConfig({ mode: 'global' }) - window?.webContents.send('controledMihomoConfigUpdated') - } - }, - { - id: 'direct', - label: '直连模式', - type: 'radio', - checked: controledMihomoConfig.mode === 'direct', - click: (): void => { - setControledMihomoConfig({ mode: 'direct' }) - patchMihomoConfig({ mode: 'direct' }) - window?.webContents.send('controledMihomoConfigUpdated') - } - }, - { type: 'separator' }, - { id: 'version', label: app.getVersion(), type: 'normal', enabled: false }, - { type: 'separator' }, - { - id: 'restart', - label: '重启应用', - type: 'normal', - click: (): void => { - app.relaunch() - app.quit() - } - }, - { id: 'quit', label: '退出应用', type: 'normal', click: (): void => app.quit() } - ]) - - ipcMain.on('controledMihomoConfigUpdated', () => { - const { mode } = controledMihomoConfig - if (mode) { - trayContextMenu?.getMenuItemById(mode)?.click() - } - }) - - tray.setContextMenu(trayContextMenu) - tray.setIgnoreDoubleClickEvents(true) - tray.setToolTip('Another Mihomo GUI.') - tray.setTitle('Mihomo Party') - tray.addListener('click', () => { - window?.isVisible() ? window?.hide() : window?.show() - }) -} diff --git a/src/main/tray.ts b/src/main/tray.ts new file mode 100644 index 0000000..7aa36b9 --- /dev/null +++ b/src/main/tray.ts @@ -0,0 +1,96 @@ +import { controledMihomoConfig, setControledMihomoConfig } from './config' +import icoIcon from '../../resources/icon.ico?asset' +import pngIcon from '../../resources/icon.png?asset' +import { patchMihomoConfig } from './mihomo-api' +import { window } from '.' +import { app, ipcMain, Menu, Tray } from 'electron' + +let tray: Tray | null = null + +const buildContextMenu = (): Menu => { + const contextMenu = [ + { + id: 'show', + label: '显示窗口', + type: 'normal', + click: (): void => { + window?.show() + window?.focusOnWebView() + } + }, + { + id: 'rule', + label: '规则模式', + type: 'radio', + checked: controledMihomoConfig.mode === 'rule', + click: (): void => { + setControledMihomoConfig({ mode: 'rule' }) + patchMihomoConfig({ mode: 'rule' }) + window?.webContents.send('controledMihomoConfigUpdated') + updateTrayMenu() + } + }, + { + id: 'global', + label: '全局模式', + type: 'radio', + checked: controledMihomoConfig.mode === 'global', + click: (): void => { + setControledMihomoConfig({ mode: 'global' }) + patchMihomoConfig({ mode: 'global' }) + window?.webContents.send('controledMihomoConfigUpdated') + updateTrayMenu() + } + }, + { + id: 'direct', + label: '直连模式', + type: 'radio', + checked: controledMihomoConfig.mode === 'direct', + click: (): void => { + setControledMihomoConfig({ mode: 'direct' }) + patchMihomoConfig({ mode: 'direct' }) + window?.webContents.send('controledMihomoConfigUpdated') + updateTrayMenu() + } + }, + { type: 'separator' }, + { + id: 'restart', + label: '重启应用', + type: 'normal', + click: (): void => { + app.relaunch() + app.quit() + } + }, + { id: 'quit', label: '退出应用', type: 'normal', click: (): void => app.quit() } + ] as Electron.MenuItemConstructorOptions[] + return Menu.buildFromTemplate(contextMenu) +} + +export function createTray(): void { + if (process.platform === 'linux') { + tray = new Tray(pngIcon) + } else { + tray = new Tray(icoIcon) + } + const menu = buildContextMenu() + + ipcMain.on('controledMihomoConfigUpdated', () => { + updateTrayMenu() + }) + + tray.setContextMenu(menu) + tray.setIgnoreDoubleClickEvents(true) + tray.setToolTip('Another Mihomo GUI.') + tray.setTitle('Mihomo Party') + tray.addListener('click', () => { + window?.isVisible() ? window?.hide() : window?.show() + }) +} + +function updateTrayMenu(): void { + const menu = buildContextMenu() + tray?.setContextMenu(menu) // 更新菜单 +} diff --git a/src/renderer/src/components/sider/outbound-mode-switcher.tsx b/src/renderer/src/components/sider/outbound-mode-switcher.tsx index 801a25f..b15e129 100644 --- a/src/renderer/src/components/sider/outbound-mode-switcher.tsx +++ b/src/renderer/src/components/sider/outbound-mode-switcher.tsx @@ -10,12 +10,6 @@ const OutboundModeSwitcher: React.FC = () => { const onChangeMode = async (mode: OutboundMode): Promise => { await patchControledMihomoConfig({ mode }) await patchMihomoConfig({ mode }) - window.electron.ipcRenderer.send(mode) - window.electron.ipcRenderer.send('test') - } - - if (!mode) { - return null } return ( diff --git a/src/renderer/src/hooks/use-controled-mihomo-config.tsx b/src/renderer/src/hooks/use-controled-mihomo-config.tsx index 40f5d37..67548d4 100644 --- a/src/renderer/src/hooks/use-controled-mihomo-config.tsx +++ b/src/renderer/src/hooks/use-controled-mihomo-config.tsx @@ -16,6 +16,7 @@ export const useControledMihomoConfig = (): RetuenType => { const patchControledMihomoConfig = async (value: Partial): Promise => { await setControledMihomoConfig(value) + mutateControledMihomoConfig() window.electron.ipcRenderer.send('controledMihomoConfigUpdated') }