mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 04:43:44 +08:00
feat: Support PAC Mode
This commit is contained in:
parent
fc1675575a
commit
b9ec94d835
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@ -5169,7 +5169,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sysproxy"
|
name = "sysproxy"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#1402eba27022a2da7b91b3090d2f4936b6260f10"
|
source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#24e8d46cb338a6a8e28742dea6ed993cd6450780"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"interfaces",
|
"interfaces",
|
||||||
"iptools",
|
"iptools",
|
||||||
|
@ -8,7 +8,7 @@ use crate::{ret_err, wrap_err};
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use sysproxy::Sysproxy;
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
use tauri::{api, Manager};
|
use tauri::{api, Manager};
|
||||||
type CmdResult<T = ()> = Result<T, String>;
|
type CmdResult<T = ()> = Result<T, String>;
|
||||||
|
|
||||||
@ -194,7 +194,6 @@ pub fn grant_permission(_core: String) -> CmdResult {
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
||||||
let current = wrap_err!(Sysproxy::get_system_proxy())?;
|
let current = wrap_err!(Sysproxy::get_system_proxy())?;
|
||||||
|
|
||||||
let mut map = Mapping::new();
|
let mut map = Mapping::new();
|
||||||
map.insert("enable".into(), current.enable.into());
|
map.insert("enable".into(), current.enable.into());
|
||||||
map.insert(
|
map.insert(
|
||||||
@ -206,6 +205,18 @@ pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
|||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the system proxy
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_auto_proxy() -> CmdResult<Mapping> {
|
||||||
|
let current = wrap_err!(Autoproxy::get_auto_proxy())?;
|
||||||
|
|
||||||
|
let mut map = Mapping::new();
|
||||||
|
map.insert("enable".into(), current.enable.into());
|
||||||
|
map.insert("url".into(), current.url.into());
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
|
pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
|
||||||
Ok(logger::Logger::global().get_log())
|
Ok(logger::Logger::global().get_log())
|
||||||
|
@ -13,3 +13,8 @@ pub use self::prfitem::*;
|
|||||||
pub use self::profiles::*;
|
pub use self::profiles::*;
|
||||||
pub use self::runtime::*;
|
pub use self::runtime::*;
|
||||||
pub use self::verge::*;
|
pub use self::verge::*;
|
||||||
|
|
||||||
|
pub const DEFAULT_PAC: &str = r#"function FindProxyForURL(url, host) {
|
||||||
|
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;"
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::config::DEFAULT_PAC;
|
||||||
use crate::utils::{dirs, help};
|
use crate::utils::{dirs, help};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
@ -80,6 +81,12 @@ pub struct IVerge {
|
|||||||
/// proxy guard duration
|
/// proxy guard duration
|
||||||
pub proxy_guard_duration: Option<u64>,
|
pub proxy_guard_duration: Option<u64>,
|
||||||
|
|
||||||
|
/// use pac mode
|
||||||
|
pub proxy_auto_config: Option<bool>,
|
||||||
|
|
||||||
|
/// pac script content
|
||||||
|
pub pac_file_content: Option<String>,
|
||||||
|
|
||||||
/// theme setting
|
/// theme setting
|
||||||
pub theme_setting: Option<IVergeTheme>,
|
pub theme_setting: Option<IVergeTheme>,
|
||||||
|
|
||||||
@ -211,6 +218,8 @@ impl IVerge {
|
|||||||
enable_auto_launch: Some(false),
|
enable_auto_launch: Some(false),
|
||||||
enable_silent_start: Some(false),
|
enable_silent_start: Some(false),
|
||||||
enable_system_proxy: Some(false),
|
enable_system_proxy: Some(false),
|
||||||
|
proxy_auto_config: Some(false),
|
||||||
|
pac_file_content: Some(DEFAULT_PAC.into()),
|
||||||
enable_random_port: Some(false),
|
enable_random_port: Some(false),
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
verge_redir_port: Some(7895),
|
verge_redir_port: Some(7895),
|
||||||
@ -290,6 +299,8 @@ impl IVerge {
|
|||||||
patch!(enable_proxy_guard);
|
patch!(enable_proxy_guard);
|
||||||
patch!(system_proxy_bypass);
|
patch!(system_proxy_bypass);
|
||||||
patch!(proxy_guard_duration);
|
patch!(proxy_guard_duration);
|
||||||
|
patch!(proxy_auto_config);
|
||||||
|
patch!(pac_file_content);
|
||||||
|
|
||||||
patch!(theme_setting);
|
patch!(theme_setting);
|
||||||
patch!(web_ui_list);
|
patch!(web_ui_list);
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
use crate::{config::Config, log_err};
|
use crate::{
|
||||||
|
config::{Config, IVerge},
|
||||||
|
log_err,
|
||||||
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::env::current_exe;
|
use std::env::current_exe;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use sysproxy::Sysproxy;
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
use tauri::async_runtime::Mutex as TokioMutex;
|
use tauri::async_runtime::Mutex as TokioMutex;
|
||||||
|
|
||||||
pub struct Sysopt {
|
pub struct Sysopt {
|
||||||
@ -16,6 +19,13 @@ pub struct Sysopt {
|
|||||||
/// recover it when exit
|
/// recover it when exit
|
||||||
old_sysproxy: Arc<Mutex<Option<Sysproxy>>>,
|
old_sysproxy: Arc<Mutex<Option<Sysproxy>>>,
|
||||||
|
|
||||||
|
/// current auto proxy setting
|
||||||
|
cur_autoproxy: Arc<Mutex<Option<Autoproxy>>>,
|
||||||
|
|
||||||
|
/// record the original auto proxy
|
||||||
|
/// recover it when exit
|
||||||
|
old_autoproxy: Arc<Mutex<Option<Autoproxy>>>,
|
||||||
|
|
||||||
/// helps to auto launch the app
|
/// helps to auto launch the app
|
||||||
auto_launch: Arc<Mutex<Option<AutoLaunch>>>,
|
auto_launch: Arc<Mutex<Option<AutoLaunch>>>,
|
||||||
|
|
||||||
@ -38,6 +48,8 @@ impl Sysopt {
|
|||||||
SYSOPT.get_or_init(|| Sysopt {
|
SYSOPT.get_or_init(|| Sysopt {
|
||||||
cur_sysproxy: Arc::new(Mutex::new(None)),
|
cur_sysproxy: Arc::new(Mutex::new(None)),
|
||||||
old_sysproxy: Arc::new(Mutex::new(None)),
|
old_sysproxy: Arc::new(Mutex::new(None)),
|
||||||
|
cur_autoproxy: Arc::new(Mutex::new(None)),
|
||||||
|
old_autoproxy: Arc::new(Mutex::new(None)),
|
||||||
auto_launch: Arc::new(Mutex::new(None)),
|
auto_launch: Arc::new(Mutex::new(None)),
|
||||||
guard_state: Arc::new(TokioMutex::new(false)),
|
guard_state: Arc::new(TokioMutex::new(false)),
|
||||||
})
|
})
|
||||||
@ -49,38 +61,77 @@ impl Sysopt {
|
|||||||
.latest()
|
.latest()
|
||||||
.verge_mixed_port
|
.verge_mixed_port
|
||||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
let pac_port = IVerge::get_singleton_port();
|
||||||
|
|
||||||
let (enable, bypass) = {
|
let (enable, bypass, pac) = {
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
verge.enable_system_proxy.unwrap_or(false),
|
verge.enable_system_proxy.unwrap_or(false),
|
||||||
verge.system_proxy_bypass.clone(),
|
verge.system_proxy_bypass.clone(),
|
||||||
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
if pac {
|
||||||
let current = Sysproxy {
|
let sys = Sysproxy {
|
||||||
enable,
|
enable: false,
|
||||||
host: String::from("127.0.0.1"),
|
host: String::from("127.0.0.1"),
|
||||||
port,
|
port,
|
||||||
bypass: match bypass {
|
bypass: match bypass {
|
||||||
Some(bypass) => {
|
Some(bypass) => {
|
||||||
if bypass.is_empty() {
|
if bypass.is_empty() {
|
||||||
DEFAULT_BYPASS.into()
|
DEFAULT_BYPASS.into()
|
||||||
} else {
|
} else {
|
||||||
bypass
|
bypass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
None => DEFAULT_BYPASS.into(),
|
||||||
None => DEFAULT_BYPASS.into(),
|
},
|
||||||
},
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if enable {
|
|
||||||
let old = Sysproxy::get_system_proxy().ok();
|
let old = Sysproxy::get_system_proxy().ok();
|
||||||
current.set_system_proxy()?;
|
sys.set_system_proxy()?;
|
||||||
|
|
||||||
*self.old_sysproxy.lock() = old;
|
*self.old_sysproxy.lock() = old;
|
||||||
*self.cur_sysproxy.lock() = Some(current);
|
*self.cur_sysproxy.lock() = Some(sys);
|
||||||
|
let auto = Autoproxy {
|
||||||
|
enable,
|
||||||
|
url: format!("http://127.0.0.1:{pac_port}/commands/pac"),
|
||||||
|
};
|
||||||
|
let old = Autoproxy::get_auto_proxy().ok();
|
||||||
|
auto.set_auto_proxy()?;
|
||||||
|
|
||||||
|
*self.old_autoproxy.lock() = old;
|
||||||
|
*self.cur_autoproxy.lock() = Some(auto);
|
||||||
|
} else {
|
||||||
|
let auto = Autoproxy {
|
||||||
|
enable: false,
|
||||||
|
url: String::new(),
|
||||||
|
};
|
||||||
|
let old = Autoproxy::get_auto_proxy().ok();
|
||||||
|
auto.set_auto_proxy()?;
|
||||||
|
|
||||||
|
*self.old_autoproxy.lock() = old;
|
||||||
|
*self.cur_autoproxy.lock() = Some(auto);
|
||||||
|
let sys = Sysproxy {
|
||||||
|
enable,
|
||||||
|
host: String::from("127.0.0.1"),
|
||||||
|
port,
|
||||||
|
bypass: match bypass {
|
||||||
|
Some(bypass) => {
|
||||||
|
if bypass.is_empty() {
|
||||||
|
DEFAULT_BYPASS.into()
|
||||||
|
} else {
|
||||||
|
bypass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => DEFAULT_BYPASS.into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let old = Sysproxy::get_system_proxy().ok();
|
||||||
|
sys.set_system_proxy()?;
|
||||||
|
|
||||||
|
*self.old_sysproxy.lock() = old;
|
||||||
|
*self.cur_sysproxy.lock() = Some(sys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the system proxy guard
|
// run the system proxy guard
|
||||||
@ -92,24 +143,38 @@ impl Sysopt {
|
|||||||
pub fn update_sysproxy(&self) -> Result<()> {
|
pub fn update_sysproxy(&self) -> Result<()> {
|
||||||
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
||||||
let old_sysproxy = self.old_sysproxy.lock();
|
let old_sysproxy = self.old_sysproxy.lock();
|
||||||
|
let mut cur_autoproxy = self.cur_autoproxy.lock();
|
||||||
|
let old_autoproxy = self.old_autoproxy.lock();
|
||||||
|
|
||||||
if cur_sysproxy.is_none() || old_sysproxy.is_none() {
|
let (enable, bypass, pac) = {
|
||||||
drop(cur_sysproxy);
|
|
||||||
drop(old_sysproxy);
|
|
||||||
return self.init_sysproxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
let (enable, bypass) = {
|
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
verge.enable_system_proxy.unwrap_or(false),
|
verge.enable_system_proxy.unwrap_or(false),
|
||||||
verge.system_proxy_bypass.clone(),
|
verge.system_proxy_bypass.clone(),
|
||||||
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let mut sysproxy = cur_sysproxy.take().unwrap();
|
if pac {
|
||||||
|
if cur_autoproxy.is_none() || old_autoproxy.is_none() {
|
||||||
|
drop(cur_autoproxy);
|
||||||
|
drop(old_autoproxy);
|
||||||
|
return self.init_sysproxy();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if cur_sysproxy.is_none() || old_sysproxy.is_none() {
|
||||||
|
drop(cur_sysproxy);
|
||||||
|
drop(old_sysproxy);
|
||||||
|
return self.init_sysproxy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let port = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.verge_mixed_port
|
||||||
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
let pac_port = IVerge::get_singleton_port();
|
||||||
|
|
||||||
sysproxy.enable = enable;
|
let mut sysproxy = cur_sysproxy.take().unwrap();
|
||||||
sysproxy.bypass = match bypass {
|
sysproxy.bypass = match bypass {
|
||||||
Some(bypass) => {
|
Some(bypass) => {
|
||||||
if bypass.is_empty() {
|
if bypass.is_empty() {
|
||||||
@ -120,15 +185,26 @@ impl Sysopt {
|
|||||||
}
|
}
|
||||||
None => DEFAULT_BYPASS.into(),
|
None => DEFAULT_BYPASS.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let port = Config::verge()
|
|
||||||
.latest()
|
|
||||||
.verge_mixed_port
|
|
||||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
|
||||||
sysproxy.port = port;
|
sysproxy.port = port;
|
||||||
|
|
||||||
sysproxy.set_system_proxy()?;
|
let mut autoproxy = cur_autoproxy.take().unwrap();
|
||||||
*cur_sysproxy = Some(sysproxy);
|
autoproxy.url = format!("http://127.0.0.1:{pac_port}/commands/pac");
|
||||||
|
|
||||||
|
if pac {
|
||||||
|
sysproxy.enable = false;
|
||||||
|
sysproxy.set_system_proxy()?;
|
||||||
|
*cur_sysproxy = Some(sysproxy);
|
||||||
|
autoproxy.enable = enable;
|
||||||
|
autoproxy.set_auto_proxy()?;
|
||||||
|
*cur_autoproxy = Some(autoproxy);
|
||||||
|
} else {
|
||||||
|
autoproxy.enable = false;
|
||||||
|
autoproxy.set_auto_proxy()?;
|
||||||
|
*cur_autoproxy = Some(autoproxy);
|
||||||
|
sysproxy.enable = enable;
|
||||||
|
sysproxy.set_system_proxy()?;
|
||||||
|
*cur_sysproxy = Some(sysproxy);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,8 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
|||||||
let tun_mode = patch.enable_tun_mode;
|
let tun_mode = patch.enable_tun_mode;
|
||||||
let auto_launch = patch.enable_auto_launch;
|
let auto_launch = patch.enable_auto_launch;
|
||||||
let system_proxy = patch.enable_system_proxy;
|
let system_proxy = patch.enable_system_proxy;
|
||||||
|
let pac = patch.proxy_auto_config;
|
||||||
|
let pac_content = patch.pac_file_content;
|
||||||
let proxy_bypass = patch.system_proxy_bypass;
|
let proxy_bypass = patch.system_proxy_bypass;
|
||||||
let language = patch.language;
|
let language = patch.language;
|
||||||
let port = patch.verge_mixed_port;
|
let port = patch.verge_mixed_port;
|
||||||
@ -219,7 +221,12 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
|||||||
if auto_launch.is_some() {
|
if auto_launch.is_some() {
|
||||||
sysopt::Sysopt::global().update_launch()?;
|
sysopt::Sysopt::global().update_launch()?;
|
||||||
}
|
}
|
||||||
if system_proxy.is_some() || proxy_bypass.is_some() || port.is_some() {
|
if system_proxy.is_some()
|
||||||
|
|| proxy_bypass.is_some()
|
||||||
|
|| port.is_some()
|
||||||
|
|| pac.is_some()
|
||||||
|
|| pac_content.is_some()
|
||||||
|
{
|
||||||
sysopt::Sysopt::global().update_sysproxy()?;
|
sysopt::Sysopt::global().update_sysproxy()?;
|
||||||
sysopt::Sysopt::global().guard_proxy();
|
sysopt::Sysopt::global().guard_proxy();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
// common
|
// common
|
||||||
cmds::get_sys_proxy,
|
cmds::get_sys_proxy,
|
||||||
|
cmds::get_auto_proxy,
|
||||||
cmds::open_app_dir,
|
cmds::open_app_dir,
|
||||||
cmds::open_logs_dir,
|
cmds::open_logs_dir,
|
||||||
cmds::open_web_url,
|
cmds::open_web_url,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
extern crate warp;
|
extern crate warp;
|
||||||
|
|
||||||
use super::resolve;
|
use super::resolve;
|
||||||
use crate::config::IVerge;
|
use crate::config::{Config, IVerge, DEFAULT_PAC};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use port_scanner::local_port_available;
|
use port_scanner::local_port_available;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
@ -64,6 +64,18 @@ pub fn embed_server(app_handle: AppHandle) {
|
|||||||
"ok"
|
"ok"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let pac = warp::path!("commands" / "pac").map(move || {
|
||||||
|
let content = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.pac_file_content
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(DEFAULT_PAC.to_string());
|
||||||
|
let port = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.verge_mixed_port
|
||||||
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
content.replace("%mixed-port%", &format!("{}", port))
|
||||||
|
});
|
||||||
let scheme = warp::path!("commands" / "scheme")
|
let scheme = warp::path!("commands" / "scheme")
|
||||||
.and(warp::query::<QueryParam>())
|
.and(warp::query::<QueryParam>())
|
||||||
.and_then(scheme_handler);
|
.and_then(scheme_handler);
|
||||||
@ -72,7 +84,7 @@ pub fn embed_server(app_handle: AppHandle) {
|
|||||||
resolve::resolve_scheme(query.param).await;
|
resolve::resolve_scheme(query.param).await;
|
||||||
Ok("ok")
|
Ok("ok")
|
||||||
}
|
}
|
||||||
let commands = ping.or(visible).or(scheme);
|
let commands = ping.or(visible).or(pac).or(scheme);
|
||||||
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -10,23 +10,34 @@ import {
|
|||||||
styled,
|
styled,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
|
Button,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
import { getSystemProxy } from "@/services/cmds";
|
import { getSystemProxy, getAutotemProxy } from "@/services/cmds";
|
||||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||||
|
import { Edit } from "@mui/icons-material";
|
||||||
|
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||||
|
const DEFAULT_PAC = `function FindProxyForURL(url, host) {
|
||||||
|
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;"
|
||||||
|
}`;
|
||||||
|
|
||||||
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
const { verge, patchVerge } = useVerge();
|
const { verge, patchVerge } = useVerge();
|
||||||
|
|
||||||
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
||||||
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
||||||
|
|
||||||
|
type AutoProxy = Awaited<ReturnType<typeof getAutotemProxy>>;
|
||||||
|
const [autoproxy, setAutoproxy] = useState<AutoProxy>();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
enable_system_proxy: enabled,
|
enable_system_proxy: enabled,
|
||||||
|
proxy_auto_config,
|
||||||
|
pac_file_content,
|
||||||
enable_proxy_guard,
|
enable_proxy_guard,
|
||||||
system_proxy_bypass,
|
system_proxy_bypass,
|
||||||
proxy_guard_duration,
|
proxy_guard_duration,
|
||||||
@ -36,6 +47,8 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
guard: enable_proxy_guard,
|
guard: enable_proxy_guard,
|
||||||
bypass: system_proxy_bypass,
|
bypass: system_proxy_bypass,
|
||||||
duration: proxy_guard_duration ?? 10,
|
duration: proxy_guard_duration ?? 10,
|
||||||
|
pac: proxy_auto_config,
|
||||||
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
});
|
});
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@ -45,8 +58,11 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
guard: enable_proxy_guard,
|
guard: enable_proxy_guard,
|
||||||
bypass: system_proxy_bypass,
|
bypass: system_proxy_bypass,
|
||||||
duration: proxy_guard_duration ?? 10,
|
duration: proxy_guard_duration ?? 10,
|
||||||
|
pac: proxy_auto_config,
|
||||||
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
});
|
});
|
||||||
getSystemProxy().then((p) => setSysproxy(p));
|
getSystemProxy().then((p) => setSysproxy(p));
|
||||||
|
getAutotemProxy().then((p) => setAutoproxy(p));
|
||||||
},
|
},
|
||||||
close: () => setOpen(false),
|
close: () => setOpen(false),
|
||||||
}));
|
}));
|
||||||
@ -68,6 +84,12 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
if (value.bypass !== system_proxy_bypass) {
|
if (value.bypass !== system_proxy_bypass) {
|
||||||
patch.system_proxy_bypass = value.bypass;
|
patch.system_proxy_bypass = value.bypass;
|
||||||
}
|
}
|
||||||
|
if (value.pac !== proxy_auto_config) {
|
||||||
|
patch.proxy_auto_config = value.pac;
|
||||||
|
}
|
||||||
|
if (value.pac_content !== pac_file_content) {
|
||||||
|
patch.pac_file_content = value.pac_content;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await patchVerge(patch);
|
await patchVerge(patch);
|
||||||
@ -89,6 +111,15 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
onOk={onSave}
|
onOk={onSave}
|
||||||
>
|
>
|
||||||
<List>
|
<List>
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText primary={t("Use PAC Mode")} />
|
||||||
|
<Switch
|
||||||
|
edge="end"
|
||||||
|
disabled={!enabled}
|
||||||
|
checked={value.pac}
|
||||||
|
onChange={(_, e) => setValue((v) => ({ ...v, pac: e }))}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
<ListItemText primary={t("Proxy Guard")} />
|
<ListItemText primary={t("Proxy Guard")} />
|
||||||
<Switch
|
<Switch
|
||||||
@ -117,25 +148,63 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
{!value.pac && (
|
||||||
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
<>
|
||||||
<ListItemText primary={t("Proxy Bypass")} sx={{ padding: "3px 0" }} />
|
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||||
</ListItem>
|
<ListItemText
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
primary={t("Proxy Bypass")}
|
||||||
<TextField
|
sx={{ padding: "3px 0" }}
|
||||||
disabled={!enabled}
|
/>
|
||||||
size="small"
|
</ListItem>
|
||||||
autoComplete="off"
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
multiline
|
<TextField
|
||||||
rows={4}
|
disabled={!enabled}
|
||||||
sx={{ width: "100%" }}
|
size="small"
|
||||||
value={value.bypass}
|
autoComplete="off"
|
||||||
placeholder={sysproxy?.bypass || `-`}
|
multiline
|
||||||
onChange={(e) =>
|
rows={4}
|
||||||
setValue((v) => ({ ...v, bypass: e.target.value }))
|
sx={{ width: "100%" }}
|
||||||
}
|
value={value.bypass}
|
||||||
/>
|
placeholder={sysproxy?.bypass || `-`}
|
||||||
</ListItem>
|
onChange={(e) =>
|
||||||
|
setValue((v) => ({ ...v, bypass: e.target.value }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{value.pac && (
|
||||||
|
<>
|
||||||
|
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("PAC Script Content")}
|
||||||
|
sx={{ padding: "3px 0" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
startIcon={<Edit />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => {
|
||||||
|
setEditorOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("Edit")} PAC
|
||||||
|
</Button>
|
||||||
|
<EditorViewer
|
||||||
|
title={`${t("Edit")} PAC`}
|
||||||
|
mode="text"
|
||||||
|
property={value.pac_content ?? ""}
|
||||||
|
open={editorOpen}
|
||||||
|
language="javascript"
|
||||||
|
onChange={(content) => {
|
||||||
|
setValue((v) => ({ ...v, pac_content: content ?? "" }));
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setEditorOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Box sx={{ mt: 2.5 }}>
|
<Box sx={{ mt: 2.5 }}>
|
||||||
@ -146,29 +215,42 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
<FlexBox>
|
<FlexBox>
|
||||||
<Typography className="label">{t("Enable status")}</Typography>
|
<Typography className="label">{t("Enable status")}</Typography>
|
||||||
<Typography className="value">
|
<Typography className="value">
|
||||||
{(!!sysproxy?.enable).toString()}
|
{value.pac
|
||||||
|
? (!!autoproxy?.enable).toString()
|
||||||
|
: (!!sysproxy?.enable).toString()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
|
{!value.pac && (
|
||||||
|
<>
|
||||||
|
<FlexBox>
|
||||||
|
<Typography className="label">{t("Server Addr")}</Typography>
|
||||||
|
<Typography className="value">
|
||||||
|
{sysproxy?.server || "-"}
|
||||||
|
</Typography>
|
||||||
|
</FlexBox>
|
||||||
|
|
||||||
<FlexBox>
|
<FlexBox>
|
||||||
<Typography className="label">{t("Server Addr")}</Typography>
|
<Typography className="label">{t("Bypass")}</Typography>
|
||||||
<Typography className="value">{sysproxy?.server || "-"}</Typography>
|
</FlexBox>
|
||||||
</FlexBox>
|
<FlexBox>
|
||||||
|
<TextField
|
||||||
<FlexBox>
|
disabled={true}
|
||||||
<Typography className="label">{t("Bypass")}</Typography>
|
size="small"
|
||||||
</FlexBox>
|
autoComplete="off"
|
||||||
<FlexBox>
|
multiline
|
||||||
<TextField
|
rows={4}
|
||||||
disabled={true}
|
sx={{ width: "100%" }}
|
||||||
size="small"
|
value={sysproxy?.bypass || "-"}
|
||||||
autoComplete="off"
|
/>
|
||||||
multiline
|
</FlexBox>
|
||||||
rows={4}
|
</>
|
||||||
sx={{ width: "100%" }}
|
)}
|
||||||
value={sysproxy?.bypass || "-"}
|
{value.pac && (
|
||||||
/>
|
<FlexBox>
|
||||||
</FlexBox>
|
<Typography className="label">{t("PAC URL")}</Typography>
|
||||||
|
<Typography className="value">{autoproxy?.url || "-"}</Typography>
|
||||||
|
</FlexBox>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "System Proxy Setting",
|
"System Proxy Setting": "System Proxy Setting",
|
||||||
"Open UWP tool": "Open UWP tool",
|
"Open UWP tool": "Open UWP tool",
|
||||||
"Update GeoData": "Update GeoData",
|
"Update GeoData": "Update GeoData",
|
||||||
|
"Use PAC Mode": "Use PAC Mode",
|
||||||
|
"PAC URL": "PAC URL",
|
||||||
|
"PAC Script Content": "PAC Script Content",
|
||||||
"Proxy Guard": "Proxy Guard",
|
"Proxy Guard": "Proxy Guard",
|
||||||
"Guard Duration": "Guard Duration",
|
"Guard Duration": "Guard Duration",
|
||||||
"Proxy Bypass": "Proxy Bypass",
|
"Proxy Bypass": "Proxy Bypass",
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
||||||
"Open UWP tool": "باز کردن ابزار UWP",
|
"Open UWP tool": "باز کردن ابزار UWP",
|
||||||
"Update GeoData": "بهروزرسانی GeoData",
|
"Update GeoData": "بهروزرسانی GeoData",
|
||||||
|
"Use PAC Mode": "استفاده از حالت PAC",
|
||||||
|
"PAC URL": "PAC URL",
|
||||||
|
"PAC Script Content": "محتوای اسکریپت PAC",
|
||||||
"Proxy Guard": "محافظ پراکسی",
|
"Proxy Guard": "محافظ پراکسی",
|
||||||
"Guard Duration": "مدت محافظت",
|
"Guard Duration": "مدت محافظت",
|
||||||
"Proxy Bypass": "دور زدن پراکسی",
|
"Proxy Bypass": "دور زدن پراکسی",
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "Настройка системного прокси",
|
"System Proxy Setting": "Настройка системного прокси",
|
||||||
"Open UWP tool": "Открыть UWP инструмент",
|
"Open UWP tool": "Открыть UWP инструмент",
|
||||||
"Update GeoData": "Обновление GeoData",
|
"Update GeoData": "Обновление GeoData",
|
||||||
|
"Use PAC Mode": "Используйте режим PAC.",
|
||||||
|
"PAC URL": "Адрес PAC",
|
||||||
|
"PAC Script Content": "Содержание сценария PAC",
|
||||||
"Proxy Guard": "Защита прокси",
|
"Proxy Guard": "Защита прокси",
|
||||||
"Guard Duration": "Период защиты",
|
"Guard Duration": "Период защиты",
|
||||||
"Proxy Bypass": "Игнорирование прокси",
|
"Proxy Bypass": "Игнорирование прокси",
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "系统代理设置",
|
"System Proxy Setting": "系统代理设置",
|
||||||
"Open UWP tool": "UWP 工具",
|
"Open UWP tool": "UWP 工具",
|
||||||
"Update GeoData": "更新 GeoData",
|
"Update GeoData": "更新 GeoData",
|
||||||
|
"Use PAC Mode": "使用PAC模式",
|
||||||
|
"PAC URL": "PAC 地址",
|
||||||
|
"PAC Script Content": "PAC 脚本内容",
|
||||||
"Proxy Guard": "系统代理守卫",
|
"Proxy Guard": "系统代理守卫",
|
||||||
"Guard Duration": "代理守卫间隔",
|
"Guard Duration": "代理守卫间隔",
|
||||||
"Proxy Bypass": "代理绕过",
|
"Proxy Bypass": "代理绕过",
|
||||||
|
@ -127,6 +127,13 @@ export async function getSystemProxy() {
|
|||||||
}>("get_sys_proxy");
|
}>("get_sys_proxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAutotemProxy() {
|
||||||
|
return invoke<{
|
||||||
|
enable: boolean;
|
||||||
|
url: string;
|
||||||
|
}>("get_auto_proxy");
|
||||||
|
}
|
||||||
|
|
||||||
export async function changeClashCore(clashCore: string) {
|
export async function changeClashCore(clashCore: string) {
|
||||||
return invoke<any>("change_clash_core", { clashCore });
|
return invoke<any>("change_clash_core", { clashCore });
|
||||||
}
|
}
|
||||||
|
2
src/services/types.d.ts
vendored
2
src/services/types.d.ts
vendored
@ -216,6 +216,8 @@ interface IVergeConfig {
|
|||||||
enable_service_mode?: boolean;
|
enable_service_mode?: boolean;
|
||||||
enable_silent_start?: boolean;
|
enable_silent_start?: boolean;
|
||||||
enable_system_proxy?: boolean;
|
enable_system_proxy?: boolean;
|
||||||
|
proxy_auto_config?: boolean;
|
||||||
|
pac_file_content?: string;
|
||||||
enable_random_port?: boolean;
|
enable_random_port?: boolean;
|
||||||
verge_mixed_port?: number;
|
verge_mixed_port?: number;
|
||||||
verge_socks_port?: number;
|
verge_socks_port?: number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user