mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
proxy delay
This commit is contained in:
parent
ba9c9ba84d
commit
0fc43b339d
@ -27,6 +27,7 @@
|
|||||||
"electron-updater": "^6.2.1",
|
"electron-updater": "^6.2.1",
|
||||||
"framer-motion": "^11.3.19",
|
"framer-motion": "^11.3.19",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
|
"pubsub-js": "^1.9.4",
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.2.1",
|
||||||
"react-monaco-editor": "^0.55.0",
|
"react-monaco-editor": "^0.55.0",
|
||||||
"react-router-dom": "^6.25.1",
|
"react-router-dom": "^6.25.1",
|
||||||
@ -40,6 +41,7 @@
|
|||||||
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
||||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
|
"@types/pubsub-js": "^1.8.6",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.12",
|
||||||
|
|||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@ -32,6 +32,9 @@ importers:
|
|||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.3.0
|
specifier: ^0.3.0
|
||||||
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
pubsub-js:
|
||||||
|
specifier: ^1.9.4
|
||||||
|
version: 1.9.4
|
||||||
react-icons:
|
react-icons:
|
||||||
specifier: ^5.2.1
|
specifier: ^5.2.1
|
||||||
version: 5.2.1(react@18.3.1)
|
version: 5.2.1(react@18.3.1)
|
||||||
@ -66,6 +69,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.0.0
|
specifier: ^22.0.0
|
||||||
version: 22.0.0
|
version: 22.0.0
|
||||||
|
'@types/pubsub-js':
|
||||||
|
specifier: ^1.8.6
|
||||||
|
version: 1.8.6
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.3.3
|
specifier: ^18.3.3
|
||||||
version: 18.3.3
|
version: 18.3.3
|
||||||
@ -1795,6 +1801,9 @@ packages:
|
|||||||
'@types/prop-types@15.7.12':
|
'@types/prop-types@15.7.12':
|
||||||
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
||||||
|
|
||||||
|
'@types/pubsub-js@1.8.6':
|
||||||
|
resolution: {integrity: sha512-Kwug5cwV0paUDm/NfwDx1sp9xI0bGIvmWJjJWCU8NngkCCMt3EIC7oPDvb6fV7BR8kPpFyyBu4D11bda/2MdPA==}
|
||||||
|
|
||||||
'@types/react-dom@18.3.0':
|
'@types/react-dom@18.3.0':
|
||||||
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
||||||
|
|
||||||
@ -3585,6 +3594,9 @@ packages:
|
|||||||
proxy-from-env@1.1.0:
|
proxy-from-env@1.1.0:
|
||||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||||
|
|
||||||
|
pubsub-js@1.9.4:
|
||||||
|
resolution: {integrity: sha512-hJYpaDvPH4w8ZX/0Fdf9ma1AwRgU353GfbaVfPjfJQf1KxZ2iHaHl3fAUw1qlJIR5dr4F3RzjGaWohYUEyoh7A==}
|
||||||
|
|
||||||
pump@3.0.0:
|
pump@3.0.0:
|
||||||
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
|
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
|
||||||
|
|
||||||
@ -6848,6 +6860,8 @@ snapshots:
|
|||||||
|
|
||||||
'@types/prop-types@15.7.12': {}
|
'@types/prop-types@15.7.12': {}
|
||||||
|
|
||||||
|
'@types/pubsub-js@1.8.6': {}
|
||||||
|
|
||||||
'@types/react-dom@18.3.0':
|
'@types/react-dom@18.3.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
@ -8929,6 +8943,8 @@ snapshots:
|
|||||||
|
|
||||||
proxy-from-env@1.1.0: {}
|
proxy-from-env@1.1.0: {}
|
||||||
|
|
||||||
|
pubsub-js@1.9.4: {}
|
||||||
|
|
||||||
pump@3.0.0:
|
pump@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
end-of-stream: 1.4.4
|
end-of-stream: 1.4.4
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import axios, { AxiosInstance } from 'axios'
|
import axios, { AxiosInstance } from 'axios'
|
||||||
import { getControledMihomoConfig } from '../config'
|
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||||
import WebSocket from 'ws'
|
import WebSocket from 'ws'
|
||||||
import { window } from '..'
|
import { window } from '..'
|
||||||
|
|
||||||
@ -59,6 +59,19 @@ export const mihomoChangeProxy = async (group: string, proxy: string): Promise<I
|
|||||||
return instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy })
|
return instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const mihomoProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
|
||||||
|
const appConfig = getAppConfig()
|
||||||
|
const { delayTestUrl, delayTestTimeout } = appConfig
|
||||||
|
const instance = await getAxios()
|
||||||
|
return instance.get(`/proxies/${encodeURIComponent(proxy)}/delay`, {
|
||||||
|
params: {
|
||||||
|
url: url || delayTestUrl || 'https://www.gstatic.com/generate_204',
|
||||||
|
timeout: delayTestTimeout || 5000
|
||||||
|
},
|
||||||
|
timeout: delayTestTimeout || 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const startMihomoTraffic = (): void => {
|
export const startMihomoTraffic = (): void => {
|
||||||
mihomoTraffic()
|
mihomoTraffic()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
mihomoConfig,
|
mihomoConfig,
|
||||||
mihomoConnections,
|
mihomoConnections,
|
||||||
mihomoProxies,
|
mihomoProxies,
|
||||||
|
mihomoProxyDelay,
|
||||||
mihomoRules,
|
mihomoRules,
|
||||||
mihomoVersion,
|
mihomoVersion,
|
||||||
patchMihomoConfig,
|
patchMihomoConfig,
|
||||||
@ -33,6 +34,7 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('mihomoRules', mihomoRules)
|
ipcMain.handle('mihomoRules', mihomoRules)
|
||||||
ipcMain.handle('mihomoProxies', () => mihomoProxies())
|
ipcMain.handle('mihomoProxies', () => mihomoProxies())
|
||||||
ipcMain.handle('mihomoChangeProxy', (_e, group, proxy) => mihomoChangeProxy(group, proxy))
|
ipcMain.handle('mihomoChangeProxy', (_e, group, proxy) => mihomoChangeProxy(group, proxy))
|
||||||
|
ipcMain.handle('mihomoProxyDelay', (_e, proxy, url) => mihomoProxyDelay(proxy, url))
|
||||||
ipcMain.handle('startMihomoLogs', startMihomoLogs)
|
ipcMain.handle('startMihomoLogs', startMihomoLogs)
|
||||||
ipcMain.handle('stopMihomoLogs', () => stopMihomoLogs())
|
ipcMain.handle('stopMihomoLogs', () => stopMihomoLogs())
|
||||||
ipcMain.handle('patchMihomoConfig', async (_e, patch) => await patchMihomoConfig(patch))
|
ipcMain.handle('patchMihomoConfig', async (_e, patch) => await patchMihomoConfig(patch))
|
||||||
|
|||||||
@ -1,14 +1,65 @@
|
|||||||
import { Card, CardBody, Divider } from '@nextui-org/react'
|
import { Button, Card, CardBody, Divider } from '@nextui-org/react'
|
||||||
import React from 'react'
|
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||||
|
import PubSub from 'pubsub-js'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
onProxyDelay: (proxy: string) => Promise<IMihomoDelay>
|
||||||
|
proxyDisplayMode: 'simple' | 'full'
|
||||||
proxy: IMihomoProxy | IMihomoGroup
|
proxy: IMihomoProxy | IMihomoGroup
|
||||||
|
group: string
|
||||||
onSelect: (proxy: string) => void
|
onSelect: (proxy: string) => void
|
||||||
selected: boolean
|
selected: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProxyItem: React.FC<Props> = (props) => {
|
const ProxyItem: React.FC<Props> = (props) => {
|
||||||
const { proxy, selected, onSelect } = props
|
const { proxyDisplayMode, group, proxy, selected, onSelect, onProxyDelay } = props
|
||||||
|
const { appConfig } = useAppConfig()
|
||||||
|
const { delayTestTimeout = 5000 } = appConfig || {}
|
||||||
|
const [delay, setDelay] = useState(() => {
|
||||||
|
if (proxy.history.length > 0) {
|
||||||
|
return proxy.history[0].delay
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
function delayColor(delay: number): 'primary' | 'success' | 'warning' | 'danger' {
|
||||||
|
if (delay < 0) return 'danger'
|
||||||
|
if (delay === 0) return 'primary'
|
||||||
|
if (delay < 500) return 'success'
|
||||||
|
if (delay < delayTestTimeout) return 'warning'
|
||||||
|
return 'danger'
|
||||||
|
}
|
||||||
|
|
||||||
|
function delayText(delay: number): string {
|
||||||
|
if (delay < 0) return 'Error'
|
||||||
|
if (delay === 0) return 'Delay'
|
||||||
|
if (delay < delayTestTimeout) return delay.toString()
|
||||||
|
return 'Timeout'
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelay = (): void => {
|
||||||
|
setLoading(true)
|
||||||
|
onProxyDelay(proxy.name).then(
|
||||||
|
(delay) => {
|
||||||
|
setDelay(delay.delay || delayTestTimeout + 1)
|
||||||
|
setLoading(false)
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
setDelay(-1)
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const token = PubSub.subscribe(`${group}-delay`, onDelay)
|
||||||
|
|
||||||
|
return (): void => {
|
||||||
|
PubSub.unsubscribe(token)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
@ -16,13 +67,26 @@ const ProxyItem: React.FC<Props> = (props) => {
|
|||||||
onPress={() => onSelect(proxy.name)}
|
onPress={() => onSelect(proxy.name)}
|
||||||
isPressable
|
isPressable
|
||||||
fullWidth
|
fullWidth
|
||||||
className={`my-1 ${selected ? 'bg-primary' : ''}`}
|
className={`my-1 ${selected ? 'bg-primary/30' : ''}`}
|
||||||
radius="sm"
|
radius="sm"
|
||||||
>
|
>
|
||||||
<CardBody className="p-1">
|
<CardBody className="p-1">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div>{proxy.name}</div>
|
<div>
|
||||||
<div className="mx-2 text-sm">{proxy.history.length > 0 && proxy.history[0].delay}</div>
|
<div className="inline">{proxy.name}</div>
|
||||||
|
{proxyDisplayMode === 'full' && (
|
||||||
|
<div className="inline ml-2 text-default-500">{proxy.type}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
isLoading={loading}
|
||||||
|
color={delayColor(delay)}
|
||||||
|
onPress={onDelay}
|
||||||
|
variant="light"
|
||||||
|
className="h-full min-w-[50px] p-0 mx-2 text-sm hover:bg-content"
|
||||||
|
>
|
||||||
|
{delayText(delay)}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -3,13 +3,16 @@ import { Virtuoso } from 'react-virtuoso'
|
|||||||
import ProxyItem from './proxy-item'
|
import ProxyItem from './proxy-item'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
onProxyDelay: (proxy: string) => Promise<IMihomoDelay>
|
||||||
onChangeProxy: (proxy: string) => void
|
onChangeProxy: (proxy: string) => void
|
||||||
|
proxyDisplayMode: 'simple' | 'full'
|
||||||
proxies: (IMihomoProxy | IMihomoGroup)[]
|
proxies: (IMihomoProxy | IMihomoGroup)[]
|
||||||
|
group: string
|
||||||
now: string
|
now: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProxyList: React.FC<Props> = (props) => {
|
const ProxyList: React.FC<Props> = (props) => {
|
||||||
const { onChangeProxy, proxies, now } = props
|
const { proxyDisplayMode, onProxyDelay, onChangeProxy, proxies, group, now } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
@ -18,8 +21,11 @@ const ProxyList: React.FC<Props> = (props) => {
|
|||||||
increaseViewportBy={100}
|
increaseViewportBy={100}
|
||||||
itemContent={(index) => (
|
itemContent={(index) => (
|
||||||
<ProxyItem
|
<ProxyItem
|
||||||
|
onProxyDelay={onProxyDelay}
|
||||||
onSelect={onChangeProxy}
|
onSelect={onChangeProxy}
|
||||||
proxy={proxies[index]}
|
proxy={proxies[index]}
|
||||||
|
group={group}
|
||||||
|
proxyDisplayMode={proxyDisplayMode}
|
||||||
selected={proxies[index].name === now}
|
selected={proxies[index].name === now}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
|
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
|
||||||
import { SiSpeedtest } from 'react-icons/si'
|
import { mihomoProxies } from '@renderer/utils/ipc'
|
||||||
|
import { SiNginxproxymanager } from 'react-icons/si'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
const ProxyCard: React.FC = () => {
|
const ProxyCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const match = location.pathname.includes('/proxies')
|
const match = location.pathname.includes('/proxies')
|
||||||
|
const { data: proxies = { proxies: {} } } = useSWR('mihomoProxies', mihomoProxies)
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
fullWidth
|
fullWidth
|
||||||
@ -13,16 +16,38 @@ const ProxyCard: React.FC = () => {
|
|||||||
isPressable
|
isPressable
|
||||||
onPress={() => navigate('/proxies')}
|
onPress={() => navigate('/proxies')}
|
||||||
>
|
>
|
||||||
<CardBody>
|
<CardBody className="pb-1 pt-0 px-0">
|
||||||
<div className="flex justify-between h-[32px]">
|
<div className="flex justify-between">
|
||||||
<h3 className="select-none text-md font-bold leading-[32px]">节点名称</h3>
|
<Button
|
||||||
<Button isIconOnly size="sm" variant="light" color="default">
|
isIconOnly
|
||||||
<SiSpeedtest color="default" className="text-[20px]" />
|
className="bg-transparent pointer-events-none"
|
||||||
|
variant="flat"
|
||||||
|
color="default"
|
||||||
|
>
|
||||||
|
<SiNginxproxymanager color="default" className="text-[20px]" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Chip
|
||||||
|
classNames={
|
||||||
|
match
|
||||||
|
? {
|
||||||
|
base: 'border-foreground',
|
||||||
|
content: 'text-foreground'
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
base: 'border-primary',
|
||||||
|
content: 'text-primary'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size="sm"
|
||||||
|
variant="bordered"
|
||||||
|
className="mr-3 mt-2"
|
||||||
|
>
|
||||||
|
{Object.keys(proxies.proxies).length ?? 0}
|
||||||
|
</Chip>
|
||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
<CardFooter className="pt-1">
|
<CardFooter className="pt-1">
|
||||||
<small>二级节点</small>
|
<h3 className="select-none text-md font-bold">代理组</h3>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
import { Accordion, AccordionItem, Avatar } from '@nextui-org/react'
|
import { Accordion, AccordionItem, Avatar, Button } from '@nextui-org/react'
|
||||||
import BasePage from '@renderer/components/base/base-page'
|
import BasePage from '@renderer/components/base/base-page'
|
||||||
import ProxyList from '@renderer/components/proxies/proxy-list'
|
import ProxyList from '@renderer/components/proxies/proxy-list'
|
||||||
import { mihomoChangeProxy, mihomoProxies } from '@renderer/utils/ipc'
|
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||||
|
import { MdOutlineSpeed } from 'react-icons/md'
|
||||||
|
import { mihomoChangeProxy, mihomoProxies, mihomoProxyDelay } from '@renderer/utils/ipc'
|
||||||
|
import { CgDetailsLess, CgDetailsMore } from 'react-icons/cg'
|
||||||
import { useEffect, useMemo } from 'react'
|
import { useEffect, useMemo } from 'react'
|
||||||
|
import PubSub from 'pubsub-js'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
const Proxies: React.FC = () => {
|
const Proxies: React.FC = () => {
|
||||||
const { data: proxies, mutate } = useSWR('mihomoProxies', mihomoProxies)
|
const { data: proxies, mutate } = useSWR('mihomoProxies', mihomoProxies)
|
||||||
|
const { appConfig, patchAppConfig } = useAppConfig()
|
||||||
|
const { proxyDisplayMode = 'simple' } = appConfig || {}
|
||||||
|
|
||||||
const groups = useMemo(() => {
|
const groups = useMemo(() => {
|
||||||
const groups: IMihomoGroup[] = []
|
const groups: IMihomoGroup[] = []
|
||||||
@ -44,16 +50,60 @@ const Proxies: React.FC = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
|
||||||
|
return await mihomoProxyDelay(proxy, url)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {}, [])
|
useEffect(() => {}, [])
|
||||||
return (
|
return (
|
||||||
<BasePage title="代理组">
|
<BasePage
|
||||||
|
title="代理组"
|
||||||
|
header={
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
isIconOnly
|
||||||
|
onPress={() => {
|
||||||
|
patchAppConfig({ proxyDisplayMode: proxyDisplayMode === 'simple' ? 'full' : 'simple' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{proxyDisplayMode === 'simple' ? (
|
||||||
|
<CgDetailsMore size={20} />
|
||||||
|
) : (
|
||||||
|
<CgDetailsLess size={20} />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Accordion variant="splitted" className="p-2">
|
<Accordion variant="splitted" className="p-2">
|
||||||
{groups.map((group) => {
|
{groups.map((group) => {
|
||||||
return (
|
return (
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
key={group.name}
|
key={group.name}
|
||||||
title={group.name}
|
title={
|
||||||
classNames={{ content: 'p-0' }}
|
<div className="flex justify-between">
|
||||||
|
<div>{group.name}</div>
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
size="sm"
|
||||||
|
isIconOnly
|
||||||
|
onPress={() => {
|
||||||
|
PubSub.publish(`${group.name}-delay`)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdOutlineSpeed className="text-lg text-default-500" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
subtitle={
|
||||||
|
proxyDisplayMode === 'full' && (
|
||||||
|
<div>
|
||||||
|
{group.type}
|
||||||
|
|
||||||
|
{group.now}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
classNames={{ title: 'select-none', base: 'px-2', content: 'pt-2', trigger: 'py-2' }}
|
||||||
startContent={
|
startContent={
|
||||||
group.icon.length > 0 ? (
|
group.icon.length > 0 ? (
|
||||||
<Avatar className="bg-transparent" size="sm" radius="sm" src={group.icon} />
|
<Avatar className="bg-transparent" size="sm" radius="sm" src={group.icon} />
|
||||||
@ -61,8 +111,11 @@ const Proxies: React.FC = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ProxyList
|
<ProxyList
|
||||||
|
onProxyDelay={(proxy) => onProxyDelay(proxy, group.testUrl)}
|
||||||
onChangeProxy={(proxy) => onChangeProxy(group.name, proxy)}
|
onChangeProxy={(proxy) => onChangeProxy(group.name, proxy)}
|
||||||
|
proxyDisplayMode={proxyDisplayMode}
|
||||||
proxies={groupProxies[group.name]}
|
proxies={groupProxies[group.name]}
|
||||||
|
group={group.name}
|
||||||
now={group.now}
|
now={group.now}
|
||||||
/>
|
/>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Button, Switch } from '@nextui-org/react'
|
import { Button, Input, Switch } from '@nextui-org/react'
|
||||||
import BasePage from '@renderer/components/base/base-page'
|
import BasePage from '@renderer/components/base/base-page'
|
||||||
import SettingCard from '@renderer/components/base/base-setting-card'
|
import SettingCard from '@renderer/components/base/base-setting-card'
|
||||||
import SettingItem from '@renderer/components/base/base-setting-item'
|
import SettingItem from '@renderer/components/base/base-setting-item'
|
||||||
@ -15,7 +15,7 @@ const Settings: React.FC = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { appConfig, patchAppConfig } = useAppConfig()
|
const { appConfig, patchAppConfig } = useAppConfig()
|
||||||
const { silentStart = false } = appConfig || {}
|
const { silentStart = false, delayTestUrl, delayTestTimeout } = appConfig || {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BasePage
|
<BasePage
|
||||||
@ -57,6 +57,32 @@ const Settings: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
</SettingCard>
|
</SettingCard>
|
||||||
|
<SettingCard>
|
||||||
|
<SettingItem title="延迟测试地址" divider>
|
||||||
|
<Input
|
||||||
|
size="sm"
|
||||||
|
className="w-[60%]"
|
||||||
|
spellCheck={false}
|
||||||
|
value={delayTestUrl}
|
||||||
|
placeholder="默认https://www.gstatic.com/generate_204"
|
||||||
|
onValueChange={(v) => {
|
||||||
|
patchAppConfig({ delayTestUrl: v })
|
||||||
|
}}
|
||||||
|
></Input>
|
||||||
|
</SettingItem>
|
||||||
|
<SettingItem title="延迟测试超时时间">
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
size="sm"
|
||||||
|
className="w-[60%]"
|
||||||
|
value={delayTestTimeout?.toString()}
|
||||||
|
placeholder="默认5000"
|
||||||
|
onValueChange={(v) => {
|
||||||
|
patchAppConfig({ delayTestTimeout: parseInt(v) })
|
||||||
|
}}
|
||||||
|
></Input>
|
||||||
|
</SettingItem>
|
||||||
|
</SettingCard>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,7 @@ const Sysproxy: React.FC = () => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
className="w-[50%]"
|
className="w-[50%]"
|
||||||
value={values.host}
|
value={values.host}
|
||||||
|
spellCheck={false}
|
||||||
placeholder="默认127.0.0.1若无特殊需求请勿修改"
|
placeholder="默认127.0.0.1若无特殊需求请勿修改"
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
setValues({ ...values, host: v })
|
setValues({ ...values, host: v })
|
||||||
|
|||||||
@ -22,6 +22,10 @@ export async function mihomoChangeProxy(group: string, proxy: string): Promise<I
|
|||||||
return await window.electron.ipcRenderer.invoke('mihomoChangeProxy', group, proxy)
|
return await window.electron.ipcRenderer.invoke('mihomoChangeProxy', group, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function mihomoProxyDelay(proxy: string, url?: string): Promise<IMihomoDelay> {
|
||||||
|
return await window.electron.ipcRenderer.invoke('mihomoProxyDelay', proxy, url)
|
||||||
|
}
|
||||||
|
|
||||||
export async function startMihomoLogs(): Promise<void> {
|
export async function startMihomoLogs(): Promise<void> {
|
||||||
return await window.electron.ipcRenderer.invoke('startMihomoLogs')
|
return await window.electron.ipcRenderer.invoke('startMihomoLogs')
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/shared/types.d.ts
vendored
9
src/shared/types.d.ts
vendored
@ -77,6 +77,11 @@ interface IMihomoHistory {
|
|||||||
delay: number
|
delay: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IMihomoDelay {
|
||||||
|
delay?: number
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
interface IMihomoProxy {
|
interface IMihomoProxy {
|
||||||
alive: boolean
|
alive: boolean
|
||||||
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
||||||
@ -93,6 +98,7 @@ interface IMihomoGroup {
|
|||||||
alive: boolean
|
alive: boolean
|
||||||
all: string[]
|
all: string[]
|
||||||
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
||||||
|
testUrl?: string
|
||||||
hidden: boolean
|
hidden: boolean
|
||||||
history: IMihomoHistory[]
|
history: IMihomoHistory[]
|
||||||
icon: string
|
icon: string
|
||||||
@ -118,9 +124,12 @@ interface ISysProxyConfig {
|
|||||||
|
|
||||||
interface IAppConfig {
|
interface IAppConfig {
|
||||||
core: 'mihomo' | 'mihomo-alpha'
|
core: 'mihomo' | 'mihomo-alpha'
|
||||||
|
proxyDisplayMode: 'simple' | 'full'
|
||||||
silentStart: boolean
|
silentStart: boolean
|
||||||
sysProxy: ISysProxyConfig
|
sysProxy: ISysProxyConfig
|
||||||
userAgent?: string
|
userAgent?: string
|
||||||
|
delayTestUrl?: string
|
||||||
|
delayTestTimeout?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMihomoTunConfig {
|
interface IMihomoTunConfig {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user