mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
support interfaces info
This commit is contained in:
parent
7b4d60e280
commit
4aeac0ebb3
@ -1,3 +1,4 @@
|
|||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- 添加覆写脚本执行日志功能
|
- 添加覆写脚本执行日志功能
|
||||||
|
- 支持查看局域网网络信息
|
||||||
|
|||||||
5
src/main/sys/interface.ts
Normal file
5
src/main/sys/interface.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import os from 'os'
|
||||||
|
|
||||||
|
export function getInterfaces(): NodeJS.Dict<NetworkInterfaceInfo[]> {
|
||||||
|
return os.networkInterfaces()
|
||||||
|
}
|
||||||
@ -51,6 +51,7 @@ import { getFilePath, openUWPTool, readTextFile, setupFirewall } from '../sys/mi
|
|||||||
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
||||||
import { isPortable, setPortable } from './dirs'
|
import { isPortable, setPortable } from './dirs'
|
||||||
import { listWebdavBackups, webdavBackup, webdavRestore } from '../resolve/backup'
|
import { listWebdavBackups, webdavBackup, webdavRestore } from '../resolve/backup'
|
||||||
|
import { getInterfaces } from '../sys/interface'
|
||||||
|
|
||||||
function ipcErrorWrapper<T>( // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
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
|
fn: (...args: any[]) => Promise<T> // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -139,6 +140,7 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('platform', () => process.platform)
|
ipcMain.handle('platform', () => process.platform)
|
||||||
ipcMain.handle('openUWPTool', ipcErrorWrapper(openUWPTool))
|
ipcMain.handle('openUWPTool', ipcErrorWrapper(openUWPTool))
|
||||||
ipcMain.handle('setupFirewall', ipcErrorWrapper(setupFirewall))
|
ipcMain.handle('setupFirewall', ipcErrorWrapper(setupFirewall))
|
||||||
|
ipcMain.handle('getInterfaces', getInterfaces)
|
||||||
ipcMain.handle('setPortable', (_e, portable) => ipcErrorWrapper(setPortable)(portable))
|
ipcMain.handle('setPortable', (_e, portable) => ipcErrorWrapper(setPortable)(portable))
|
||||||
ipcMain.handle('isPortable', isPortable)
|
ipcMain.handle('isPortable', isPortable)
|
||||||
ipcMain.handle('webdavBackup', ipcErrorWrapper(webdavBackup))
|
ipcMain.handle('webdavBackup', ipcErrorWrapper(webdavBackup))
|
||||||
|
|||||||
67
src/renderer/src/components/mihomo/interface-modal.tsx
Normal file
67
src/renderer/src/components/mihomo/interface-modal.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalBody,
|
||||||
|
ModalFooter,
|
||||||
|
Button,
|
||||||
|
Snippet
|
||||||
|
} from '@nextui-org/react'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInterfaces } from '@renderer/utils/ipc'
|
||||||
|
interface Props {
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
const InterfaceModal: React.FC<Props> = (props) => {
|
||||||
|
const { onClose } = props
|
||||||
|
const [info, setInfo] = useState<Record<string, NetworkInterfaceInfo[]>>({})
|
||||||
|
const getInfo = async (): Promise<void> => {
|
||||||
|
setInfo(await getInterfaces())
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getInfo()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
backdrop="blur"
|
||||||
|
hideCloseButton
|
||||||
|
isOpen={true}
|
||||||
|
onOpenChange={onClose}
|
||||||
|
scrollBehavior="inside"
|
||||||
|
>
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader className="flex">网络信息</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
{Object.entries(info).map(([key, value]) => {
|
||||||
|
return (
|
||||||
|
<div key={key}>
|
||||||
|
<h4 className="font-bold">{key}</h4>
|
||||||
|
{value.map((v) => {
|
||||||
|
return (
|
||||||
|
<div key={v.address}>
|
||||||
|
<div className="mt-2 flex justify-between">
|
||||||
|
{v.family}
|
||||||
|
<Snippet symbol="" size="sm">
|
||||||
|
{v.address}
|
||||||
|
</Snippet>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button variant="light" onPress={onClose}>
|
||||||
|
关闭
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InterfaceModal
|
||||||
@ -5,8 +5,10 @@ import SettingItem from '@renderer/components/base/base-setting-item'
|
|||||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||||
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
|
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
|
||||||
import { platform } from '@renderer/utils/init'
|
import { platform } from '@renderer/utils/init'
|
||||||
|
import { FaNetworkWired } from 'react-icons/fa'
|
||||||
import { restartCore } from '@renderer/utils/ipc'
|
import { restartCore } from '@renderer/utils/ipc'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
import InterfaceModal from '@renderer/components/mihomo/interface-modal'
|
||||||
|
|
||||||
const CoreMap = {
|
const CoreMap = {
|
||||||
mihomo: '稳定版',
|
mihomo: '稳定版',
|
||||||
@ -43,128 +45,47 @@ const Mihomo: React.FC = () => {
|
|||||||
const [externalControllerInput, setExternalControllerInput] = useState(externalController)
|
const [externalControllerInput, setExternalControllerInput] = useState(externalController)
|
||||||
const [secretInput, setSecretInput] = useState(secret)
|
const [secretInput, setSecretInput] = useState(secret)
|
||||||
|
|
||||||
|
const [lanOpen, setLanOpen] = useState(false)
|
||||||
|
|
||||||
const onChangeNeedRestart = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
const onChangeNeedRestart = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
||||||
await patchControledMihomoConfig(patch)
|
await patchControledMihomoConfig(patch)
|
||||||
await restartCore()
|
await restartCore()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BasePage title="内核设置">
|
<>
|
||||||
<SettingCard>
|
{lanOpen && <InterfaceModal onClose={() => setLanOpen(false)} />}
|
||||||
<SettingItem title="内核版本" divider>
|
<BasePage title="内核设置">
|
||||||
<Select
|
<SettingCard>
|
||||||
className="w-[100px]"
|
<SettingItem title="内核版本" divider>
|
||||||
size="sm"
|
<Select
|
||||||
selectedKeys={new Set([core])}
|
|
||||||
onSelectionChange={async (v) => {
|
|
||||||
try {
|
|
||||||
await patchAppConfig({ core: v.currentKey as 'mihomo' | 'mihomo-alpha' })
|
|
||||||
await restartCore()
|
|
||||||
} catch (e) {
|
|
||||||
alert(e)
|
|
||||||
} finally {
|
|
||||||
PubSub.publish('mihomo-core-changed')
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectItem key="mihomo">{CoreMap['mihomo']}</SelectItem>
|
|
||||||
<SelectItem key="mihomo-alpha">{CoreMap['mihomo-alpha']}</SelectItem>
|
|
||||||
</Select>
|
|
||||||
</SettingItem>
|
|
||||||
<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]"
|
className="w-[100px]"
|
||||||
value={mixedPortInput.toString()}
|
|
||||||
max={65535}
|
|
||||||
min={0}
|
|
||||||
onValueChange={(v) => {
|
|
||||||
setMixedPortInput(parseInt(v))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</SettingItem>
|
|
||||||
<SettingItem title="Socks端口" divider>
|
|
||||||
<div className="flex">
|
|
||||||
{socksPortInput !== socksPort && (
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
color="primary"
|
|
||||||
className="mr-2"
|
|
||||||
onPress={() => {
|
|
||||||
onChangeNeedRestart({ 'socks-port': socksPortInput })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
确认
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Input
|
|
||||||
size="sm"
|
size="sm"
|
||||||
type="number"
|
selectedKeys={new Set([core])}
|
||||||
className="w-[100px]"
|
onSelectionChange={async (v) => {
|
||||||
value={socksPortInput.toString()}
|
try {
|
||||||
max={65535}
|
await patchAppConfig({ core: v.currentKey as 'mihomo' | 'mihomo-alpha' })
|
||||||
min={0}
|
await restartCore()
|
||||||
onValueChange={(v) => {
|
} catch (e) {
|
||||||
setSocksPortInput(parseInt(v))
|
alert(e)
|
||||||
|
} finally {
|
||||||
|
PubSub.publish('mihomo-core-changed')
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
</div>
|
<SelectItem key="mihomo">{CoreMap['mihomo']}</SelectItem>
|
||||||
</SettingItem>
|
<SelectItem key="mihomo-alpha">{CoreMap['mihomo-alpha']}</SelectItem>
|
||||||
<SettingItem title="Http端口" divider>
|
</Select>
|
||||||
<div className="flex">
|
</SettingItem>
|
||||||
{httpPortInput !== httpPort && (
|
<SettingItem title="混合端口" divider>
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
color="primary"
|
|
||||||
className="mr-2"
|
|
||||||
onPress={() => {
|
|
||||||
onChangeNeedRestart({ port: httpPortInput })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
确认
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Input
|
|
||||||
size="sm"
|
|
||||||
type="number"
|
|
||||||
className="w-[100px]"
|
|
||||||
value={httpPortInput.toString()}
|
|
||||||
max={65535}
|
|
||||||
min={0}
|
|
||||||
onValueChange={(v) => {
|
|
||||||
setHttpPortInput(parseInt(v))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</SettingItem>
|
|
||||||
{platform !== 'win32' && (
|
|
||||||
<SettingItem title="Redir端口" divider>
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{redirPortInput !== redirPort && (
|
{mixedPortInput !== mixedPort && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
onChangeNeedRestart({ 'redir-port': redirPortInput })
|
onChangeNeedRestart({ 'mixed-port': mixedPortInput })
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
确认
|
确认
|
||||||
@ -175,26 +96,24 @@ const Mihomo: React.FC = () => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
type="number"
|
type="number"
|
||||||
className="w-[100px]"
|
className="w-[100px]"
|
||||||
value={redirPortInput.toString()}
|
value={mixedPortInput.toString()}
|
||||||
max={65535}
|
max={65535}
|
||||||
min={0}
|
min={0}
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
setRedirPortInput(parseInt(v))
|
setMixedPortInput(parseInt(v))
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
)}
|
<SettingItem title="Socks端口" divider>
|
||||||
{platform === 'linux' && (
|
|
||||||
<SettingItem title="TProxy端口" divider>
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{tproxyPortInput !== tproxyPort && (
|
{socksPortInput !== socksPort && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
onChangeNeedRestart({ 'tproxy-port': tproxyPortInput })
|
onChangeNeedRestart({ 'socks-port': socksPortInput })
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
确认
|
确认
|
||||||
@ -205,151 +124,255 @@ const Mihomo: React.FC = () => {
|
|||||||
size="sm"
|
size="sm"
|
||||||
type="number"
|
type="number"
|
||||||
className="w-[100px]"
|
className="w-[100px]"
|
||||||
value={tproxyPortInput.toString()}
|
value={socksPortInput.toString()}
|
||||||
max={65535}
|
max={65535}
|
||||||
min={0}
|
min={0}
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
setTproxyPortInput(parseInt(v))
|
setSocksPortInput(parseInt(v))
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
)}
|
<SettingItem title="Http端口" divider>
|
||||||
<SettingItem title="外部控制" divider>
|
<div className="flex">
|
||||||
<div className="flex">
|
{httpPortInput !== httpPort && (
|
||||||
{externalControllerInput !== externalController && (
|
<Button
|
||||||
<Button
|
size="sm"
|
||||||
size="sm"
|
color="primary"
|
||||||
color="primary"
|
className="mr-2"
|
||||||
className="mr-2"
|
onPress={() => {
|
||||||
onPress={() => {
|
onChangeNeedRestart({ port: httpPortInput })
|
||||||
onChangeNeedRestart({ 'external-controller': externalControllerInput })
|
}}
|
||||||
}}
|
>
|
||||||
>
|
确认
|
||||||
确认
|
</Button>
|
||||||
</Button>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
size="sm"
|
||||||
|
type="number"
|
||||||
|
className="w-[100px]"
|
||||||
|
value={httpPortInput.toString()}
|
||||||
|
max={65535}
|
||||||
|
min={0}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
setHttpPortInput(parseInt(v))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingItem>
|
||||||
|
{platform !== 'win32' && (
|
||||||
|
<SettingItem title="Redir端口" divider>
|
||||||
|
<div className="flex">
|
||||||
|
{redirPortInput !== redirPort && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
className="mr-2"
|
||||||
|
onPress={() => {
|
||||||
|
onChangeNeedRestart({ 'redir-port': redirPortInput })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Input
|
||||||
|
size="sm"
|
||||||
|
type="number"
|
||||||
|
className="w-[100px]"
|
||||||
|
value={redirPortInput.toString()}
|
||||||
|
max={65535}
|
||||||
|
min={0}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
setRedirPortInput(parseInt(v))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingItem>
|
||||||
|
)}
|
||||||
|
{platform === 'linux' && (
|
||||||
|
<SettingItem title="TProxy端口" divider>
|
||||||
|
<div className="flex">
|
||||||
|
{tproxyPortInput !== tproxyPort && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
className="mr-2"
|
||||||
|
onPress={() => {
|
||||||
|
onChangeNeedRestart({ 'tproxy-port': tproxyPortInput })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Input
|
||||||
|
size="sm"
|
||||||
|
type="number"
|
||||||
|
className="w-[100px]"
|
||||||
|
value={tproxyPortInput.toString()}
|
||||||
|
max={65535}
|
||||||
|
min={0}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
setTproxyPortInput(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"
|
||||||
|
type="password"
|
||||||
|
value={secretInput}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
setSecretInput(v)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingItem>
|
||||||
|
<SettingItem title="IPv6" divider>
|
||||||
|
<Switch
|
||||||
size="sm"
|
size="sm"
|
||||||
value={externalControllerInput}
|
isSelected={ipv6}
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
setExternalControllerInput(v)
|
onChangeNeedRestart({ ipv6: v })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem
|
||||||
<SettingItem title="外部控制访问密钥" divider>
|
title="允许局域网连接"
|
||||||
<div className="flex">
|
actions={
|
||||||
{secretInput !== secret && (
|
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
isIconOnly
|
||||||
className="mr-2"
|
variant="light"
|
||||||
|
className="ml-2"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
onChangeNeedRestart({ secret: secretInput })
|
setLanOpen(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
确认
|
<FaNetworkWired className="text-lg" />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
}
|
||||||
|
divider
|
||||||
<Input
|
>
|
||||||
|
<Switch
|
||||||
size="sm"
|
size="sm"
|
||||||
type="password"
|
isSelected={allowLan}
|
||||||
value={secretInput}
|
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
setSecretInput(v)
|
onChangeNeedRestart({ 'allow-lan': v })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem title="使用RTT延迟测试" divider>
|
||||||
<SettingItem title="IPv6" divider>
|
<Switch
|
||||||
<Switch
|
size="sm"
|
||||||
size="sm"
|
isSelected={unifiedDelay}
|
||||||
isSelected={ipv6}
|
onValueChange={(v) => {
|
||||||
onValueChange={(v) => {
|
onChangeNeedRestart({ 'unified-delay': v })
|
||||||
onChangeNeedRestart({ ipv6: v })
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem title="TCP并发" divider>
|
||||||
<SettingItem title="允许局域网连接" divider>
|
<Switch
|
||||||
<Switch
|
size="sm"
|
||||||
size="sm"
|
isSelected={tcpConcurrent}
|
||||||
isSelected={allowLan}
|
onValueChange={(v) => {
|
||||||
onValueChange={(v) => {
|
onChangeNeedRestart({ 'tcp-concurrent': v })
|
||||||
onChangeNeedRestart({ 'allow-lan': v })
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem title="存储选择节点" divider>
|
||||||
<SettingItem title="使用RTT延迟测试" divider>
|
<Switch
|
||||||
<Switch
|
size="sm"
|
||||||
size="sm"
|
isSelected={storeSelected}
|
||||||
isSelected={unifiedDelay}
|
onValueChange={(v) => {
|
||||||
onValueChange={(v) => {
|
onChangeNeedRestart({ profile: { 'store-selected': v } })
|
||||||
onChangeNeedRestart({ 'unified-delay': v })
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem title="存储FakeIP" divider>
|
||||||
<SettingItem title="TCP并发" divider>
|
<Switch
|
||||||
<Switch
|
size="sm"
|
||||||
size="sm"
|
isSelected={storeFakeIp}
|
||||||
isSelected={tcpConcurrent}
|
onValueChange={(v) => {
|
||||||
onValueChange={(v) => {
|
onChangeNeedRestart({ profile: { 'store-fake-ip': v } })
|
||||||
onChangeNeedRestart({ 'tcp-concurrent': v })
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</SettingItem>
|
||||||
</SettingItem>
|
<SettingItem title="日志等级" divider>
|
||||||
<SettingItem title="存储选择节点" divider>
|
<Select
|
||||||
<Switch
|
className="w-[100px]"
|
||||||
size="sm"
|
size="sm"
|
||||||
isSelected={storeSelected}
|
selectedKeys={new Set([logLevel])}
|
||||||
onValueChange={(v) => {
|
onSelectionChange={(v) => {
|
||||||
onChangeNeedRestart({ profile: { 'store-selected': v } })
|
onChangeNeedRestart({ 'log-level': v.currentKey as LogLevel })
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
</SettingItem>
|
<SelectItem key="silent">静默</SelectItem>
|
||||||
<SettingItem title="存储FakeIP" divider>
|
<SelectItem key="error">错误</SelectItem>
|
||||||
<Switch
|
<SelectItem key="warning">警告</SelectItem>
|
||||||
size="sm"
|
<SelectItem key="info">信息</SelectItem>
|
||||||
isSelected={storeFakeIp}
|
<SelectItem key="debug">调试</SelectItem>
|
||||||
onValueChange={(v) => {
|
</Select>
|
||||||
onChangeNeedRestart({ profile: { 'store-fake-ip': v } })
|
</SettingItem>
|
||||||
}}
|
<SettingItem title="查找进程">
|
||||||
/>
|
<Select
|
||||||
</SettingItem>
|
className="w-[100px]"
|
||||||
<SettingItem title="日志等级" divider>
|
size="sm"
|
||||||
<Select
|
selectedKeys={new Set([findProcessMode])}
|
||||||
className="w-[100px]"
|
onSelectionChange={(v) => {
|
||||||
size="sm"
|
onChangeNeedRestart({ 'find-process-mode': v.currentKey as FindProcessMode })
|
||||||
selectedKeys={new Set([logLevel])}
|
}}
|
||||||
onSelectionChange={(v) => {
|
>
|
||||||
onChangeNeedRestart({ 'log-level': v.currentKey as LogLevel })
|
<SelectItem key="strict">自动</SelectItem>
|
||||||
}}
|
<SelectItem key="off">关闭</SelectItem>
|
||||||
>
|
<SelectItem key="always">开启</SelectItem>
|
||||||
<SelectItem key="silent">静默</SelectItem>
|
</Select>
|
||||||
<SelectItem key="error">错误</SelectItem>
|
</SettingItem>
|
||||||
<SelectItem key="warning">警告</SelectItem>
|
</SettingCard>
|
||||||
<SelectItem key="info">信息</SelectItem>
|
</BasePage>
|
||||||
<SelectItem key="debug">调试</SelectItem>
|
</>
|
||||||
</Select>
|
|
||||||
</SettingItem>
|
|
||||||
<SettingItem title="查找进程">
|
|
||||||
<Select
|
|
||||||
className="w-[100px]"
|
|
||||||
size="sm"
|
|
||||||
selectedKeys={new Set([findProcessMode])}
|
|
||||||
onSelectionChange={(v) => {
|
|
||||||
onChangeNeedRestart({ 'find-process-mode': v.currentKey as FindProcessMode })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectItem key="strict">自动</SelectItem>
|
|
||||||
<SelectItem key="off">关闭</SelectItem>
|
|
||||||
<SelectItem key="always">开启</SelectItem>
|
|
||||||
</Select>
|
|
||||||
</SettingItem>
|
|
||||||
</SettingCard>
|
|
||||||
</BasePage>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -251,6 +251,10 @@ export async function setupFirewall(): Promise<void> {
|
|||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setupFirewall'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setupFirewall'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getInterfaces(): Promise<Record<string, NetworkInterfaceInfo[]>> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('getInterfaces'))
|
||||||
|
}
|
||||||
|
|
||||||
export async function setPortable(portable: boolean): Promise<void> {
|
export async function setPortable(portable: boolean): Promise<void> {
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setPortable', portable))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setPortable', portable))
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/shared/types.d.ts
vendored
1
src/shared/types.d.ts
vendored
@ -36,6 +36,7 @@ type MihomoProxyType =
|
|||||||
type TunStack = 'gvisor' | 'mixed' | 'system'
|
type TunStack = 'gvisor' | 'mixed' | 'system'
|
||||||
type FindProcessMode = 'off' | 'strict' | 'always'
|
type FindProcessMode = 'off' | 'strict' | 'always'
|
||||||
type DnsMode = 'normal' | 'fake-ip' | 'redir-host'
|
type DnsMode = 'normal' | 'fake-ip' | 'redir-host'
|
||||||
|
type NetworkInterfaceInfo = os.NetworkInterfaceInfo
|
||||||
|
|
||||||
interface IAppVersion {
|
interface IAppVersion {
|
||||||
version: string
|
version: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user