添加代理主机的设置,允许代理设置为其他IP(非127.0.0.1) (#2963)

允许下拉选择ip地址(支持IPv6)、localhost、以及当前系统的主机名,同时兼容手工输入
This commit is contained in:
逐雁南飛 2025-04-16 10:22:53 +08:00 committed by GitHub
parent 224096abce
commit d0836781d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 223 additions and 21 deletions

13
src-tauri/Cargo.lock generated
View File

@ -1056,6 +1056,7 @@ dependencies = [
"dirs 6.0.0", "dirs 6.0.0",
"dunce", "dunce",
"futures", "futures",
"gethostname 1.0.1",
"getrandom 0.3.2", "getrandom 0.3.2",
"image", "image",
"imageproc", "imageproc",
@ -2416,6 +2417,16 @@ dependencies = [
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
[[package]]
name = "gethostname"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed7131e57abbde63513e0e6636f76668a1ca9798dcae2df4e283cae9ee83859e"
dependencies = [
"rustix 1.0.3",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.1.16" version = "0.1.16"
@ -9319,7 +9330,7 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
dependencies = [ dependencies = [
"gethostname", "gethostname 0.4.3",
"rustix 0.38.44", "rustix 0.38.44",
"x11rb-protocol", "x11rb-protocol",
] ]

View File

@ -75,6 +75,7 @@ mihomo_api = { path = "src_crates/crate_mihomo_api" }
ab_glyph = "0.2.29" ab_glyph = "0.2.29"
tungstenite = "0.26.2" tungstenite = "0.26.2"
libc = "0.2" libc = "0.2"
gethostname = "1.0.1"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
runas = "=1.2.0" runas = "=1.2.0"

View File

@ -31,6 +31,25 @@ pub fn get_auto_proxy() -> CmdResult<Mapping> {
Ok(map) Ok(map)
} }
/// 获取系统主机名
#[tauri::command]
pub fn get_system_hostname() -> CmdResult<String> {
use gethostname::gethostname;
// 获取系统主机名处理可能的非UTF-8字符
let hostname = match gethostname().into_string() {
Ok(name) => name,
Err(os_string) => {
// 对于包含非UTF-8的主机名使用调试格式化
let fallback = format!("{:?}", os_string);
// 去掉可能存在的引号
fallback.trim_matches('"').to_string()
}
};
Ok(hostname)
}
/// 获取网络接口列表 /// 获取网络接口列表
#[tauri::command] #[tauri::command]
pub fn get_network_interfaces() -> Vec<String> { pub fn get_network_interfaces() -> Vec<String> {

View File

@ -88,6 +88,9 @@ pub struct IVerge {
/// pac script content /// pac script content
pub pac_file_content: Option<String>, pub pac_file_content: Option<String>,
/// proxy host address
pub proxy_host: Option<String>,
/// theme setting /// theme setting
pub theme_setting: Option<IVergeTheme>, pub theme_setting: Option<IVergeTheme>,
@ -275,6 +278,7 @@ impl IVerge {
enable_system_proxy: Some(false), enable_system_proxy: Some(false),
proxy_auto_config: Some(false), proxy_auto_config: Some(false),
pac_file_content: Some(DEFAULT_PAC.into()), pac_file_content: Some(DEFAULT_PAC.into()),
proxy_host: Some("127.0.0.1".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),
@ -368,7 +372,7 @@ impl IVerge {
patch!(proxy_guard_duration); patch!(proxy_guard_duration);
patch!(proxy_auto_config); patch!(proxy_auto_config);
patch!(pac_file_content); patch!(pac_file_content);
patch!(proxy_host);
patch!(theme_setting); patch!(theme_setting);
patch!(web_ui_list); patch!(web_ui_list);
patch!(clash_core); patch!(clash_core);
@ -452,6 +456,7 @@ pub struct IVergeResponse {
pub proxy_guard_duration: Option<u64>, pub proxy_guard_duration: Option<u64>,
pub proxy_auto_config: Option<bool>, pub proxy_auto_config: Option<bool>,
pub pac_file_content: Option<String>, pub pac_file_content: Option<String>,
pub proxy_host: Option<String>,
pub theme_setting: Option<IVergeTheme>, pub theme_setting: Option<IVergeTheme>,
pub web_ui_list: Option<Vec<String>>, pub web_ui_list: Option<Vec<String>>,
pub clash_core: Option<String>, pub clash_core: Option<String>,
@ -520,6 +525,7 @@ impl From<IVerge> for IVergeResponse {
proxy_guard_duration: verge.proxy_guard_duration, proxy_guard_duration: verge.proxy_guard_duration,
proxy_auto_config: verge.proxy_auto_config, proxy_auto_config: verge.proxy_auto_config,
pac_file_content: verge.pac_file_content, pac_file_content: verge.pac_file_content,
proxy_host: verge.proxy_host,
theme_setting: verge.theme_setting, theme_setting: verge.theme_setting,
web_ui_list: verge.web_ui_list, web_ui_list: verge.web_ui_list,
clash_core: verge.clash_core, clash_core: verge.clash_core,

View File

@ -76,12 +76,13 @@ impl Sysopt {
.unwrap_or(Config::clash().data().get_mixed_port()); .unwrap_or(Config::clash().data().get_mixed_port());
let pac_port = IVerge::get_singleton_port(); let pac_port = IVerge::get_singleton_port();
let (sys_enable, pac_enable) = { let (sys_enable, pac_enable, proxy_host) = {
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.proxy_auto_config.unwrap_or(false), verge.proxy_auto_config.unwrap_or(false),
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
) )
}; };
@ -89,13 +90,13 @@ impl Sysopt {
{ {
let mut sys = Sysproxy { let mut sys = Sysproxy {
enable: false, enable: false,
host: String::from("127.0.0.1"), host: proxy_host.clone(),
port, port,
bypass: get_bypass(), bypass: get_bypass(),
}; };
let mut auto = Autoproxy { let mut auto = Autoproxy {
enable: false, enable: false,
url: format!("http://127.0.0.1:{pac_port}/commands/pac"), url: format!("http://{}:{}/commands/pac", proxy_host, pac_port),
}; };
if !sys_enable { if !sys_enable {
@ -139,7 +140,7 @@ impl Sysopt {
let shell = app_handle.shell(); let shell = app_handle.shell();
let output = if pac_enable { let output = if pac_enable {
let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port); let address = format!("http://{}:{}/commands/pac", proxy_host, pac_port);
let output = shell let output = shell
.command(sysproxy_exe.as_path().to_str().unwrap()) .command(sysproxy_exe.as_path().to_str().unwrap())
.args(["pac", address.as_str()]) .args(["pac", address.as_str()])
@ -148,7 +149,7 @@ impl Sysopt {
.unwrap(); .unwrap();
output output
} else { } else {
let address = format!("{}:{}", "127.0.0.1", port); let address = format!("{}:{}", proxy_host, port);
let bypass = get_bypass(); let bypass = get_bypass();
let output = shell let output = shell
.command(sysproxy_exe.as_path().to_str().unwrap()) .command(sysproxy_exe.as_path().to_str().unwrap())
@ -256,7 +257,7 @@ impl Sysopt {
loop { loop {
sleep(Duration::from_secs(wait_secs)).await; sleep(Duration::from_secs(wait_secs)).await;
let (enable, guard, guard_duration, pac) = { let (enable, guard, guard_duration, pac, proxy_host) = {
let verge = Config::verge(); let verge = Config::verge();
let verge = verge.latest(); let verge = verge.latest();
( (
@ -264,6 +265,7 @@ impl Sysopt {
verge.enable_proxy_guard.unwrap_or(false), verge.enable_proxy_guard.unwrap_or(false),
verge.proxy_guard_duration.unwrap_or(10), verge.proxy_guard_duration.unwrap_or(10),
verge.proxy_auto_config.unwrap_or(false), verge.proxy_auto_config.unwrap_or(false),
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
) )
}; };
@ -303,13 +305,13 @@ impl Sysopt {
if pac { if pac {
let autoproxy = Autoproxy { let autoproxy = Autoproxy {
enable: true, enable: true,
url: format!("http://127.0.0.1:{pac_port}/commands/pac"), url: format!("http://{}:{}/commands/pac", proxy_host, pac_port),
}; };
logging_error!(Type::System, true, autoproxy.set_auto_proxy()); logging_error!(Type::System, true, autoproxy.set_auto_proxy());
} else { } else {
let sysproxy = Sysproxy { let sysproxy = Sysproxy {
enable: true, enable: true,
host: "127.0.0.1".into(), host: proxy_host.into(),
port, port,
bypass: get_bypass(), bypass: get_bypass(),
}; };
@ -333,7 +335,7 @@ impl Sysopt {
let shell = app_handle.shell(); let shell = app_handle.shell();
let output = if pac { let output = if pac {
let address = format!("http://{}:{}/commands/pac", "127.0.0.1", pac_port); let address = format!("http://{}:{}/commands/pac", proxy_host, pac_port);
shell shell
.command(sysproxy_exe.as_path().to_str().unwrap()) .command(sysproxy_exe.as_path().to_str().unwrap())
@ -342,7 +344,7 @@ impl Sysopt {
.await .await
.unwrap() .unwrap()
} else { } else {
let address = format!("{}:{}", "127.0.0.1", port); let address = format!("{}:{}", proxy_host, port);
let bypass = get_bypass(); let bypass = get_bypass();
shell shell

View File

@ -63,9 +63,14 @@ pub fn toggle_tun_mode(not_save_file: Option<bool>) {
/// Copy proxy environment variables to clipboard /// Copy proxy environment variables to clipboard
pub fn copy_clash_env() { pub fn copy_clash_env() {
// 从环境变量获取IP地址默认127.0.0.1 // 从环境变量获取IP地址如果没有则从配置中获取 proxy_host默认为 127.0.0.1
let clash_verge_rev_ip = let clash_verge_rev_ip = env::var("CLASH_VERGE_REV_IP").unwrap_or_else(|_| {
env::var("CLASH_VERGE_REV_IP").unwrap_or_else(|_| "127.0.0.1".to_string()); Config::verge()
.latest()
.proxy_host
.clone()
.unwrap_or_else(|| "127.0.0.1".to_string())
});
let app_handle = handle::Handle::global().app_handle().unwrap(); let app_handle = handle::Handle::global().app_handle().unwrap();
let port = { Config::verge().latest().verge_mixed_port.unwrap_or(7897) }; let port = { Config::verge().latest().verge_mixed_port.unwrap_or(7897) };

View File

@ -156,6 +156,7 @@ pub fn run() {
cmd::open_core_dir, cmd::open_core_dir,
cmd::get_portable_flag, cmd::get_portable_flag,
cmd::get_network_interfaces, cmd::get_network_interfaces,
cmd::get_system_hostname,
cmd::restart_core, cmd::restart_core,
cmd::restart_app, cmd::restart_app,
// 添加新的命令 // 添加新的命令

View File

@ -3,10 +3,17 @@ import { BaseFieldset } from "@/components/base/base-fieldset";
import { TooltipIcon } from "@/components/base/base-tooltip-icon"; import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { EditorViewer } from "@/components/profile/editor-viewer"; import { EditorViewer } from "@/components/profile/editor-viewer";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { getAutotemProxy, getSystemProxy } from "@/services/cmds"; import {
getAutotemProxy,
getNetworkInterfaces,
getNetworkInterfacesInfo,
getSystemHostname,
getSystemProxy,
} from "@/services/cmds";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
import { EditRounded } from "@mui/icons-material"; import { EditRounded } from "@mui/icons-material";
import { import {
Autocomplete,
Button, Button,
InputAdornment, InputAdornment,
List, List,
@ -17,10 +24,16 @@ import {
Typography, Typography,
} from "@mui/material"; } from "@mui/material";
import { useLockFn } from "ahooks"; import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useMemo, useState } from "react"; import {
forwardRef,
useImperativeHandle,
useEffect,
useMemo,
useState,
} from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const DEFAULT_PAC = `function FindProxyForURL(url, host) { const DEFAULT_PAC = `function FindProxyForURL(url, host) {
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;"; return "PROXY %proxy_host%:%mixed-port%; SOCKS5 %proxy_host%:%mixed-port%; DIRECT;";
}`; }`;
/** NO_PROXY validation */ /** NO_PROXY validation */
@ -64,6 +77,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [editorOpen, setEditorOpen] = useState(false); const [editorOpen, setEditorOpen] = useState(false);
const { verge, patchVerge } = useVerge(); const { verge, patchVerge } = useVerge();
const [hostOptions, setHostOptions] = useState<string[]>([]);
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>; type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
const [sysproxy, setSysproxy] = useState<SysProxy>(); const [sysproxy, setSysproxy] = useState<SysProxy>();
@ -79,6 +93,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
use_default_bypass, use_default_bypass,
system_proxy_bypass, system_proxy_bypass,
proxy_guard_duration, proxy_guard_duration,
proxy_host,
} = verge ?? {}; } = verge ?? {};
const [value, setValue] = useState({ const [value, setValue] = useState({
@ -88,6 +103,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
use_default: use_default_bypass ?? true, use_default: use_default_bypass ?? true,
pac: proxy_auto_config, pac: proxy_auto_config,
pac_content: pac_file_content ?? DEFAULT_PAC, pac_content: pac_file_content ?? DEFAULT_PAC,
proxy_host: proxy_host ?? "127.0.0.1",
}); });
const defaultBypass = () => { const defaultBypass = () => {
@ -110,13 +126,74 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
use_default: use_default_bypass ?? true, use_default: use_default_bypass ?? true,
pac: proxy_auto_config, pac: proxy_auto_config,
pac_content: pac_file_content ?? DEFAULT_PAC, pac_content: pac_file_content ?? DEFAULT_PAC,
proxy_host: proxy_host ?? "127.0.0.1",
}); });
getSystemProxy().then((p) => setSysproxy(p)); getSystemProxy().then((p) => setSysproxy(p));
getAutotemProxy().then((p) => setAutoproxy(p)); getAutotemProxy().then((p) => setAutoproxy(p));
fetchNetworkInterfaces();
}, },
close: () => setOpen(false), close: () => setOpen(false),
})); }));
// 获取网络接口和主机名
const fetchNetworkInterfaces = async () => {
try {
// 获取系统网络接口信息
const interfaces = await getNetworkInterfacesInfo();
const ipAddresses: string[] = [];
// 从interfaces中提取IPv4和IPv6地址
interfaces.forEach((iface) => {
iface.addr.forEach((address) => {
if (address.V4 && address.V4.ip) {
ipAddresses.push(address.V4.ip);
}
if (address.V6 && address.V6.ip) {
ipAddresses.push(address.V6.ip);
}
});
});
// 获取当前系统的主机名
let hostname = "";
try {
hostname = await getSystemHostname();
console.log("获取到主机名:", hostname);
} catch (err) {
console.error("获取主机名失败:", err);
}
// 构建选项列表
const options = ["127.0.0.1", "localhost"];
// 确保主机名添加到列表,即使它是空字符串也记录下来
if (hostname) {
// 如果主机名不是localhost或127.0.0.1,则添加它
if (hostname !== "localhost" && hostname !== "127.0.0.1") {
hostname = hostname + ".local";
options.push(hostname);
console.log("主机名已添加到选项中:", hostname);
} else {
console.log("主机名与已有选项重复:", hostname);
}
} else {
console.log("主机名为空");
}
// 添加IP地址
options.push(...ipAddresses);
// 去重
const uniqueOptions = Array.from(new Set(options));
console.log("最终选项列表:", uniqueOptions);
setHostOptions(uniqueOptions);
} catch (error) {
console.error("获取网络接口失败:", error);
// 失败时至少提供基本选项
setHostOptions(["127.0.0.1", "localhost"]);
}
};
const onSave = useLockFn(async () => { const onSave = useLockFn(async () => {
if (value.duration < 1) { if (value.duration < 1) {
Notice.error(t("Proxy Daemon Duration Cannot be Less than 1 Second")); Notice.error(t("Proxy Daemon Duration Cannot be Less than 1 Second"));
@ -127,6 +204,23 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
return; return;
} }
// 修改验证规则允许IP和主机名
const ipv4Regex =
/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
const ipv6Regex =
/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
const hostnameRegex =
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
if (
!ipv4Regex.test(value.proxy_host) &&
!ipv6Regex.test(value.proxy_host) &&
!hostnameRegex.test(value.proxy_host)
) {
Notice.error(t("Invalid Proxy Host Format"));
return;
}
const patch: Partial<IVergeConfig> = {}; const patch: Partial<IVergeConfig> = {};
if (value.guard !== enable_proxy_guard) { if (value.guard !== enable_proxy_guard) {
@ -138,15 +232,34 @@ 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) { if (value.pac !== proxy_auto_config) {
patch.proxy_auto_config = value.pac; patch.proxy_auto_config = value.pac;
} }
if (value.use_default !== use_default_bypass) { if (value.use_default !== use_default_bypass) {
patch.use_default_bypass = value.use_default; patch.use_default_bypass = value.use_default;
} }
if (value.pac_content !== pac_file_content) {
patch.pac_file_content = value.pac_content; let pacContent = value.pac_content;
if (pacContent) {
pacContent = pacContent.replace(/%proxy_host%/g, value.proxy_host);
}
if (pacContent !== pac_file_content) {
patch.pac_file_content = pacContent;
}
// 处理IPv6地址如果是IPv6地址但没有被方括号包围则添加方括号
let proxyHost = value.proxy_host;
if (
ipv6Regex.test(proxyHost) &&
!proxyHost.startsWith("[") &&
!proxyHost.endsWith("]")
) {
proxyHost = `[${proxyHost}]`;
}
if (proxyHost !== proxy_host) {
patch.proxy_host = proxyHost;
} }
try { try {
@ -199,6 +312,31 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
</FlexBox> </FlexBox>
)} )}
</BaseFieldset> </BaseFieldset>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Proxy Host")} />
<Autocomplete
size="small"
sx={{ width: 150 }}
options={hostOptions}
value={value.proxy_host}
freeSolo
renderInput={(params) => (
<TextField {...params} placeholder="127.0.0.1" size="small" />
)}
onChange={(_, newValue) => {
setValue((v) => ({
...v,
proxy_host: newValue || "127.0.0.1",
}));
}}
onInputChange={(_, newInputValue) => {
setValue((v) => ({
...v,
proxy_host: newInputValue || "127.0.0.1",
}));
}}
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}> <ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Use PAC Mode")} /> <ListItemText primary={t("Use PAC Mode")} />
<Switch <Switch

View File

@ -225,6 +225,8 @@
"Enabled": "ممكّن", "Enabled": "ممكّن",
"Disabled": "معطّل", "Disabled": "معطّل",
"Server Addr": "عنوان الخادم:", "Server Addr": "عنوان الخادم:",
"Proxy Host": "مضيف الوكيل",
"Invalid Proxy Host Format": "تنسيق مضيف الوكيل غير صالح",
"Not available": "غير متوفر", "Not available": "غير متوفر",
"Proxy Guard": "حماية الوكيل", "Proxy Guard": "حماية الوكيل",
"Proxy Guard Info": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام", "Proxy Guard Info": "عند التمكين، يمنع برامج أخرى من تعديل إعدادات وكيل النظام",

View File

@ -243,6 +243,8 @@
"Enabled": "Enabled", "Enabled": "Enabled",
"Disabled": "Disabled", "Disabled": "Disabled",
"Server Addr": "Server Addr: ", "Server Addr": "Server Addr: ",
"Proxy Host": "Proxy Host",
"Invalid Proxy Host Format": "Invalid Proxy Host Format",
"Not available": "Not available", "Not available": "Not available",
"Proxy Guard": "Proxy Guard", "Proxy Guard": "Proxy Guard",
"Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings", "Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings",

View File

@ -225,6 +225,8 @@
"Enabled": "توانایی فعال شد", "Enabled": "توانایی فعال شد",
"Disabled": "غیرفعال شد", "Disabled": "غیرفعال شد",
"Server Addr": "آدرس سرور: ", "Server Addr": "آدرس سرور: ",
"Proxy Host": "میزبان پراکسی",
"Invalid Proxy Host Format": "فرمت میزبان پراکسی نامعتبر است",
"Not available": "غیر فعال شد", "Not available": "غیر فعال شد",
"Proxy Guard": "محافظ پراکسی", "Proxy Guard": "محافظ پراکسی",
"Proxy Guard Info": "امکان جلوگیری از نرم‌افزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید", "Proxy Guard Info": "امکان جلوگیری از نرم‌افزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید",

View File

@ -257,6 +257,8 @@
"Enabled": "Diaktifkan", "Enabled": "Diaktifkan",
"Disabled": "Dinonaktifkan", "Disabled": "Dinonaktifkan",
"Server Addr": "Alamat Server: ", "Server Addr": "Alamat Server: ",
"Proxy Host": "Host Proksi",
"Invalid Proxy Host Format": "Format Host Proksi Tidak Valid",
"Not available": "Tidak tersedia", "Not available": "Tidak tersedia",
"Proxy Guard": "Penjaga Proksi", "Proxy Guard": "Penjaga Proksi",
"Proxy Guard Info": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi", "Proxy Guard Info": "Aktifkan untuk mencegah perangkat lunak lain mengubah pengaturan proksi sistem operasi",

View File

@ -240,6 +240,8 @@
"Enabled": "Включено", "Enabled": "Включено",
"Disabled": "Отключено", "Disabled": "Отключено",
"Server Addr": "Адрес сервера: ", "Server Addr": "Адрес сервера: ",
"Proxy Host": "Хост прокси",
"Invalid Proxy Host Format": "Неверный формат хоста прокси",
"Not available": "Недоступно", "Not available": "Недоступно",
"Proxy Guard": "Proxy Guard", "Proxy Guard": "Proxy Guard",
"Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО", "Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим ПО",

View File

@ -225,6 +225,8 @@
"Enabled": "Кушылган", "Enabled": "Кушылган",
"Disabled": "Сүнгән", "Disabled": "Сүнгән",
"Server Addr": "Сервер адресы", "Server Addr": "Сервер адресы",
"Proxy Host": "Прокси хосты",
"Invalid Proxy Host Format": "Прокси хосты форматы дөрес түгел",
"Not available": "Мөмкин түгел", "Not available": "Мөмкин түгел",
"Proxy Guard": "Прокси саклаучы", "Proxy Guard": "Прокси саклаучы",
"Proxy Guard Info": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз", "Proxy Guard Info": "Системалы прокси көйләүләрен чит программа үзгәртмәсен өчен шушы функцияне кабызыгыз",

View File

@ -243,6 +243,8 @@
"Enabled": "已启用", "Enabled": "已启用",
"Disabled": "未启用", "Disabled": "未启用",
"Server Addr": "服务地址:", "Server Addr": "服务地址:",
"Proxy Host": "代理主机",
"Invalid Proxy Host Format": "代理主机格式无效",
"Not available": "不可用", "Not available": "不可用",
"Proxy Guard": "系统代理守卫", "Proxy Guard": "系统代理守卫",
"Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置", "Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置",

View File

@ -265,6 +265,10 @@ export async function getNetworkInterfaces() {
return invoke<string[]>("get_network_interfaces"); return invoke<string[]>("get_network_interfaces");
} }
export async function getSystemHostname() {
return invoke<string>("get_system_hostname");
}
export async function getNetworkInterfacesInfo() { export async function getNetworkInterfacesInfo() {
return invoke<INetworkInterface[]>("get_network_interfaces_info"); return invoke<INetworkInterface[]>("get_network_interfaces_info");
} }

View File

@ -750,6 +750,7 @@ interface IVergeConfig {
enable_external_controller?: boolean; enable_external_controller?: boolean;
proxy_auto_config?: boolean; proxy_auto_config?: boolean;
pac_file_content?: string; pac_file_content?: string;
proxy_host?: 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;