diff --git a/src/main/config/controledMihomo.ts b/src/main/config/controledMihomo.ts index c15de5eb..bf279edd 100644 --- a/src/main/config/controledMihomo.ts +++ b/src/main/config/controledMihomo.ts @@ -1,6 +1,7 @@ import { controledMihomoConfigPath } from '../utils/dirs' import yaml from 'yaml' import fs from 'fs' +import { getAxios } from '../core/mihomoApi' export let controledMihomoConfig: Partial // mihomo.yaml @@ -13,5 +14,8 @@ export function getControledMihomoConfig(force = false): Partial export function setControledMihomoConfig(patch: Partial): void { controledMihomoConfig = Object.assign(controledMihomoConfig, patch) + if (patch['external-controller'] || patch.secret) { + getAxios(true) + } fs.writeFileSync(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig)) } diff --git a/src/main/core/mihomoApi.ts b/src/main/core/mihomoApi.ts index 7270fc14..56c880f8 100644 --- a/src/main/core/mihomoApi.ts +++ b/src/main/core/mihomoApi.ts @@ -5,6 +5,7 @@ import { window } from '..' let axiosIns: AxiosInstance = null! let mihomoTrafficWs: WebSocket | null = null +let mihomoMemoryWs: WebSocket | null = null let mihomoLogsWs: WebSocket | null = null export const getAxios = async (force: boolean = false): Promise => { @@ -111,6 +112,45 @@ const mihomoTraffic = (): void => { } } +export const startMihomoMemory = (): void => { + mihomoMemory() +} + +export const stopMihomoMemory = (): void => { + if (mihomoMemoryWs) { + mihomoMemoryWs.removeAllListeners() + if (mihomoMemoryWs.readyState === WebSocket.OPEN) { + mihomoMemoryWs.close() + } + mihomoMemoryWs = null + } +} + +const mihomoMemory = (): void => { + let server = getControledMihomoConfig()['external-controller'] + const secret = getControledMihomoConfig().secret ?? '' + if (server?.startsWith(':')) server = `127.0.0.1${server}` + stopMihomoMemory() + + mihomoMemoryWs = new WebSocket(`ws://${server}/memory?secret=${secret}`) + + mihomoMemoryWs.onmessage = (e): void => { + const data = e.data as string + window?.webContents.send('mihomoMemory', JSON.parse(data) as IMihomoMemoryInfo) + } + + mihomoMemoryWs.onclose = (): void => { + mihomoMemory() + } + + mihomoMemoryWs.onerror = (): void => { + if (mihomoMemoryWs) { + mihomoMemoryWs.close() + mihomoMemoryWs = null + } + } +} + export const startMihomoLogs = (): void => { mihomoLogs() } diff --git a/src/main/index.ts b/src/main/index.ts index 41d06774..728ba3a1 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -8,7 +8,12 @@ import { createTray } from './core/tray' import { init } from './resolve/init' import { getAppConfig } from './config' import { join } from 'path' -import { startMihomoTraffic, stopMihomoTraffic } from './core/mihomoApi' +import { + startMihomoMemory, + startMihomoTraffic, + stopMihomoMemory, + stopMihomoTraffic +} from './core/mihomoApi' export let window: BrowserWindow | null = null @@ -93,10 +98,12 @@ function createWindow(): void { window.on('show', () => { startMihomoTraffic() + startMihomoMemory() }) window.on('close', (event) => { stopMihomoTraffic() + stopMihomoMemory() event.preventDefault() window?.hide() }) diff --git a/src/renderer/src/components/logs/log-item.tsx b/src/renderer/src/components/logs/log-item.tsx index d8e85562..76120cb1 100644 --- a/src/renderer/src/components/logs/log-item.tsx +++ b/src/renderer/src/components/logs/log-item.tsx @@ -3,7 +3,7 @@ import React from 'react' const colorMap = { error: 'danger', - warn: 'warning', + warning: 'warning', info: 'primary', debug: 'default' } diff --git a/src/renderer/src/components/sider/mihomo-core-card.tsx.tsx b/src/renderer/src/components/sider/mihomo-core-card.tsx.tsx index 069b7f92..62277326 100644 --- a/src/renderer/src/components/sider/mihomo-core-card.tsx.tsx +++ b/src/renderer/src/components/sider/mihomo-core-card.tsx.tsx @@ -1,31 +1,28 @@ -import { - Button, - Card, - CardBody, - CardFooter, - Dropdown, - DropdownItem, - DropdownMenu, - DropdownTrigger -} from '@nextui-org/react' -import { useAppConfig } from '@renderer/hooks/use-config' +import { Button, Card, CardBody, CardFooter } from '@nextui-org/react' +import { calcTraffic } from '@renderer/utils/calc' import { mihomoVersion, restartCore } from '@renderer/utils/ipc' +import { useEffect, useState } from 'react' import { IoMdRefresh } from 'react-icons/io' import { useLocation, useNavigate } from 'react-router-dom' import useSWR from 'swr' -const CoreMap = { - mihomo: '稳定版', - 'mihomo-alpha': '预览版' -} - const MihomoCoreCard: React.FC = () => { - const { data: version, mutate } = useSWR('mihomoVersion', mihomoVersion) - const { appConfig, patchAppConfig } = useAppConfig() - const { core } = appConfig || {} + const { data: version } = useSWR('mihomoVersion', mihomoVersion) const navigate = useNavigate() const location = useLocation() const match = location.pathname.includes('/mihomo') + + const [mem, setMem] = useState(0) + + useEffect(() => { + window.electron.ipcRenderer.on('mihomoMemory', (_e, info: IMihomoMemoryInfo) => { + setMem(info.inuse) + }) + return (): void => { + window.electron.ipcRenderer.removeAllListeners('mihomoMemory') + } + }, []) + return ( {

