mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
show proxy in tray menu
This commit is contained in:
parent
87b7ed4edc
commit
206255d1bd
@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
- 添加覆写脚本执行日志功能
|
- 添加覆写脚本执行日志功能
|
||||||
- 支持查看局域网网络信息
|
- 支持查看局域网网络信息
|
||||||
|
- 支持托盘菜单显示节点信息
|
||||||
|
|||||||
@ -7,9 +7,14 @@ import {
|
|||||||
import icoIcon from '../../../resources/icon.ico?asset'
|
import icoIcon from '../../../resources/icon.ico?asset'
|
||||||
import pngIcon from '../../../resources/icon.png?asset'
|
import pngIcon from '../../../resources/icon.png?asset'
|
||||||
import templateIcon from '../../../resources/iconTemplate.png?asset'
|
import templateIcon from '../../../resources/iconTemplate.png?asset'
|
||||||
import { patchMihomoConfig } from '../core/mihomoApi'
|
import {
|
||||||
|
mihomoChangeProxy,
|
||||||
|
mihomoCloseAllConnections,
|
||||||
|
mihomoGroups,
|
||||||
|
patchMihomoConfig
|
||||||
|
} from '../core/mihomoApi'
|
||||||
import { mainWindow, showMainWindow } from '..'
|
import { mainWindow, showMainWindow } from '..'
|
||||||
import { app, ipcMain, Menu, nativeImage, shell, Tray } from 'electron'
|
import { app, Menu, nativeImage, shell, Tray } from 'electron'
|
||||||
import { dataDir, logDir, mihomoCoreDir, mihomoWorkDir } from '../utils/dirs'
|
import { dataDir, logDir, mihomoCoreDir, mihomoWorkDir } from '../utils/dirs'
|
||||||
import { triggerSysProxy } from '../sys/sysproxy'
|
import { triggerSysProxy } from '../sys/sysproxy'
|
||||||
|
|
||||||
@ -17,7 +22,47 @@ export let tray: Tray | null = null
|
|||||||
|
|
||||||
const buildContextMenu = async (): Promise<Menu> => {
|
const buildContextMenu = async (): Promise<Menu> => {
|
||||||
const { mode, tun } = await getControledMihomoConfig()
|
const { mode, tun } = await getControledMihomoConfig()
|
||||||
const { sysProxy } = await getAppConfig()
|
const { sysProxy, autoCloseConnection, proxyInTray = true } = await getAppConfig()
|
||||||
|
let groupsMenu: Electron.MenuItemConstructorOptions[] = []
|
||||||
|
if (proxyInTray) {
|
||||||
|
try {
|
||||||
|
const groups = await mihomoGroups()
|
||||||
|
groupsMenu = groups.map((group) => {
|
||||||
|
return {
|
||||||
|
id: group.name,
|
||||||
|
label: group.name,
|
||||||
|
type: 'submenu',
|
||||||
|
submenu: group.all.map((proxy) => {
|
||||||
|
const delay = proxy.history.length ? proxy.history[proxy.history.length - 1].delay : -1
|
||||||
|
let displayDelay = `(${delay}ms)`
|
||||||
|
if (delay === -1) {
|
||||||
|
displayDelay = ''
|
||||||
|
}
|
||||||
|
if (delay === 0) {
|
||||||
|
displayDelay = '(Timeout)'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: proxy.name,
|
||||||
|
label: `${proxy.name} ${displayDelay}`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: proxy.name === group.now,
|
||||||
|
click: async (): Promise<void> => {
|
||||||
|
await mihomoChangeProxy(group.name, proxy.name)
|
||||||
|
if (autoCloseConnection) {
|
||||||
|
await mihomoCloseAllConnections()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
groupsMenu.unshift({ type: 'separator' })
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
// 避免出错时无法创建托盘菜单
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const contextMenu = [
|
const contextMenu = [
|
||||||
{
|
{
|
||||||
id: 'show',
|
id: 'show',
|
||||||
@ -36,7 +81,6 @@ const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
await patchControledMihomoConfig({ mode: 'rule' })
|
await patchControledMihomoConfig({ mode: 'rule' })
|
||||||
await patchMihomoConfig({ mode: 'rule' })
|
await patchMihomoConfig({ mode: 'rule' })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
await updateTrayMenu()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -48,7 +92,6 @@ const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
await patchControledMihomoConfig({ mode: 'global' })
|
await patchControledMihomoConfig({ mode: 'global' })
|
||||||
await patchMihomoConfig({ mode: 'global' })
|
await patchMihomoConfig({ mode: 'global' })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
await updateTrayMenu()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -60,7 +103,6 @@ const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
await patchControledMihomoConfig({ mode: 'direct' })
|
await patchControledMihomoConfig({ mode: 'direct' })
|
||||||
await patchMihomoConfig({ mode: 'direct' })
|
await patchMihomoConfig({ mode: 'direct' })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
await updateTrayMenu()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
@ -77,7 +119,6 @@ const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
await patchAppConfig({ sysProxy: { enable: !enable } })
|
await patchAppConfig({ sysProxy: { enable: !enable } })
|
||||||
} finally {
|
} finally {
|
||||||
mainWindow?.webContents.send('appConfigUpdated')
|
mainWindow?.webContents.send('appConfigUpdated')
|
||||||
await updateTrayMenu()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -94,9 +135,9 @@ const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
}
|
}
|
||||||
await patchMihomoConfig({ tun: { enable } })
|
await patchMihomoConfig({ tun: { enable } })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
await updateTrayMenu()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
...groupsMenu,
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
type: 'submenu',
|
type: 'submenu',
|
||||||
@ -152,31 +193,22 @@ export async function createTray(): Promise<void> {
|
|||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
tray = new Tray(icoIcon)
|
tray = new Tray(icoIcon)
|
||||||
}
|
}
|
||||||
const menu = await buildContextMenu()
|
|
||||||
|
|
||||||
ipcMain.on('controledMihomoConfigUpdated', async () => {
|
|
||||||
await updateTrayMenu()
|
|
||||||
})
|
|
||||||
ipcMain.on('appConfigUpdated', async () => {
|
|
||||||
await updateTrayMenu()
|
|
||||||
})
|
|
||||||
|
|
||||||
tray?.setToolTip('Mihomo Party')
|
tray?.setToolTip('Mihomo Party')
|
||||||
tray?.setContextMenu(menu)
|
|
||||||
tray?.setIgnoreDoubleClickEvents(true)
|
tray?.setIgnoreDoubleClickEvents(true)
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
if (!useDockIcon) {
|
if (!useDockIcon) {
|
||||||
app.dock.hide()
|
app.dock.hide()
|
||||||
} else {
|
|
||||||
app.dock.setMenu(menu)
|
|
||||||
}
|
}
|
||||||
tray?.addListener('right-click', () => {
|
tray?.addListener('right-click', async () => {
|
||||||
if (mainWindow?.isVisible()) {
|
if (mainWindow?.isVisible()) {
|
||||||
mainWindow?.close()
|
mainWindow?.close()
|
||||||
} else {
|
} else {
|
||||||
showMainWindow()
|
showMainWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
tray?.addListener('click', async () => {
|
||||||
|
await updateTrayMenu()
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
tray?.addListener('click', () => {
|
tray?.addListener('click', () => {
|
||||||
if (mainWindow?.isVisible()) {
|
if (mainWindow?.isVisible()) {
|
||||||
@ -185,13 +217,13 @@ export async function createTray(): Promise<void> {
|
|||||||
showMainWindow()
|
showMainWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
tray?.addListener('right-click', async () => {
|
||||||
|
await updateTrayMenu()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateTrayMenu(): Promise<void> {
|
async function updateTrayMenu(): Promise<void> {
|
||||||
const menu = await buildContextMenu()
|
const menu = await buildContextMenu()
|
||||||
if (process.platform === 'darwin') {
|
tray?.popUpContextMenu(menu) // 弹出菜单
|
||||||
app.dock.setMenu(menu) // 更新dock菜单
|
|
||||||
}
|
|
||||||
tray?.setContextMenu(menu) // 更新菜单
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,11 +109,11 @@ export async function init(): Promise<void> {
|
|||||||
await startPacServer()
|
await startPacServer()
|
||||||
const { sysProxy } = await getAppConfig()
|
const { sysProxy } = await getAppConfig()
|
||||||
await triggerSysProxy(sysProxy.enable)
|
await triggerSysProxy(sysProxy.enable)
|
||||||
startCore().then(() => {
|
await startCore()
|
||||||
startMihomoTraffic()
|
await startMihomoTraffic()
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await initProfileUpdater()
|
await initProfileUpdater()
|
||||||
}, 60000)
|
}, 60000)
|
||||||
})
|
|
||||||
initDeeplink()
|
initDeeplink()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ export const defaultConfig: IAppConfig = {
|
|||||||
core: 'mihomo',
|
core: 'mihomo',
|
||||||
silentStart: false,
|
silentStart: false,
|
||||||
appTheme: 'system',
|
appTheme: 'system',
|
||||||
|
proxyInTray: true,
|
||||||
proxyDisplayMode: 'simple',
|
proxyDisplayMode: 'simple',
|
||||||
proxyDisplayOrder: 'default',
|
proxyDisplayOrder: 'default',
|
||||||
autoCheckUpdate: true,
|
autoCheckUpdate: true,
|
||||||
|
|||||||
@ -18,7 +18,6 @@ export const useAppConfig = (listenUpdate = false): RetuenType => {
|
|||||||
alert(e)
|
alert(e)
|
||||||
} finally {
|
} finally {
|
||||||
mutateAppConfig()
|
mutateAppConfig()
|
||||||
window.electron.ipcRenderer.send('appConfigUpdated')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,6 @@ export const useControledMihomoConfig = (listenUpdate = false): RetuenType => {
|
|||||||
alert(e)
|
alert(e)
|
||||||
} finally {
|
} finally {
|
||||||
mutateControledMihomoConfig()
|
mutateControledMihomoConfig()
|
||||||
window.electron.ipcRenderer.send('controledMihomoConfigUpdated')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -62,6 +62,7 @@ const Proxies: React.FC = () => {
|
|||||||
if (autoCloseConnection) {
|
if (autoCloseConnection) {
|
||||||
await mihomoCloseAllConnections()
|
await mihomoCloseAllConnections()
|
||||||
}
|
}
|
||||||
|
// window.electron.ipcRenderer.send('mihomoGroupsUpdated')
|
||||||
mutate()
|
mutate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ const Settings: React.FC = () => {
|
|||||||
controlSniff = true,
|
controlSniff = true,
|
||||||
useDockIcon = true,
|
useDockIcon = true,
|
||||||
showTraffic = true,
|
showTraffic = true,
|
||||||
|
proxyInTray = true,
|
||||||
delayTestUrl,
|
delayTestUrl,
|
||||||
delayTestTimeout,
|
delayTestTimeout,
|
||||||
autoCheckUpdate,
|
autoCheckUpdate,
|
||||||
@ -194,6 +195,15 @@ const Settings: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
<SettingItem title="托盘菜单显示节点信息" divider>
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isSelected={proxyInTray}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
patchAppConfig({ proxyInTray: v })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
{platform === 'darwin' && (
|
{platform === 'darwin' && (
|
||||||
<>
|
<>
|
||||||
<SettingItem title="显示Dock图标" divider>
|
<SettingItem title="显示Dock图标" divider>
|
||||||
|
|||||||
1
src/shared/types.d.ts
vendored
1
src/shared/types.d.ts
vendored
@ -214,6 +214,7 @@ interface IAppConfig {
|
|||||||
core: 'mihomo' | 'mihomo-alpha'
|
core: 'mihomo' | 'mihomo-alpha'
|
||||||
proxyDisplayMode: 'simple' | 'full'
|
proxyDisplayMode: 'simple' | 'full'
|
||||||
proxyDisplayOrder: 'default' | 'delay' | 'name'
|
proxyDisplayOrder: 'default' | 'delay' | 'name'
|
||||||
|
proxyInTray: boolean
|
||||||
siderOrder: string[]
|
siderOrder: string[]
|
||||||
appTheme: AppTheme
|
appTheme: AppTheme
|
||||||
autoCheckUpdate: boolean
|
autoCheckUpdate: boolean
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user