mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-15 19:22:31 +08:00
support pac mode
This commit is contained in:
parent
c4dcead397
commit
cb1d8c6141
|
@ -21,12 +21,14 @@
|
|||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@mihomo-party/sysproxy": "^1.0.1",
|
||||
"@nextui-org/react": "^2.4.6",
|
||||
"axios": "^1.7.2",
|
||||
"electron-updater": "^6.2.1",
|
||||
"framer-motion": "^11.3.19",
|
||||
"next-themes": "^0.3.0",
|
||||
"react-icons": "^5.2.1",
|
||||
"react-monaco-editor": "^0.55.0",
|
||||
"react-router-dom": "^6.25.1",
|
||||
"swr": "^2.2.5",
|
||||
"ws": "^8.18.0",
|
||||
|
|
102
pnpm-lock.yaml
102
pnpm-lock.yaml
|
@ -14,6 +14,9 @@ importers:
|
|||
'@electron-toolkit/utils':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0(electron@31.3.1)
|
||||
'@mihomo-party/sysproxy':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
'@nextui-org/react':
|
||||
specifier: ^2.4.6
|
||||
version: 2.4.6(@types/react@18.3.3)(framer-motion@11.3.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7)
|
||||
|
@ -32,6 +35,9 @@ importers:
|
|||
react-icons:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1(react@18.3.1)
|
||||
react-monaco-editor:
|
||||
specifier: ^0.55.0
|
||||
version: 0.55.0(@types/react@18.3.3)(monaco-editor@0.44.0)(react@18.3.1)
|
||||
react-router-dom:
|
||||
specifier: ^6.25.1
|
||||
version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
@ -522,6 +528,52 @@ packages:
|
|||
resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@mihomo-party/sysproxy-darwin-arm64@1.0.1':
|
||||
resolution: {integrity: sha512-VNrJLIXpgQBesNw9Ng3IgHK8L9JS4hHIXe/cn3ODHjq2kDXar1Q1qcXAHpi8ZRiw6Q1H5pewRl+EBb+ZCAHInQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@mihomo-party/sysproxy-darwin-x64@1.0.1':
|
||||
resolution: {integrity: sha512-OdkcgjXscnos4hQ6YmFtxyTJZde0QjNJpgyCW826JYyjPzWPTtjftCnLWFVnSIU6U0jAfW+iSF8B1qmj3+db+w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@mihomo-party/sysproxy-linux-arm64-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-NHzw7lI4oqANuYoU+QmwmEwntYDakkgYBZ1xf8JF48eIKoff48Nw0c3+lF57U0NNVy+s1xdPlZwmPABHe9fmhg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@mihomo-party/sysproxy-linux-x64-gnu@1.0.1':
|
||||
resolution: {integrity: sha512-BYKTHGMxxxCMjaeUV5VH/Ikq1QMC0vJrQ9dX/LXnYN2++wL/bz8cKs3K2FgzUN2rczDj/7yQGmlhLqUgEQ6Wqg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@mihomo-party/sysproxy-win32-arm64-msvc@1.0.1':
|
||||
resolution: {integrity: sha512-d467s+fpXYUafJ1rEiqeCpbEC3iL25+3SXIReTg3264irq9H439+S/BBqENAoenq30UTp58r8f2Cr93LcsqLSQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@mihomo-party/sysproxy-win32-ia32-msvc@1.0.1':
|
||||
resolution: {integrity: sha512-ZXtNYV+egkb0DdQrAfsEwUH25S4PRyuh9ziSW9TuqQW9d+La8SOMxPut9jbMmyFnKnbvXtcibqXxKpxDHPspoQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@mihomo-party/sysproxy-win32-x64-msvc@1.0.1':
|
||||
resolution: {integrity: sha512-lJR8sIN3ciFdKs5A2oy+nKhiFMseDxPiP1tFDhFYwnzgqTCkZBTadH6km+TMP1VWseYT1QG/sDG6U2jVz126bg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@mihomo-party/sysproxy@1.0.1':
|
||||
resolution: {integrity: sha512-VLuplU5WEsexJJZWcHut8zO/l8o1vZFpyisMhL1PwAaYwsTEOt4NGtkXrTB1HkNTvmsdhAFPk7EU7XTbs3QPmA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@nextui-org/accordion@2.0.38':
|
||||
resolution: {integrity: sha512-kFCZU1VaKkUI295Fg3NxuQR2+kZ5vTH4ftIs0oByrOs0+l14dVQGFOd9ZV402fHNykZJt7Sk6oWjTp4Qwl83JA==}
|
||||
peerDependencies:
|
||||
|
@ -3258,6 +3310,9 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
monaco-editor@0.44.0:
|
||||
resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==}
|
||||
|
||||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
|
@ -3554,6 +3609,13 @@ packages:
|
|||
react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
react-monaco-editor@0.55.0:
|
||||
resolution: {integrity: sha512-GdEP0Q3Rn1dczfKEEyY08Nes5plWwIYU4sWRBQO0+jsQWQsKMHKCC6+hPRwR7G/4aA3V/iU9jSmWPzVJYMVFSQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '>=16 <= 18'
|
||||
monaco-editor: ^0.44.0
|
||||
react: '>=16 <= 18'
|
||||
|
||||
react-refresh@0.14.2:
|
||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -4674,6 +4736,37 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@mihomo-party/sysproxy-darwin-arm64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-darwin-x64@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-linux-arm64-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-linux-x64-gnu@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-win32-arm64-msvc@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-win32-ia32-msvc@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy-win32-x64-msvc@1.0.1':
|
||||
optional: true
|
||||
|
||||
'@mihomo-party/sysproxy@1.0.1':
|
||||
optionalDependencies:
|
||||
'@mihomo-party/sysproxy-darwin-arm64': 1.0.1
|
||||
'@mihomo-party/sysproxy-darwin-x64': 1.0.1
|
||||
'@mihomo-party/sysproxy-linux-arm64-gnu': 1.0.1
|
||||
'@mihomo-party/sysproxy-linux-x64-gnu': 1.0.1
|
||||
'@mihomo-party/sysproxy-win32-arm64-msvc': 1.0.1
|
||||
'@mihomo-party/sysproxy-win32-ia32-msvc': 1.0.1
|
||||
'@mihomo-party/sysproxy-win32-x64-msvc': 1.0.1
|
||||
|
||||
'@nextui-org/accordion@2.0.38(@nextui-org/system@2.2.5(@nextui-org/theme@2.2.9(tailwindcss@3.4.7))(framer-motion@11.3.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@nextui-org/theme@2.2.9(tailwindcss@3.4.7))(framer-motion@11.3.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@nextui-org/aria-utils': 2.0.24(@nextui-org/theme@2.2.9(tailwindcss@3.4.7))(framer-motion@11.3.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
@ -8574,6 +8667,8 @@ snapshots:
|
|||
|
||||
mkdirp@3.0.1: {}
|
||||
|
||||
monaco-editor@0.44.0: {}
|
||||
|
||||
ms@2.1.2: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
@ -8847,6 +8942,13 @@ snapshots:
|
|||
|
||||
react-is@16.13.1: {}
|
||||
|
||||
react-monaco-editor@0.55.0(@types/react@18.3.3)(monaco-editor@0.44.0)(react@18.3.1):
|
||||
dependencies:
|
||||
'@types/react': 18.3.3
|
||||
monaco-editor: 0.44.0
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
|
||||
react-refresh@0.14.2: {}
|
||||
|
||||
react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):
|
||||
|
|
|
@ -12,6 +12,11 @@ export function getAppConfig(force = false): IAppConfig {
|
|||
}
|
||||
|
||||
export function setAppConfig(patch: Partial<IAppConfig>): void {
|
||||
if (patch.sysProxy) {
|
||||
const oldSysProxy = appConfig.sysProxy || {}
|
||||
const newSysProxy = Object.assign(oldSysProxy, patch.sysProxy)
|
||||
patch.sysProxy = newSysProxy
|
||||
}
|
||||
appConfig = Object.assign(appConfig, patch)
|
||||
fs.writeFileSync(appConfigPath(), yaml.stringify(appConfig))
|
||||
}
|
||||
|
|
|
@ -68,10 +68,16 @@ const buildContextMenu = (): Menu => {
|
|||
checked: getAppConfig().sysProxy?.enable ?? false,
|
||||
click: (item): void => {
|
||||
const enable = item.checked
|
||||
setAppConfig({ sysProxy: { enable } })
|
||||
triggerSysProxy(enable)
|
||||
window?.webContents.send('appConfigUpdated')
|
||||
updateTrayMenu()
|
||||
try {
|
||||
triggerSysProxy(enable)
|
||||
setAppConfig({ sysProxy: { enable } })
|
||||
window?.webContents.send('appConfigUpdated')
|
||||
} catch (e) {
|
||||
setAppConfig({ sysProxy: { enable: !enable } })
|
||||
console.error(e)
|
||||
} finally {
|
||||
updateTrayMenu()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@ import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
|||
import { registerIpcMainHandlers } from './utils/cmds'
|
||||
import { app, shell, BrowserWindow } from 'electron'
|
||||
import { stopCore, startCore } from './core/manager'
|
||||
import { triggerSysProxy } from './resolve/sysproxy'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
import { mihomoTraffic } from './core/mihomoApi'
|
||||
import { createTray } from './core/tray'
|
||||
|
@ -35,6 +36,7 @@ if (!gotTheLock) {
|
|||
|
||||
app.on('before-quit', () => {
|
||||
stopCore()
|
||||
triggerSysProxy(false)
|
||||
app.exit()
|
||||
})
|
||||
|
||||
|
@ -86,6 +88,10 @@ function createWindow(): void {
|
|||
}
|
||||
})
|
||||
|
||||
window.on('resize', () => {
|
||||
window?.webContents.send('resize')
|
||||
})
|
||||
|
||||
window.on('close', (event) => {
|
||||
event.preventDefault()
|
||||
window?.hide()
|
||||
|
|
|
@ -18,6 +18,9 @@ import {
|
|||
import yaml from 'yaml'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { startPacServer } from './server'
|
||||
import { triggerSysProxy } from './sysproxy'
|
||||
import { getAppConfig } from '../config'
|
||||
|
||||
function initDirs(): void {
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
|
@ -64,4 +67,7 @@ export function init(): void {
|
|||
initDirs()
|
||||
initConfig()
|
||||
initFiles()
|
||||
startPacServer().then(() => {
|
||||
triggerSysProxy(getAppConfig().sysProxy.enable)
|
||||
})
|
||||
}
|
||||
|
|
49
src/main/resolve/server.ts
Normal file
49
src/main/resolve/server.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||
import http from 'http'
|
||||
import net from 'net'
|
||||
|
||||
export let pacPort: number
|
||||
|
||||
const defaultPacScript = `
|
||||
function FindProxyForURL(url, host) {
|
||||
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||
}
|
||||
`
|
||||
|
||||
function findAvailablePort(startPort: number): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer()
|
||||
server.unref()
|
||||
server.on('error', (err) => {
|
||||
if (startPort <= 65535) {
|
||||
resolve(findAvailablePort(startPort + 1))
|
||||
} else {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
|
||||
server.listen(startPort, () => {
|
||||
// 端口可用
|
||||
server.close(() => {
|
||||
resolve(startPort)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function startPacServer(): Promise<void> {
|
||||
pacPort = await findAvailablePort(10000)
|
||||
const server = http
|
||||
.createServer((_req, res) => {
|
||||
const {
|
||||
sysProxy: { pacScript }
|
||||
} = getAppConfig()
|
||||
const { 'mixed-port': port = 7890 } = getControledMihomoConfig()
|
||||
let script = pacScript || defaultPacScript
|
||||
script = script.replaceAll('%mixed-port%', port.toString())
|
||||
res.writeHead(200, { 'Content-Type': 'application/x-ns-proxy-autoconfig' })
|
||||
res.end(script)
|
||||
})
|
||||
.listen(pacPort)
|
||||
server.unref()
|
||||
}
|
|
@ -1,7 +1,49 @@
|
|||
import { getControledMihomoConfig } from '../config'
|
||||
import { triggerAutoProxy, triggerManualProxy } from '@mihomo-party/sysproxy'
|
||||
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||
import { pacPort } from './server'
|
||||
|
||||
let defaultBypass: string[]
|
||||
if (process.platform === 'linux')
|
||||
defaultBypass = ['localhost', '127.0.0.1', '192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12', '::1']
|
||||
if (process.platform === 'darwin')
|
||||
defaultBypass = [
|
||||
'127.0.0.1',
|
||||
'192.168.0.0/16',
|
||||
'10.0.0.0/8',
|
||||
'172.16.0.0/12',
|
||||
'localhost',
|
||||
'*.local',
|
||||
'*.crashlytics.com',
|
||||
'<local>'
|
||||
]
|
||||
if (process.platform === 'win32')
|
||||
defaultBypass = [
|
||||
'localhost',
|
||||
'127.*',
|
||||
'192.168.*',
|
||||
'10.*',
|
||||
'172.16.*',
|
||||
'172.17.*',
|
||||
'172.18.*',
|
||||
'172.19.*',
|
||||
'172.20.*',
|
||||
'172.21.*',
|
||||
'172.22.*',
|
||||
'172.23.*',
|
||||
'172.24.*',
|
||||
'172.25.*',
|
||||
'172.26.*',
|
||||
'172.27.*',
|
||||
'172.28.*',
|
||||
'172.29.*',
|
||||
'172.30.*',
|
||||
'172.31.*',
|
||||
'<local>'
|
||||
]
|
||||
|
||||
export function triggerSysProxy(enable: boolean): void {
|
||||
if (enable) {
|
||||
disableSysProxy()
|
||||
enableSysProxy()
|
||||
} else {
|
||||
disableSysProxy()
|
||||
|
@ -9,9 +51,29 @@ export function triggerSysProxy(enable: boolean): void {
|
|||
}
|
||||
|
||||
export function enableSysProxy(): void {
|
||||
console.log('enableSysProxy', getControledMihomoConfig()['mixed-port'])
|
||||
const { sysProxy } = getAppConfig()
|
||||
const { mode, host, bypass = defaultBypass } = sysProxy
|
||||
const { 'mixed-port': port = 7890 } = getControledMihomoConfig()
|
||||
|
||||
switch (mode || 'manual') {
|
||||
case 'auto': {
|
||||
triggerAutoProxy(true, `http://${host || '127.0.0.1'}:${pacPort}/pac`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'manual': {
|
||||
triggerManualProxy(
|
||||
true,
|
||||
host || '127.0.0.1',
|
||||
port,
|
||||
bypass.join(process.platform === 'win32' ? ';' : ',')
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function disableSysProxy(): void {
|
||||
console.log('disableSysProxy')
|
||||
triggerAutoProxy(false, '')
|
||||
triggerManualProxy(false, '', 0, '')
|
||||
}
|
||||
|
|
|
@ -15,8 +15,12 @@ const SysproxySwitcher: React.FC = () => {
|
|||
const { enable } = sysProxy || {}
|
||||
|
||||
const onChange = async (enable: boolean): Promise<void> => {
|
||||
await patchAppConfig({ sysProxy: { enable } })
|
||||
await triggerSysProxy(enable)
|
||||
try {
|
||||
await triggerSysProxy(enable)
|
||||
await patchAppConfig({ sysProxy: { enable } })
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -15,7 +15,6 @@ const TunSwitcher: React.FC = () => {
|
|||
const { tun } = controledMihomoConfig || {}
|
||||
const { enable } = tun || {}
|
||||
|
||||
console.log('controledMihomoConfig', controledMihomoConfig)
|
||||
const onChange = async (enable: boolean): Promise<void> => {
|
||||
await patchControledMihomoConfig({ tun: { enable } })
|
||||
await patchMihomoConfig({ tun: { enable } })
|
||||
|
|
63
src/renderer/src/components/sysproxy/pac-editor-modal.tsx
Normal file
63
src/renderer/src/components/sysproxy/pac-editor-modal.tsx
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react'
|
||||
import React, { useState } from 'react'
|
||||
import MonacoEditor, { monaco } from 'react-monaco-editor'
|
||||
import { useTheme } from 'next-themes'
|
||||
interface Props {
|
||||
script: string
|
||||
onCancel: () => void
|
||||
onConfirm: (script: string) => void
|
||||
}
|
||||
const PacEditorViewer: React.FC<Props> = (props) => {
|
||||
const { script, onCancel, onConfirm } = props
|
||||
const [currData, setCurrData] = useState(script)
|
||||
const { theme } = useTheme()
|
||||
|
||||
const editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor): void => {
|
||||
window.electron.ipcRenderer.on('resize', () => {
|
||||
editor.layout()
|
||||
})
|
||||
}
|
||||
|
||||
const editorWillUnmount = (editor: monaco.editor.IStandaloneCodeEditor): void => {
|
||||
window.electron.ipcRenderer.removeAllListeners('resize')
|
||||
editor.dispose()
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal size="5xl" hideCloseButton isOpen={true} scrollBehavior="inside">
|
||||
<ModalContent className="h-full w-[calc(100%-100px)]">
|
||||
<ModalHeader className="flex">编辑PAC脚本</ModalHeader>
|
||||
<ModalBody className="h-full">
|
||||
<MonacoEditor
|
||||
height="100%"
|
||||
language="javascript"
|
||||
value={currData}
|
||||
theme={theme === 'dark' ? 'vs-dark' : 'vs'}
|
||||
options={{
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
mouseWheelZoom: true,
|
||||
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"`,
|
||||
fontLigatures: true, // 连字符
|
||||
smoothScrolling: true // 平滑滚动
|
||||
}}
|
||||
editorDidMount={editorDidMount}
|
||||
editorWillUnmount={editorWillUnmount}
|
||||
onChange={(value) => setCurrData(value)}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button color="primary" onPress={() => onConfirm(currData)}>
|
||||
确认
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default PacEditorViewer
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Switch } from '@nextui-org/react'
|
||||
import BasePage from '@renderer/components/base/base-page'
|
||||
import SettingCard from '@renderer/components/settings/setting-card'
|
||||
import SettingItem from '@renderer/components/settings/setting-item'
|
||||
import SettingCard from '@renderer/components/base/base-setting-card'
|
||||
import SettingItem from '@renderer/components/base/base-setting-item'
|
||||
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||
import { checkAutoRun, enableAutoRun, disableAutoRun } from '@renderer/utils/ipc'
|
||||
import { IoLogoGithub } from 'react-icons/io5'
|
||||
|
|
|
@ -1,5 +1,95 @@
|
|||
import { Button, Input, Tab, Tabs } 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 PacEditorViewer from '@renderer/components/sysproxy/pac-editor-modal'
|
||||
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||
import { triggerSysProxy } from '@renderer/utils/ipc'
|
||||
import { Key, useState } from 'react'
|
||||
import React from 'react'
|
||||
|
||||
const defaultPacScript = `
|
||||
function FindProxyForURL(url, host) {
|
||||
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||
}
|
||||
`
|
||||
|
||||
const Sysproxy: React.FC = () => {
|
||||
return <div>Sysproxy</div>
|
||||
const { appConfig, patchAppConfig } = useAppConfig()
|
||||
const { sysProxy } = appConfig || { sysProxy: { enable: false } }
|
||||
|
||||
const [values, setValues] = useState<ISysProxyConfig>(sysProxy)
|
||||
const [openPacEditor, setOpenPacEditor] = useState(false)
|
||||
const onSave = async (): Promise<void> => {
|
||||
// check valid TODO
|
||||
await patchAppConfig({ sysProxy: values })
|
||||
try {
|
||||
await triggerSysProxy(true)
|
||||
await patchAppConfig({ sysProxy: { enable: true } })
|
||||
} catch (e) {
|
||||
await patchAppConfig({ sysProxy: { enable: false } })
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
title="系统代理设置"
|
||||
header={
|
||||
<Button size="sm" color="primary" onPress={onSave}>
|
||||
保存
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{openPacEditor && (
|
||||
<PacEditorViewer
|
||||
script={values.pacScript || defaultPacScript}
|
||||
onCancel={() => setOpenPacEditor(false)}
|
||||
onConfirm={(script: string) => {
|
||||
setValues({ ...values, pacScript: script })
|
||||
setOpenPacEditor(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SettingCard>
|
||||
<SettingItem title="代理主机" divider>
|
||||
<Input
|
||||
size="sm"
|
||||
className="w-[50%]"
|
||||
value={values.host}
|
||||
placeholder="默认127.0.0.1若无特殊需求请勿修改"
|
||||
onValueChange={(v) => {
|
||||
setValues({ ...values, host: v })
|
||||
}}
|
||||
/>
|
||||
</SettingItem>
|
||||
<SettingItem title="代理模式" divider>
|
||||
<Tabs
|
||||
size="sm"
|
||||
color="primary"
|
||||
selectedKey={values.mode}
|
||||
onSelectionChange={(key: Key) => setValues({ ...values, mode: key as SysProxyMode })}
|
||||
>
|
||||
<Tab
|
||||
className={`select-none ${values.mode === 'manual' ? 'font-bold' : ''}`}
|
||||
key="manual"
|
||||
title="手动"
|
||||
/>
|
||||
<Tab
|
||||
className={`select-none ${values.mode === 'auto' ? 'font-bold' : ''}`}
|
||||
key="auto"
|
||||
title="PAC"
|
||||
/>
|
||||
</Tabs>
|
||||
</SettingItem>
|
||||
<SettingItem title="代理模式">
|
||||
<Button size="sm" onPress={() => setOpenPacEditor(true)} variant="bordered">
|
||||
编辑PAC脚本
|
||||
</Button>
|
||||
</SettingItem>
|
||||
</SettingCard>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
||||
|
||||
export default Sysproxy
|
||||
|
|
5
src/shared/types.d.ts
vendored
5
src/shared/types.d.ts
vendored
|
@ -1,6 +1,6 @@
|
|||
type OutboundMode = 'rule' | 'global' | 'direct'
|
||||
type LogLevel = 'info' | 'debug' | 'warn' | 'error' | 'silent'
|
||||
|
||||
type SysProxyMode = 'auto' | 'manual'
|
||||
interface IMihomoVersion {
|
||||
version: string
|
||||
meta: boolean
|
||||
|
@ -65,7 +65,8 @@ interface IMihomoConnectionDetail {
|
|||
|
||||
interface ISysProxyConfig {
|
||||
enable: boolean
|
||||
mode?: 'auto' | 'manual'
|
||||
host?: string
|
||||
mode?: SysProxyMode
|
||||
bypass?: string[]
|
||||
pacScript?: string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user