mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 11:42:19 +08:00
support pac mode
This commit is contained in:
parent
c4dcead397
commit
cb1d8c6141
|
@ -21,12 +21,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-toolkit/preload": "^3.0.1",
|
"@electron-toolkit/preload": "^3.0.1",
|
||||||
"@electron-toolkit/utils": "^3.0.0",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
|
"@mihomo-party/sysproxy": "^1.0.1",
|
||||||
"@nextui-org/react": "^2.4.6",
|
"@nextui-org/react": "^2.4.6",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"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",
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.2.1",
|
||||||
|
"react-monaco-editor": "^0.55.0",
|
||||||
"react-router-dom": "^6.25.1",
|
"react-router-dom": "^6.25.1",
|
||||||
"swr": "^2.2.5",
|
"swr": "^2.2.5",
|
||||||
"ws": "^8.18.0",
|
"ws": "^8.18.0",
|
||||||
|
|
102
pnpm-lock.yaml
102
pnpm-lock.yaml
|
@ -14,6 +14,9 @@ importers:
|
||||||
'@electron-toolkit/utils':
|
'@electron-toolkit/utils':
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0(electron@31.3.1)
|
version: 3.0.0(electron@31.3.1)
|
||||||
|
'@mihomo-party/sysproxy':
|
||||||
|
specifier: ^1.0.1
|
||||||
|
version: 1.0.1
|
||||||
'@nextui-org/react':
|
'@nextui-org/react':
|
||||||
specifier: ^2.4.6
|
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)
|
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:
|
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)
|
||||||
|
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:
|
react-router-dom:
|
||||||
specifier: ^6.25.1
|
specifier: ^6.25.1
|
||||||
version: 6.25.1(react-dom@18.3.1(react@18.3.1))(react@18.3.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==}
|
resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==}
|
||||||
engines: {node: '>= 10.0.0'}
|
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':
|
'@nextui-org/accordion@2.0.38':
|
||||||
resolution: {integrity: sha512-kFCZU1VaKkUI295Fg3NxuQR2+kZ5vTH4ftIs0oByrOs0+l14dVQGFOd9ZV402fHNykZJt7Sk6oWjTp4Qwl83JA==}
|
resolution: {integrity: sha512-kFCZU1VaKkUI295Fg3NxuQR2+kZ5vTH4ftIs0oByrOs0+l14dVQGFOd9ZV402fHNykZJt7Sk6oWjTp4Qwl83JA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -3258,6 +3310,9 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
monaco-editor@0.44.0:
|
||||||
|
resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==}
|
||||||
|
|
||||||
ms@2.1.2:
|
ms@2.1.2:
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||||
|
|
||||||
|
@ -3554,6 +3609,13 @@ packages:
|
||||||
react-is@16.13.1:
|
react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
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:
|
react-refresh@0.14.2:
|
||||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -4674,6 +4736,37 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- 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)':
|
'@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:
|
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)
|
'@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: {}
|
mkdirp@3.0.1: {}
|
||||||
|
|
||||||
|
monaco-editor@0.44.0: {}
|
||||||
|
|
||||||
ms@2.1.2: {}
|
ms@2.1.2: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
@ -8847,6 +8942,13 @@ snapshots:
|
||||||
|
|
||||||
react-is@16.13.1: {}
|
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-refresh@0.14.2: {}
|
||||||
|
|
||||||
react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):
|
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 {
|
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)
|
appConfig = Object.assign(appConfig, patch)
|
||||||
fs.writeFileSync(appConfigPath(), yaml.stringify(appConfig))
|
fs.writeFileSync(appConfigPath(), yaml.stringify(appConfig))
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,10 +68,16 @@ const buildContextMenu = (): Menu => {
|
||||||
checked: getAppConfig().sysProxy?.enable ?? false,
|
checked: getAppConfig().sysProxy?.enable ?? false,
|
||||||
click: (item): void => {
|
click: (item): void => {
|
||||||
const enable = item.checked
|
const enable = item.checked
|
||||||
setAppConfig({ sysProxy: { enable } })
|
try {
|
||||||
triggerSysProxy(enable)
|
triggerSysProxy(enable)
|
||||||
window?.webContents.send('appConfigUpdated')
|
setAppConfig({ sysProxy: { enable } })
|
||||||
updateTrayMenu()
|
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 { registerIpcMainHandlers } from './utils/cmds'
|
||||||
import { app, shell, BrowserWindow } from 'electron'
|
import { app, shell, BrowserWindow } from 'electron'
|
||||||
import { stopCore, startCore } from './core/manager'
|
import { stopCore, startCore } from './core/manager'
|
||||||
|
import { triggerSysProxy } from './resolve/sysproxy'
|
||||||
import icon from '../../resources/icon.png?asset'
|
import icon from '../../resources/icon.png?asset'
|
||||||
import { mihomoTraffic } from './core/mihomoApi'
|
import { mihomoTraffic } from './core/mihomoApi'
|
||||||
import { createTray } from './core/tray'
|
import { createTray } from './core/tray'
|
||||||
|
@ -35,6 +36,7 @@ if (!gotTheLock) {
|
||||||
|
|
||||||
app.on('before-quit', () => {
|
app.on('before-quit', () => {
|
||||||
stopCore()
|
stopCore()
|
||||||
|
triggerSysProxy(false)
|
||||||
app.exit()
|
app.exit()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -86,6 +88,10 @@ function createWindow(): void {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.on('resize', () => {
|
||||||
|
window?.webContents.send('resize')
|
||||||
|
})
|
||||||
|
|
||||||
window.on('close', (event) => {
|
window.on('close', (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
window?.hide()
|
window?.hide()
|
||||||
|
|
|
@ -18,6 +18,9 @@ import {
|
||||||
import yaml from 'yaml'
|
import yaml from 'yaml'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { startPacServer } from './server'
|
||||||
|
import { triggerSysProxy } from './sysproxy'
|
||||||
|
import { getAppConfig } from '../config'
|
||||||
|
|
||||||
function initDirs(): void {
|
function initDirs(): void {
|
||||||
if (!fs.existsSync(dataDir)) {
|
if (!fs.existsSync(dataDir)) {
|
||||||
|
@ -64,4 +67,7 @@ export function init(): void {
|
||||||
initDirs()
|
initDirs()
|
||||||
initConfig()
|
initConfig()
|
||||||
initFiles()
|
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 {
|
export function triggerSysProxy(enable: boolean): void {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
disableSysProxy()
|
||||||
enableSysProxy()
|
enableSysProxy()
|
||||||
} else {
|
} else {
|
||||||
disableSysProxy()
|
disableSysProxy()
|
||||||
|
@ -9,9 +51,29 @@ export function triggerSysProxy(enable: boolean): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enableSysProxy(): 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 {
|
export function disableSysProxy(): void {
|
||||||
console.log('disableSysProxy')
|
triggerAutoProxy(false, '')
|
||||||
|
triggerManualProxy(false, '', 0, '')
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,12 @@ const SysproxySwitcher: React.FC = () => {
|
||||||
const { enable } = sysProxy || {}
|
const { enable } = sysProxy || {}
|
||||||
|
|
||||||
const onChange = async (enable: boolean): Promise<void> => {
|
const onChange = async (enable: boolean): Promise<void> => {
|
||||||
await patchAppConfig({ sysProxy: { enable } })
|
try {
|
||||||
await triggerSysProxy(enable)
|
await triggerSysProxy(enable)
|
||||||
|
await patchAppConfig({ sysProxy: { enable } })
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -15,7 +15,6 @@ const TunSwitcher: React.FC = () => {
|
||||||
const { tun } = controledMihomoConfig || {}
|
const { tun } = controledMihomoConfig || {}
|
||||||
const { enable } = tun || {}
|
const { enable } = tun || {}
|
||||||
|
|
||||||
console.log('controledMihomoConfig', controledMihomoConfig)
|
|
||||||
const onChange = async (enable: boolean): Promise<void> => {
|
const onChange = async (enable: boolean): Promise<void> => {
|
||||||
await patchControledMihomoConfig({ tun: { enable } })
|
await patchControledMihomoConfig({ tun: { enable } })
|
||||||
await patchMihomoConfig({ 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 { Button, 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/settings/setting-card'
|
import SettingCard from '@renderer/components/base/base-setting-card'
|
||||||
import SettingItem from '@renderer/components/settings/setting-item'
|
import SettingItem from '@renderer/components/base/base-setting-item'
|
||||||
import { useAppConfig } from '@renderer/hooks/use-config'
|
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||||
import { checkAutoRun, enableAutoRun, disableAutoRun } from '@renderer/utils/ipc'
|
import { checkAutoRun, enableAutoRun, disableAutoRun } from '@renderer/utils/ipc'
|
||||||
import { IoLogoGithub } from 'react-icons/io5'
|
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 = () => {
|
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
|
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 OutboundMode = 'rule' | 'global' | 'direct'
|
||||||
type LogLevel = 'info' | 'debug' | 'warn' | 'error' | 'silent'
|
type LogLevel = 'info' | 'debug' | 'warn' | 'error' | 'silent'
|
||||||
|
type SysProxyMode = 'auto' | 'manual'
|
||||||
interface IMihomoVersion {
|
interface IMihomoVersion {
|
||||||
version: string
|
version: string
|
||||||
meta: boolean
|
meta: boolean
|
||||||
|
@ -65,7 +65,8 @@ interface IMihomoConnectionDetail {
|
||||||
|
|
||||||
interface ISysProxyConfig {
|
interface ISysProxyConfig {
|
||||||
enable: boolean
|
enable: boolean
|
||||||
mode?: 'auto' | 'manual'
|
host?: string
|
||||||
|
mode?: SysProxyMode
|
||||||
bypass?: string[]
|
bypass?: string[]
|
||||||
pacScript?: string
|
pacScript?: string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user