mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
support show traffic on taskbar
This commit is contained in:
parent
a111131a16
commit
1f2eee133b
@ -1,6 +1,7 @@
|
|||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Windows 允许添加 `noadmin` 参数以普通权限启动程序
|
- Windows 允许添加 `noadmin` 参数以普通权限启动程序
|
||||||
|
- 支持在 Windows 任务栏显示网速信息
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|||||||
@ -271,6 +271,28 @@ const resolveRunner = () =>
|
|||||||
file: 'mihomo-party-run.exe',
|
file: 'mihomo-party-run.exe',
|
||||||
downloadURL: `https://github.com/mihomo-party-org/mihomo-party-run/releases/download/${arch}/mihomo-party-run.exe`
|
downloadURL: `https://github.com/mihomo-party-org/mihomo-party-run/releases/download/${arch}/mihomo-party-run.exe`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const resolveMonitor = async () => {
|
||||||
|
const tempDir = path.join(TEMP_DIR, 'TrafficMonitor')
|
||||||
|
const tempZip = path.join(tempDir, `${arch}.zip`)
|
||||||
|
if (!fs.existsSync(tempDir)) {
|
||||||
|
fs.mkdirSync(tempDir, { recursive: true })
|
||||||
|
}
|
||||||
|
await downloadFile(
|
||||||
|
`https://github.com/mihomo-party-org/mihomo-party-run/releases/download/monitor/${arch}.zip`,
|
||||||
|
tempZip
|
||||||
|
)
|
||||||
|
const zip = new AdmZip(tempZip)
|
||||||
|
const resDir = path.join(cwd, 'extra', 'files')
|
||||||
|
const targetPath = path.join(resDir, 'TrafficMonitor')
|
||||||
|
if (fs.existsSync(targetPath)) {
|
||||||
|
fs.rmSync(targetPath, { recursive: true })
|
||||||
|
}
|
||||||
|
zip.extractAllTo(resDir, true)
|
||||||
|
|
||||||
|
console.log(`[INFO]: TrafficMonitor finished`)
|
||||||
|
}
|
||||||
|
|
||||||
const resolve7zip = () =>
|
const resolve7zip = () =>
|
||||||
resolveResource({
|
resolveResource({
|
||||||
file: '7za.exe',
|
file: '7za.exe',
|
||||||
@ -355,6 +377,12 @@ const tasks = [
|
|||||||
retry: 5,
|
retry: 5,
|
||||||
winOnly: true
|
winOnly: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'monitor',
|
||||||
|
func: resolveMonitor,
|
||||||
|
retry: 5,
|
||||||
|
winOnly: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'substore',
|
name: 'substore',
|
||||||
func: resolveSubstore,
|
func: resolveSubstore,
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import { mainWindow } from '..'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { existsSync } from 'fs'
|
import { existsSync } from 'fs'
|
||||||
import { uploadRuntimeConfig } from '../resolve/gistApi'
|
import { uploadRuntimeConfig } from '../resolve/gistApi'
|
||||||
|
import { startMonitor } from '../resolve/trafficMonitor'
|
||||||
|
|
||||||
chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {}).on('unlinkDir', async () => {
|
chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {}).on('unlinkDir', async () => {
|
||||||
try {
|
try {
|
||||||
@ -193,6 +194,7 @@ export async function keepCoreAlive(): Promise<void> {
|
|||||||
|
|
||||||
export async function quitWithoutCore(): Promise<void> {
|
export async function quitWithoutCore(): Promise<void> {
|
||||||
await keepCoreAlive()
|
await keepCoreAlive()
|
||||||
|
await startMonitor(true)
|
||||||
app.exit()
|
app.exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
src/main/resolve/trafficMonitor.ts
Normal file
27
src/main/resolve/trafficMonitor.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { ChildProcess, spawn } from 'child_process'
|
||||||
|
import { getAppConfig } from '../config'
|
||||||
|
import { resourcesFilesDir } from '../utils/dirs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
let child: ChildProcess
|
||||||
|
|
||||||
|
export async function startMonitor(detached = false): Promise<void> {
|
||||||
|
if (process.platform !== 'win32') return
|
||||||
|
await stopMonitor()
|
||||||
|
const { showTraffic = true } = await getAppConfig()
|
||||||
|
if (!showTraffic) return
|
||||||
|
child = spawn(path.join(resourcesFilesDir(), 'TrafficMonitor/TrafficMonitor.exe'), [], {
|
||||||
|
cwd: path.join(resourcesFilesDir(), 'TrafficMonitor'),
|
||||||
|
detached: detached,
|
||||||
|
stdio: detached ? 'ignore' : undefined
|
||||||
|
})
|
||||||
|
if (detached) {
|
||||||
|
child.unref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopMonitor(): Promise<void> {
|
||||||
|
if (child) {
|
||||||
|
child.kill('SIGINT')
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,7 @@ import {
|
|||||||
} from '../config'
|
} from '../config'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
import { startSSIDCheck } from '../sys/ssid'
|
import { startSSIDCheck } from '../sys/ssid'
|
||||||
|
import { startMonitor } from '../resolve/trafficMonitor'
|
||||||
|
|
||||||
async function initDirs(): Promise<void> {
|
async function initDirs(): Promise<void> {
|
||||||
if (!existsSync(dataDir())) {
|
if (!existsSync(dataDir())) {
|
||||||
@ -223,6 +224,7 @@ export async function init(): Promise<void> {
|
|||||||
await cleanup()
|
await cleanup()
|
||||||
await startPacServer()
|
await startPacServer()
|
||||||
await startSubStoreServer()
|
await startSubStoreServer()
|
||||||
|
await startMonitor()
|
||||||
const { sysProxy } = await getAppConfig()
|
const { sysProxy } = await getAppConfig()
|
||||||
await triggerSysProxy(sysProxy.enable)
|
await triggerSysProxy(sysProxy.enable)
|
||||||
await startSSIDCheck()
|
await startSSIDCheck()
|
||||||
|
|||||||
@ -80,6 +80,7 @@ import path from 'path'
|
|||||||
import v8 from 'v8'
|
import v8 from 'v8'
|
||||||
import { getGistUrl } from '../resolve/gistApi'
|
import { getGistUrl } from '../resolve/gistApi'
|
||||||
import { getImageDataURL } from './image'
|
import { getImageDataURL } from './image'
|
||||||
|
import { startMonitor } from '../resolve/trafficMonitor'
|
||||||
|
|
||||||
function ipcErrorWrapper<T>( // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
function ipcErrorWrapper<T>( // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
fn: (...args: any[]) => Promise<T> // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
fn: (...args: any[]) => Promise<T> // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -161,6 +162,7 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('getOverride', (_e, id, ext) => ipcErrorWrapper(getOverride)(id, ext))
|
ipcMain.handle('getOverride', (_e, id, ext) => ipcErrorWrapper(getOverride)(id, ext))
|
||||||
ipcMain.handle('setOverride', (_e, id, ext, str) => ipcErrorWrapper(setOverride)(id, ext, str))
|
ipcMain.handle('setOverride', (_e, id, ext, str) => ipcErrorWrapper(setOverride)(id, ext, str))
|
||||||
ipcMain.handle('restartCore', ipcErrorWrapper(restartCore))
|
ipcMain.handle('restartCore', ipcErrorWrapper(restartCore))
|
||||||
|
ipcMain.handle('startMonitor', (_e, detached) => ipcErrorWrapper(startMonitor)(detached))
|
||||||
ipcMain.handle('triggerSysProxy', (_e, enable) => ipcErrorWrapper(triggerSysProxy)(enable))
|
ipcMain.handle('triggerSysProxy', (_e, enable) => ipcErrorWrapper(triggerSysProxy)(enable))
|
||||||
ipcMain.handle('isEncryptionAvailable', isEncryptionAvailable)
|
ipcMain.handle('isEncryptionAvailable', isEncryptionAvailable)
|
||||||
ipcMain.handle('encryptString', (_e, str) => encryptString(str))
|
ipcMain.handle('encryptString', (_e, str) => encryptString(str))
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
importThemes,
|
importThemes,
|
||||||
relaunchApp,
|
relaunchApp,
|
||||||
resolveThemes,
|
resolveThemes,
|
||||||
restartCore,
|
startMonitor,
|
||||||
writeTheme
|
writeTheme
|
||||||
} from '@renderer/utils/ipc'
|
} from '@renderer/utils/ipc'
|
||||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||||
@ -176,15 +176,30 @@ const GeneralConfig: React.FC = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
{platform !== 'linux' && (
|
{platform !== 'linux' && (
|
||||||
<SettingItem title="托盘菜单显示节点信息" divider>
|
<>
|
||||||
<Switch
|
<SettingItem title="托盘菜单显示节点信息" divider>
|
||||||
size="sm"
|
<Switch
|
||||||
isSelected={proxyInTray}
|
size="sm"
|
||||||
onValueChange={async (v) => {
|
isSelected={proxyInTray}
|
||||||
await patchAppConfig({ proxyInTray: v })
|
onValueChange={async (v) => {
|
||||||
}}
|
await patchAppConfig({ proxyInTray: v })
|
||||||
/>
|
}}
|
||||||
</SettingItem>
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
<SettingItem
|
||||||
|
title={`${platform === 'win32' ? '任务栏' : '状态栏'}显示网速信息`}
|
||||||
|
divider
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isSelected={showTraffic}
|
||||||
|
onValueChange={async (v) => {
|
||||||
|
await patchAppConfig({ showTraffic: v })
|
||||||
|
await startMonitor()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{platform === 'darwin' && (
|
{platform === 'darwin' && (
|
||||||
<>
|
<>
|
||||||
@ -197,16 +212,6 @@ const GeneralConfig: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
<SettingItem title="显示网速信息" divider>
|
|
||||||
<Switch
|
|
||||||
size="sm"
|
|
||||||
isSelected={showTraffic}
|
|
||||||
onValueChange={async (v) => {
|
|
||||||
await patchAppConfig({ showTraffic: v })
|
|
||||||
await restartCore()
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SettingItem>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -191,6 +191,10 @@ export async function restartCore(): Promise<void> {
|
|||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('restartCore'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('restartCore'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function startMonitor(): Promise<void> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startMonitor'))
|
||||||
|
}
|
||||||
|
|
||||||
export async function triggerSysProxy(enable: boolean): Promise<void> {
|
export async function triggerSysProxy(enable: boolean): Promise<void> {
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('triggerSysProxy', enable))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('triggerSysProxy', enable))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user