mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 11:42:19 +08:00
proxies page
This commit is contained in:
parent
deeaa5933d
commit
ba9c9ba84d
|
@ -30,6 +30,7 @@
|
|||
"react-icons": "^5.2.1",
|
||||
"react-monaco-editor": "^0.55.0",
|
||||
"react-router-dom": "^6.25.1",
|
||||
"react-virtuoso": "^4.9.0",
|
||||
"swr": "^2.2.5",
|
||||
"ws": "^8.18.0",
|
||||
"yaml": "^2.5.0"
|
||||
|
|
|
@ -41,6 +41,9 @@ importers:
|
|||
react-router-dom:
|
||||
specifier: ^6.25.1
|
||||
version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react-virtuoso:
|
||||
specifier: ^4.9.0
|
||||
version: 4.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
swr:
|
||||
specifier: ^2.2.5
|
||||
version: 2.2.5(react@18.3.1)
|
||||
|
@ -3669,6 +3672,13 @@ packages:
|
|||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
|
||||
react-virtuoso@4.9.0:
|
||||
resolution: {integrity: sha512-MiiSGKqvYPfAK3FUe852n2L3M5IXMKP0pUgYQ/UTk90A/l2UNQOvaEUvAZp+0ytL0kOCNk8i8/J8FMKvIq7kqg==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
react: '>=16 || >=17 || >= 18'
|
||||
react-dom: '>=16 || >=17 || >= 18'
|
||||
|
||||
react@18.3.1:
|
||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -9000,6 +9010,11 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
react-virtuoso@4.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
react@18.3.1:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
|
|
@ -49,6 +49,16 @@ export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
|
|||
return instance.get('/rules') as Promise<IMihomoRulesInfo>
|
||||
}
|
||||
|
||||
export const mihomoProxies = async (): Promise<IMihomoProxies> => {
|
||||
const instance = await getAxios()
|
||||
return instance.get('/proxies') as Promise<IMihomoProxies>
|
||||
}
|
||||
|
||||
export const mihomoChangeProxy = async (group: string, proxy: string): Promise<IMihomoProxy> => {
|
||||
const instance = await getAxios()
|
||||
return instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy })
|
||||
}
|
||||
|
||||
export const startMihomoTraffic = (): void => {
|
||||
mihomoTraffic()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { ipcMain } from 'electron'
|
||||
import {
|
||||
mihomoChangeProxy,
|
||||
mihomoConfig,
|
||||
mihomoConnections,
|
||||
mihomoProxies,
|
||||
mihomoRules,
|
||||
mihomoVersion,
|
||||
patchMihomoConfig,
|
||||
|
@ -29,6 +31,8 @@ export function registerIpcMainHandlers(): void {
|
|||
ipcMain.handle('mihomoConfig', mihomoConfig)
|
||||
ipcMain.handle('mihomoConnections', mihomoConnections)
|
||||
ipcMain.handle('mihomoRules', mihomoRules)
|
||||
ipcMain.handle('mihomoProxies', () => mihomoProxies())
|
||||
ipcMain.handle('mihomoChangeProxy', (_e, group, proxy) => mihomoChangeProxy(group, proxy))
|
||||
ipcMain.handle('startMihomoLogs', startMihomoLogs)
|
||||
ipcMain.handle('stopMihomoLogs', () => stopMihomoLogs())
|
||||
ipcMain.handle('patchMihomoConfig', async (_e, patch) => await patchMihomoConfig(patch))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src *"
|
||||
/>
|
||||
</head>
|
||||
|
||||
|
|
33
src/renderer/src/components/proxies/proxy-item.tsx
Normal file
33
src/renderer/src/components/proxies/proxy-item.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { Card, CardBody, Divider } from '@nextui-org/react'
|
||||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
proxy: IMihomoProxy | IMihomoGroup
|
||||
onSelect: (proxy: string) => void
|
||||
selected: boolean
|
||||
}
|
||||
|
||||
const ProxyItem: React.FC<Props> = (props) => {
|
||||
const { proxy, selected, onSelect } = props
|
||||
return (
|
||||
<>
|
||||
<Divider />
|
||||
<Card
|
||||
onPress={() => onSelect(proxy.name)}
|
||||
isPressable
|
||||
fullWidth
|
||||
className={`my-1 ${selected ? 'bg-primary' : ''}`}
|
||||
radius="sm"
|
||||
>
|
||||
<CardBody className="p-1">
|
||||
<div className="flex justify-between items-center">
|
||||
<div>{proxy.name}</div>
|
||||
<div className="mx-2 text-sm">{proxy.history.length > 0 && proxy.history[0].delay}</div>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProxyItem
|
30
src/renderer/src/components/proxies/proxy-list.tsx
Normal file
30
src/renderer/src/components/proxies/proxy-list.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React from 'react'
|
||||
import { Virtuoso } from 'react-virtuoso'
|
||||
import ProxyItem from './proxy-item'
|
||||
|
||||
interface Props {
|
||||
onChangeProxy: (proxy: string) => void
|
||||
proxies: (IMihomoProxy | IMihomoGroup)[]
|
||||
now: string
|
||||
}
|
||||
|
||||
const ProxyList: React.FC<Props> = (props) => {
|
||||
const { onChangeProxy, proxies, now } = props
|
||||
|
||||
return (
|
||||
<Virtuoso
|
||||
style={{ height: `min(calc(100vh - 200px), ${proxies.length * 44}px)` }}
|
||||
totalCount={proxies.length}
|
||||
increaseViewportBy={100}
|
||||
itemContent={(index) => (
|
||||
<ProxyItem
|
||||
onSelect={onChangeProxy}
|
||||
proxy={proxies[index]}
|
||||
selected={proxies[index].name === now}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProxyList
|
|
@ -1,7 +1,80 @@
|
|||
import { Accordion, AccordionItem, Avatar } from '@nextui-org/react'
|
||||
import BasePage from '@renderer/components/base/base-page'
|
||||
import ProxyList from '@renderer/components/proxies/proxy-list'
|
||||
import { mihomoChangeProxy, mihomoProxies } from '@renderer/utils/ipc'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import useSWR from 'swr'
|
||||
|
||||
const Proxies: React.FC = () => {
|
||||
return <BasePage title="代理组"></BasePage>
|
||||
const { data: proxies, mutate } = useSWR('mihomoProxies', mihomoProxies)
|
||||
|
||||
const groups = useMemo(() => {
|
||||
const groups: IMihomoGroup[] = []
|
||||
if (proxies) {
|
||||
const globalGroup = proxies.proxies['GLOBAL'] as IMihomoGroup
|
||||
for (const global of globalGroup.all) {
|
||||
if (isGroup(proxies.proxies[global])) {
|
||||
groups.push(proxies.proxies[global] as IMihomoGroup)
|
||||
}
|
||||
}
|
||||
Object.keys(proxies.proxies).forEach((key) => {
|
||||
if (isGroup(proxies.proxies[key])) {
|
||||
if (!groups.find((group) => group.name === key)) {
|
||||
groups.push(proxies.proxies[key] as IMihomoGroup)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return groups
|
||||
}, [proxies])
|
||||
|
||||
const groupProxies = useMemo(() => {
|
||||
const groupProxies: Record<string, (IMihomoProxy | IMihomoGroup)[]> = {}
|
||||
if (proxies) {
|
||||
for (const group of groups) {
|
||||
groupProxies[group.name] = group.all.map((name) => proxies.proxies[name])
|
||||
}
|
||||
}
|
||||
return groupProxies
|
||||
}, [proxies])
|
||||
|
||||
const onChangeProxy = (group: string, proxy: string): void => {
|
||||
mihomoChangeProxy(group, proxy).then(() => {
|
||||
mutate()
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {}, [])
|
||||
return (
|
||||
<BasePage title="代理组">
|
||||
<Accordion variant="splitted" className="p-2">
|
||||
{groups.map((group) => {
|
||||
return (
|
||||
<AccordionItem
|
||||
key={group.name}
|
||||
title={group.name}
|
||||
classNames={{ content: 'p-0' }}
|
||||
startContent={
|
||||
group.icon.length > 0 ? (
|
||||
<Avatar className="bg-transparent" size="sm" radius="sm" src={group.icon} />
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<ProxyList
|
||||
onChangeProxy={(proxy) => onChangeProxy(group.name, proxy)}
|
||||
proxies={groupProxies[group.name]}
|
||||
now={group.now}
|
||||
/>
|
||||
</AccordionItem>
|
||||
)
|
||||
})}
|
||||
</Accordion>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
||||
|
||||
function isGroup(proxy: IMihomoProxy | IMihomoGroup): proxy is IMihomoGroup {
|
||||
return 'all' in proxy
|
||||
}
|
||||
|
||||
export default Proxies
|
||||
|
|
|
@ -13,6 +13,15 @@ export async function mihomoConnections(): Promise<IMihomoConnectionsInfo> {
|
|||
export async function mihomoRules(): Promise<IMihomoRulesInfo> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoRules')
|
||||
}
|
||||
|
||||
export async function mihomoProxies(): Promise<IMihomoProxies> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoProxies')
|
||||
}
|
||||
|
||||
export async function mihomoChangeProxy(group: string, proxy: string): Promise<IMihomoProxy> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoChangeProxy', group, proxy)
|
||||
}
|
||||
|
||||
export async function startMihomoLogs(): Promise<void> {
|
||||
return await window.electron.ipcRenderer.invoke('startMihomoLogs')
|
||||
}
|
||||
|
|
39
src/shared/types.d.ts
vendored
39
src/shared/types.d.ts
vendored
|
@ -1,6 +1,9 @@
|
|||
type OutboundMode = 'rule' | 'global' | 'direct'
|
||||
type LogLevel = 'info' | 'debug' | 'warning' | 'error' | 'silent'
|
||||
type SysProxyMode = 'auto' | 'manual'
|
||||
type MihomoGroupType = 'Selector'
|
||||
type MihomoProxyType = 'Shadowsocks'
|
||||
|
||||
interface IMihomoVersion {
|
||||
version: string
|
||||
meta: boolean
|
||||
|
@ -69,6 +72,42 @@ interface IMihomoConnectionDetail {
|
|||
rulePayload: string
|
||||
}
|
||||
|
||||
interface IMihomoHistory {
|
||||
time: string
|
||||
delay: number
|
||||
}
|
||||
|
||||
interface IMihomoProxy {
|
||||
alive: boolean
|
||||
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
||||
history: IMihomoHistory[]
|
||||
id: string
|
||||
name: string
|
||||
tfo: boolean
|
||||
type: MihomoProxyType
|
||||
udp: boolean
|
||||
xudp: boolean
|
||||
}
|
||||
|
||||
interface IMihomoGroup {
|
||||
alive: boolean
|
||||
all: string[]
|
||||
extra: Record<string, { alive: boolean; history: IMihomoHistory[] }>
|
||||
hidden: boolean
|
||||
history: IMihomoHistory[]
|
||||
icon: string
|
||||
name: string
|
||||
now: string
|
||||
tfo: boolean
|
||||
type: MihomoGroupType
|
||||
udp: boolean
|
||||
xudp: boolean
|
||||
}
|
||||
|
||||
interface IMihomoProxies {
|
||||
proxies: Record<string, IMihomoProxy | IMihomoGroup>
|
||||
}
|
||||
|
||||
interface ISysProxyConfig {
|
||||
enable: boolean
|
||||
host?: string
|
||||
|
|
Loading…
Reference in New Issue
Block a user