support show traffic on taskbar

This commit is contained in:
pompurin404 2024-09-28 17:36:40 +08:00
parent a111131a16
commit 1f2eee133b
No known key found for this signature in database
8 changed files with 91 additions and 20 deletions

View File

@ -1,6 +1,7 @@
### New Features
- Windows 允许添加 `noadmin` 参数以普通权限启动程序
- 支持在 Windows 任务栏显示网速信息
### Bug Fixes

View File

@ -271,6 +271,28 @@ const resolveRunner = () =>
file: '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 = () =>
resolveResource({
file: '7za.exe',
@ -355,6 +377,12 @@ const tasks = [
retry: 5,
winOnly: true
},
{
name: 'monitor',
func: resolveMonitor,
retry: 5,
winOnly: true
},
{
name: 'substore',
func: resolveSubstore,

View File

@ -34,6 +34,7 @@ import { mainWindow } from '..'
import path from 'path'
import { existsSync } from 'fs'
import { uploadRuntimeConfig } from '../resolve/gistApi'
import { startMonitor } from '../resolve/trafficMonitor'
chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {}).on('unlinkDir', async () => {
try {
@ -193,6 +194,7 @@ export async function keepCoreAlive(): Promise<void> {
export async function quitWithoutCore(): Promise<void> {
await keepCoreAlive()
await startMonitor(true)
app.exit()
}

View 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')
}
}

View File

@ -35,6 +35,7 @@ import {
} from '../config'
import { app } from 'electron'
import { startSSIDCheck } from '../sys/ssid'
import { startMonitor } from '../resolve/trafficMonitor'
async function initDirs(): Promise<void> {
if (!existsSync(dataDir())) {
@ -223,6 +224,7 @@ export async function init(): Promise<void> {
await cleanup()
await startPacServer()
await startSubStoreServer()
await startMonitor()
const { sysProxy } = await getAppConfig()
await triggerSysProxy(sysProxy.enable)
await startSSIDCheck()

View File

@ -80,6 +80,7 @@ import path from 'path'
import v8 from 'v8'
import { getGistUrl } from '../resolve/gistApi'
import { getImageDataURL } from './image'
import { startMonitor } from '../resolve/trafficMonitor'
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
@ -161,6 +162,7 @@ export function registerIpcMainHandlers(): void {
ipcMain.handle('getOverride', (_e, id, ext) => ipcErrorWrapper(getOverride)(id, ext))
ipcMain.handle('setOverride', (_e, id, ext, str) => ipcErrorWrapper(setOverride)(id, ext, str))
ipcMain.handle('restartCore', ipcErrorWrapper(restartCore))
ipcMain.handle('startMonitor', (_e, detached) => ipcErrorWrapper(startMonitor)(detached))
ipcMain.handle('triggerSysProxy', (_e, enable) => ipcErrorWrapper(triggerSysProxy)(enable))
ipcMain.handle('isEncryptionAvailable', isEncryptionAvailable)
ipcMain.handle('encryptString', (_e, str) => encryptString(str))

View File

@ -15,7 +15,7 @@ import {
importThemes,
relaunchApp,
resolveThemes,
restartCore,
startMonitor,
writeTheme
} from '@renderer/utils/ipc'
import { useAppConfig } from '@renderer/hooks/use-app-config'
@ -176,15 +176,30 @@ const GeneralConfig: React.FC = () => {
</Select>
</SettingItem>
{platform !== 'linux' && (
<SettingItem title="托盘菜单显示节点信息" divider>
<Switch
size="sm"
isSelected={proxyInTray}
onValueChange={async (v) => {
await patchAppConfig({ proxyInTray: v })
}}
/>
</SettingItem>
<>
<SettingItem title="托盘菜单显示节点信息" divider>
<Switch
size="sm"
isSelected={proxyInTray}
onValueChange={async (v) => {
await patchAppConfig({ proxyInTray: v })
}}
/>
</SettingItem>
<SettingItem
title={`${platform === 'win32' ? '任务栏' : '状态栏'}显示网速信息`}
divider
>
<Switch
size="sm"
isSelected={showTraffic}
onValueChange={async (v) => {
await patchAppConfig({ showTraffic: v })
await startMonitor()
}}
/>
</SettingItem>
</>
)}
{platform === 'darwin' && (
<>
@ -197,16 +212,6 @@ const GeneralConfig: React.FC = () => {
}}
/>
</SettingItem>
<SettingItem title="显示网速信息" divider>
<Switch
size="sm"
isSelected={showTraffic}
onValueChange={async (v) => {
await patchAppConfig({ showTraffic: v })
await restartCore()
}}
/>
</SettingItem>
</>
)}

View File

@ -191,6 +191,10 @@ export async function restartCore(): Promise<void> {
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> {
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('triggerSysProxy', enable))
}