{version?.version ?? '-'}

+ - - { - await patchAppConfig({ core: key as 'mihomo' | 'mihomo-alpha' }) - await restartCore() - mutate() - setTimeout(() => { - mutate() - }, 200) - }} - > - {CoreMap['mihomo']} - {CoreMap['mihomo-alpha']} - - +
+

内核设置

+

{calcTraffic(mem)}

+
) diff --git a/src/renderer/src/pages/mihomo.tsx b/src/renderer/src/pages/mihomo.tsx index ececba40..4cdeadc5 100644 --- a/src/renderer/src/pages/mihomo.tsx +++ b/src/renderer/src/pages/mihomo.tsx @@ -1,40 +1,114 @@ -import { Input, Select, SelectItem, Switch } from '@nextui-org/react' +import { Button, Input, Select, SelectItem, Switch } from '@nextui-org/react' import BasePage from '@renderer/components/base/base-page' import SettingCard from '@renderer/components/base/base-setting-card' import SettingItem from '@renderer/components/base/base-setting-item' import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config' -import { patchMihomoConfig } from '@renderer/utils/ipc' -import React from 'react' +import { patchMihomoConfig, restartCore } from '@renderer/utils/ipc' +import React, { useState } from 'react' const Mihomo: React.FC = () => { const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig() const { ipv6, + 'external-controller': externalController, + secret, 'log-level': level = 'info', 'allow-lan': lan, 'mixed-port': mixedPort = 7890 } = controledMihomoConfig || {} + const [mixedPortInput, setMixedPortInput] = useState(mixedPort) + const [externalControllerInput, setExternalControllerInput] = useState(externalController) + const [secretInput, setSecretInput] = useState(secret) + const onChange = async (patch: Partial): Promise => { await patchControledMihomoConfig(patch) await patchMihomoConfig(patch) } + const onChangeNeedRestart = async (patch: Partial): Promise => { + await patchControledMihomoConfig(patch) + await restartCore() + } + return ( - { - onChange({ 'mixed-port': parseInt(v) }) - }} - /> +
+ {mixedPortInput !== mixedPort && ( + + )} + + { + setMixedPortInput(parseInt(v)) + }} + /> +
+
+ +
+ {externalControllerInput !== externalController && ( + + )} + + { + setExternalControllerInput(v) + }} + /> +
+
+ +
+ {secretInput !== secret && ( + + )} + + { + setSecretInput(v) + }} + /> +