mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
memory and mihomo setting
This commit is contained in:
parent
e456259fcb
commit
5ece0adcd6
@ -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<IMihomoConfig> // mihomo.yaml
|
||||
|
||||
@ -13,5 +14,8 @@ export function getControledMihomoConfig(force = false): Partial<IMihomoConfig>
|
||||
|
||||
export function setControledMihomoConfig(patch: Partial<IMihomoConfig>): void {
|
||||
controledMihomoConfig = Object.assign(controledMihomoConfig, patch)
|
||||
if (patch['external-controller'] || patch.secret) {
|
||||
getAxios(true)
|
||||
}
|
||||
fs.writeFileSync(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig))
|
||||
}
|
||||
|
||||
@ -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<AxiosInstance> => {
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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()
|
||||
})
|
||||
|
||||
@ -3,7 +3,7 @@ import React from 'react'
|
||||
|
||||
const colorMap = {
|
||||
error: 'danger',
|
||||
warn: 'warning',
|
||||
warning: 'warning',
|
||||
info: 'primary',
|
||||
debug: 'default'
|
||||
}
|
||||
|
||||
@ -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 (
|
||||
<Card
|
||||
fullWidth
|
||||
@ -38,6 +35,7 @@ const MihomoCoreCard: React.FC = () => {
|
||||
<h3 className="select-none text-md font-bold leading-[32px]">
|
||||
{version?.version ?? '-'}
|
||||
</h3>
|
||||
|
||||
<Button
|
||||
isIconOnly
|
||||
size="sm"
|
||||
@ -52,26 +50,10 @@ const MihomoCoreCard: React.FC = () => {
|
||||
</div>
|
||||
</CardBody>
|
||||
<CardFooter className="pt-1">
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
<Button fullWidth size="sm" variant="solid">
|
||||
{core ? CoreMap[core] : ''}
|
||||
</Button>
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu
|
||||
onAction={async (key) => {
|
||||
await patchAppConfig({ core: key as 'mihomo' | 'mihomo-alpha' })
|
||||
await restartCore()
|
||||
mutate()
|
||||
setTimeout(() => {
|
||||
mutate()
|
||||
}, 200)
|
||||
}}
|
||||
>
|
||||
<DropdownItem key="mihomo">{CoreMap['mihomo']}</DropdownItem>
|
||||
<DropdownItem key="mihomo-alpha">{CoreMap['mihomo-alpha']}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<div className="flex justify-between w-full">
|
||||
<h4 className="select-none text-md font-bold">内核设置</h4>
|
||||
<h4 className="select-none text-md">{calcTraffic(mem)}</h4>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
|
||||
@ -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<IMihomoConfig>): Promise<void> => {
|
||||
await patchControledMihomoConfig(patch)
|
||||
await patchMihomoConfig(patch)
|
||||
}
|
||||
|
||||
const onChangeNeedRestart = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
||||
await patchControledMihomoConfig(patch)
|
||||
await restartCore()
|
||||
}
|
||||
|
||||
return (
|
||||
<BasePage title="内核设置">
|
||||
<SettingCard>
|
||||
<SettingItem title="混合端口" divider>
|
||||
<div className="flex">
|
||||
{mixedPortInput !== mixedPort && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
onChangeNeedRestart({ 'mixed-port': mixedPortInput })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Input
|
||||
size="sm"
|
||||
type="number"
|
||||
className="w-[100px]"
|
||||
value={mixedPort.toString()}
|
||||
value={mixedPortInput.toString()}
|
||||
max={65535}
|
||||
min={0}
|
||||
onValueChange={(v) => {
|
||||
onChange({ 'mixed-port': parseInt(v) })
|
||||
setMixedPortInput(parseInt(v))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="外部控制" divider>
|
||||
<div className="flex">
|
||||
{externalControllerInput !== externalController && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
onChangeNeedRestart({ 'external-controller': externalControllerInput })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Input
|
||||
size="sm"
|
||||
value={externalControllerInput}
|
||||
onValueChange={(v) => {
|
||||
setExternalControllerInput(v)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="外部控制访问密钥" divider>
|
||||
<div className="flex">
|
||||
{secretInput !== secret && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
onChangeNeedRestart({ secret: secretInput })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Input
|
||||
size="sm"
|
||||
value={secretInput}
|
||||
onValueChange={(v) => {
|
||||
setSecretInput(v)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="IPv6" divider>
|
||||
<Switch
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
export function calcTraffic(bit: number): string {
|
||||
if (bit < 1024) return `${bit} B`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} KB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} MB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} GB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} TB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} PB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} EB`
|
||||
bit /= 1024
|
||||
if (bit < 1024) return `${bit.toFixed(2)} ZB`
|
||||
bit /= 1024
|
||||
return `${bit.toFixed(2)} YB`
|
||||
export function calcTraffic(byte: number): string {
|
||||
if (byte < 1024) return `${byte} B`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} KB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} MB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} GB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} TB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} PB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} EB`
|
||||
byte /= 1024
|
||||
if (byte < 1024) return `${byte.toFixed(2)} ZB`
|
||||
byte /= 1024
|
||||
return `${byte.toFixed(2)} YB`
|
||||
}
|
||||
|
||||
export function calcPercent(
|
||||
|
||||
5
src/shared/types.d.ts
vendored
5
src/shared/types.d.ts
vendored
@ -14,6 +14,11 @@ interface IMihomoTrafficInfo {
|
||||
down: number
|
||||
}
|
||||
|
||||
interface IMihomoMemoryInfo {
|
||||
inuse: number
|
||||
oslimit: number
|
||||
}
|
||||
|
||||
interface IMihomoLogInfo {
|
||||
type: LogLevel
|
||||
payload: string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user