mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 21:20:29 +08:00
synced tray menu
This commit is contained in:
parent
3dd436d837
commit
8463175779
@ -1,20 +1,71 @@
|
|||||||
import { app, shell, BrowserWindow, Tray, Menu } from 'electron'
|
import { app, shell, BrowserWindow, Tray, Menu, ipcMain } from 'electron'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||||
import pngIcon from '../../resources/icon.png?asset'
|
import pngIcon from '../../resources/icon.png?asset'
|
||||||
import icoIcon from '../../resources/icon.ico?asset'
|
import icoIcon from '../../resources/icon.ico?asset'
|
||||||
import { registerIpcMainHandlers } from './cmds'
|
import { registerIpcMainHandlers } from './cmds'
|
||||||
import { initConfig, appConfig } from './config'
|
import { initConfig, appConfig, controledMihomoConfig, setControledMihomoConfig } from './config'
|
||||||
import { stopCore, startCore } from './manager'
|
import { stopCore, startCore } from './manager'
|
||||||
import { initDirs } from './dirs'
|
import { initDirs } from './dirs'
|
||||||
|
import { patchMihomoConfig } from './mihomo-api'
|
||||||
|
|
||||||
let window: BrowserWindow | null = null
|
let window: BrowserWindow | null = null
|
||||||
let tray: Tray | null = null
|
let tray: Tray | null = null
|
||||||
let trayContextMenu: Menu | null = null
|
let trayContextMenu: Menu | null = null
|
||||||
|
|
||||||
initDirs()
|
const gotTheLock = app.requestSingleInstanceLock()
|
||||||
initConfig()
|
|
||||||
startCore()
|
if (!gotTheLock) {
|
||||||
|
app.quit()
|
||||||
|
} else {
|
||||||
|
initDirs()
|
||||||
|
initConfig()
|
||||||
|
startCore()
|
||||||
|
|
||||||
|
app.on('second-instance', () => {
|
||||||
|
window?.show()
|
||||||
|
window?.focusOnWebView()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||||
|
// for applications and their menu bar to stay active until the user quits
|
||||||
|
// explicitly with Cmd + Q.
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('before-quit', () => {
|
||||||
|
stopCore()
|
||||||
|
app.exit()
|
||||||
|
})
|
||||||
|
|
||||||
|
// This method will be called when Electron has finished
|
||||||
|
// initialization and is ready to create browser windows.
|
||||||
|
// Some APIs can only be used after this event occurs.
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
// Set app user model id for windows
|
||||||
|
electronApp.setAppUserModelId('party.mihomo.app')
|
||||||
|
|
||||||
|
// Default open or close DevTools by F12 in development
|
||||||
|
// and ignore CommandOrControl + R in production.
|
||||||
|
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||||
|
app.on('browser-window-created', (_, window) => {
|
||||||
|
optimizer.watchWindowShortcuts(window)
|
||||||
|
})
|
||||||
|
registerIpcMainHandlers()
|
||||||
|
createWindow()
|
||||||
|
createTray()
|
||||||
|
|
||||||
|
app.on('activate', function () {
|
||||||
|
// On macOS it's common to re-create a window in the app when the
|
||||||
|
// dock icon is clicked and there are no other windows open.
|
||||||
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function createWindow(): void {
|
function createWindow(): void {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
window = new BrowserWindow({
|
window = new BrowserWindow({
|
||||||
@ -65,6 +116,7 @@ function createTray(): void {
|
|||||||
}
|
}
|
||||||
trayContextMenu = Menu.buildFromTemplate([
|
trayContextMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
|
id: 'show',
|
||||||
label: '显示窗口',
|
label: '显示窗口',
|
||||||
type: 'normal',
|
type: 'normal',
|
||||||
click: (): void => {
|
click: (): void => {
|
||||||
@ -73,6 +125,43 @@ function createTray(): void {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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: '重启应用',
|
label: '重启应用',
|
||||||
type: 'normal',
|
type: 'normal',
|
||||||
click: (): void => {
|
click: (): void => {
|
||||||
@ -80,10 +169,16 @@ function createTray(): void {
|
|||||||
app.quit()
|
app.quit()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ type: 'separator' },
|
{ id: 'quit', label: '退出应用', type: 'normal', click: (): void => app.quit() }
|
||||||
{ label: '退出应用', type: 'normal', click: (): void => app.quit() }
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
ipcMain.on('controledMihomoConfigUpdated', () => {
|
||||||
|
const { mode } = controledMihomoConfig
|
||||||
|
if (mode) {
|
||||||
|
trayContextMenu?.getMenuItemById(mode)?.click()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
tray.setContextMenu(trayContextMenu)
|
tray.setContextMenu(trayContextMenu)
|
||||||
tray.setIgnoreDoubleClickEvents(true)
|
tray.setIgnoreDoubleClickEvents(true)
|
||||||
tray.setToolTip('Another Mihomo GUI.')
|
tray.setToolTip('Another Mihomo GUI.')
|
||||||
@ -92,41 +187,3 @@ function createTray(): void {
|
|||||||
window?.isVisible() ? window?.hide() : window?.show()
|
window?.isVisible() ? window?.hide() : window?.show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
|
||||||
// initialization and is ready to create browser windows.
|
|
||||||
// Some APIs can only be used after this event occurs.
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
// Set app user model id for windows
|
|
||||||
electronApp.setAppUserModelId('party.mihomo.app')
|
|
||||||
|
|
||||||
// Default open or close DevTools by F12 in development
|
|
||||||
// and ignore CommandOrControl + R in production.
|
|
||||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
|
||||||
app.on('browser-window-created', (_, window) => {
|
|
||||||
optimizer.watchWindowShortcuts(window)
|
|
||||||
})
|
|
||||||
registerIpcMainHandlers()
|
|
||||||
createWindow()
|
|
||||||
createTray()
|
|
||||||
|
|
||||||
app.on('activate', function () {
|
|
||||||
// On macOS it's common to re-create a window in the app when the
|
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
|
||||||
// for applications and their menu bar to stay active until the user quits
|
|
||||||
// explicitly with Cmd + Q.
|
|
||||||
app.on('window-all-closed', () => {
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
app.quit()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.on('before-quit', () => {
|
|
||||||
stopCore()
|
|
||||||
app.exit()
|
|
||||||
})
|
|
||||||
|
|||||||
@ -9,9 +9,7 @@ export function startCore(): void {
|
|||||||
const corePath = mihomoCorePath(appConfig.core ?? 'mihomo')
|
const corePath = mihomoCorePath(appConfig.core ?? 'mihomo')
|
||||||
generateProfile()
|
generateProfile()
|
||||||
stopCore()
|
stopCore()
|
||||||
child = execFile(corePath, ['-d', mihomoWorkDir()], (error, stdout) => {
|
child = execFile(corePath, ['-d', mihomoWorkDir()], () => {})
|
||||||
console.log(stdout)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stopCore(): void {
|
export function stopCore(): void {
|
||||||
|
|||||||
@ -10,6 +10,12 @@ const OutboundModeSwitcher: React.FC = () => {
|
|||||||
const onChangeMode = async (mode: OutboundMode): Promise<void> => {
|
const onChangeMode = async (mode: OutboundMode): Promise<void> => {
|
||||||
await patchControledMihomoConfig({ mode })
|
await patchControledMihomoConfig({ mode })
|
||||||
await patchMihomoConfig({ mode })
|
await patchMihomoConfig({ mode })
|
||||||
|
window.electron.ipcRenderer.send(mode)
|
||||||
|
window.electron.ipcRenderer.send('test')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mode) {
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { getControledMihomoConfig, setControledMihomoConfig } from '@renderer/utils/ipc'
|
import { getControledMihomoConfig, setControledMihomoConfig } from '@renderer/utils/ipc'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
interface RetuenType {
|
interface RetuenType {
|
||||||
controledMihomoConfig: Partial<IMihomoConfig> | undefined
|
controledMihomoConfig: Partial<IMihomoConfig> | undefined
|
||||||
@ -15,9 +16,18 @@ export const useControledMihomoConfig = (): RetuenType => {
|
|||||||
|
|
||||||
const patchControledMihomoConfig = async (value: Partial<IMihomoConfig>): Promise<void> => {
|
const patchControledMihomoConfig = async (value: Partial<IMihomoConfig>): Promise<void> => {
|
||||||
await setControledMihomoConfig(value)
|
await setControledMihomoConfig(value)
|
||||||
mutateControledMihomoConfig()
|
window.electron.ipcRenderer.send('controledMihomoConfigUpdated')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.electron.ipcRenderer.on('controledMihomoConfigUpdated', () => {
|
||||||
|
mutateControledMihomoConfig()
|
||||||
|
})
|
||||||
|
return (): void => {
|
||||||
|
window.electron.ipcRenderer.removeAllListeners('controledMihomoConfigUpdated')
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
controledMihomoConfig,
|
controledMihomoConfig,
|
||||||
mutateControledMihomoConfig,
|
mutateControledMihomoConfig,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user