Compare commits
13 Commits
22
README.md
22
README.md
@@ -41,18 +41,18 @@ A Clash Meta GUI based on <a href="https://github.com/tauri-apps/tauri">Tauri</a
|
||||
|
||||
Download from [release](https://github.com/clash-verge-rev/clash-verge-rev/releases). Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
|
||||
|
||||
- [Windows x64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x64-setup.exe)
|
||||
- [Windows x86](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x86-setup.exe)
|
||||
- [Windows arm64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_arm64-setup.exe)
|
||||
- [Windows x64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/Clash.Verge_1.4.7_x64-setup.exe)
|
||||
- [Windows x86](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/Clash.Verge_1.4.7_x86-setup.exe)
|
||||
- [Windows arm64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/Clash.Verge_1.4.7_arm64-setup.exe)
|
||||
|
||||
- [macOS intel](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x64.dmg)
|
||||
- [macOS apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_aarch64.dmg)
|
||||
- [macOS intel](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/Clash.Verge_1.4.7_x64.dmg)
|
||||
- [macOS apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/Clash.Verge_1.4.7_aarch64.dmg)
|
||||
|
||||
- [Linux x64 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_amd64.AppImage)
|
||||
- [Linux x64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_amd64.deb)
|
||||
- [Linux x86 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_i386.AppImage)
|
||||
- [Linux x86 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_i386.deb)
|
||||
- [Linux arm64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_arm64.deb)
|
||||
- [Linux x64 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/clash-verge_1.4.7_amd64.AppImage)
|
||||
- [Linux x64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/clash-verge_1.4.7_amd64.deb)
|
||||
- [Linux x86 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/clash-verge_1.4.7_i386.AppImage)
|
||||
- [Linux x86 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/clash-verge_1.4.7_i386.deb)
|
||||
- [Linux arm64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.7/clash-verge_1.4.7_arm64.deb)
|
||||
|
||||
Or you can build it yourself. Supports Windows, Linux and macOS 10.15+
|
||||
|
||||
@@ -72,7 +72,7 @@ You should install Rust and Nodejs, see [here](https://tauri.app/v1/guides/getti
|
||||
pnpm i
|
||||
```
|
||||
|
||||
Then download the clash binary... Or you can download it from [clash meta release](https://github.com/MetaCubeX/Clash.Meta/releases) and rename it according to [tauri config](https://tauri.studio/docs/api/config/#tauri.bundle.externalBin).
|
||||
Then download the clash binary... Or you can download it from [clash meta release](https://github.com/MetaCubeX/Clash.Meta/releases) and rename it according to [tauri config](https://tauri.app/v1/api/config#bundleconfig.externalbin).
|
||||
|
||||
```shell
|
||||
# force update to latest version
|
||||
|
||||
10
UPDATELOG.md
10
UPDATELOG.md
@@ -1,3 +1,13 @@
|
||||
## v1.4.7
|
||||
|
||||
### Features
|
||||
|
||||
- Windows 便携版禁用应用内更新
|
||||
- 支持代理组 Hidden 选项
|
||||
- 支持 URL Scheme(MacOS & Linux)
|
||||
|
||||
---
|
||||
|
||||
## v1.4.6
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clash-verge",
|
||||
"version": "1.4.6",
|
||||
"version": "1.4.7",
|
||||
"license": "GPL-3.0",
|
||||
"scripts": {
|
||||
"dev": "tauri dev",
|
||||
|
||||
@@ -123,7 +123,7 @@ index 6c207d9..d47dc33 100644
|
||||
- if result == "\"\"" {
|
||||
- anyhow::bail!("main function should return object");
|
||||
- }
|
||||
- return Ok(serde_json::from_str::<Mapping>(result.as_str())?);
|
||||
- Ok(serde_json::from_str::<Mapping>(result.as_str())?)
|
||||
- });
|
||||
-
|
||||
- let mut out = outputs.lock().unwrap();
|
||||
|
||||
@@ -57,7 +57,7 @@ const META_ALPHA_MAP = {
|
||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||
"win32-ia32": "mihomo-windows-386",
|
||||
"win32-arm64": "mihomo-windows-arm64",
|
||||
"darwin-x64": "mihomo-darwin-amd64-cgo",
|
||||
"darwin-x64": "mihomo-darwin-amd64",
|
||||
"darwin-arm64": "mihomo-darwin-arm64",
|
||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||
"linux-ia32": "mihomo-linux-386",
|
||||
@@ -102,7 +102,7 @@ const META_MAP = {
|
||||
"win32-x64": "mihomo-windows-amd64-compatible",
|
||||
"win32-ia32": "mihomo-windows-386",
|
||||
"win32-arm64": "mihomo-windows-arm64",
|
||||
"darwin-x64": "mihomo-darwin-amd64-cgo",
|
||||
"darwin-x64": "mihomo-darwin-amd64",
|
||||
"darwin-arm64": "mihomo-darwin-arm64",
|
||||
"linux-x64": "mihomo-linux-amd64-compatible",
|
||||
"linux-ia32": "mihomo-linux-386",
|
||||
|
||||
54
src-tauri/Cargo.lock
generated
54
src-tauri/Cargo.lock
generated
@@ -28,19 +28,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.2.11",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.10"
|
||||
@@ -580,7 +567,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clash-verge"
|
||||
version = "1.4.6"
|
||||
version = "1.4.7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"auto-launch",
|
||||
@@ -1828,7 +1815,7 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash 0.7.7",
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2182,17 +2169,6 @@ version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||
|
||||
[[package]]
|
||||
name = "iptools"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03bfb870879ce6a141b644653d63b203d290ec5f3b6919cf7b30cba06a164a5"
|
||||
dependencies = [
|
||||
"ahash 0.8.6",
|
||||
"once_cell",
|
||||
"regex 1.10.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-docker"
|
||||
version = "0.2.0"
|
||||
@@ -4492,12 +4468,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sysproxy"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#f8fab6a542c41cf3b973f4fe77d399756e3efff1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9707a79d3b95683aa5a9521e698ffd878b8fb289727c25a69157fb85d529ffff"
|
||||
dependencies = [
|
||||
"interfaces",
|
||||
"iptools",
|
||||
"thiserror",
|
||||
"windows 0.52.0",
|
||||
"winapi",
|
||||
"winreg 0.10.1",
|
||||
]
|
||||
|
||||
@@ -6342,26 +6318,6 @@ dependencies = [
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clash-verge"
|
||||
version = "1.4.6"
|
||||
version = "1.4.7"
|
||||
description = "clash verge"
|
||||
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
||||
license = "GPL-3.0"
|
||||
@@ -14,6 +14,7 @@ tauri-build = { version = "1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
warp = "0.3"
|
||||
sysproxy = "0.3.0"
|
||||
which = "5.0.0"
|
||||
anyhow = "1.0"
|
||||
dirs = "5.0"
|
||||
@@ -38,7 +39,6 @@ window-shadows = { version = "0.2" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
reqwest = { version = "0.11", features = ["json", "rustls-tls"] }
|
||||
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||
tauri = { version = "1.5", features = [ "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
||||
17
src-tauri/Info.plist
Normal file
17
src-tauri/Info.plist
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>io.github.clash-verge-rev.clash-verge-rev</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>clash</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
9
src-tauri/clash-verge.desktop
Normal file
9
src-tauri/clash-verge.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Categories={{{categories}}}
|
||||
Comment={{{comment}}}
|
||||
Exec={{{exec}}} %u
|
||||
Icon={{{icon}}}
|
||||
Name={{{name}}}
|
||||
Terminal=false
|
||||
Type=Application
|
||||
MimeType=x-scheme-handler/clash;
|
||||
@@ -219,7 +219,7 @@ pub fn open_app_dir() -> CmdResult<()> {
|
||||
#[tauri::command]
|
||||
pub fn open_core_dir() -> CmdResult<()> {
|
||||
let core_dir = wrap_err!(tauri::utils::platform::current_exe())?;
|
||||
let core_dir = core_dir.parent().ok_or(format!("failed to get core dir"))?;
|
||||
let core_dir = core_dir.parent().ok_or("failed to get core dir")?;
|
||||
wrap_err!(open::that(core_dir))
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ pub async fn clash_api_get_proxy_delay(
|
||||
) -> CmdResult<clash_api::DelayRes> {
|
||||
match clash_api::get_proxy_delay(name, url).await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => Err(format!("{}", err.to_string())),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ impl IClashTemp {
|
||||
let config = &self.0;
|
||||
|
||||
ClashInfo {
|
||||
port: Self::guard_mixed_port(&config),
|
||||
server: Self::guard_client_ctrl(&config),
|
||||
port: Self::guard_mixed_port(config),
|
||||
server: Self::guard_client_ctrl(config),
|
||||
secret: config.get("secret").and_then(|value| match value {
|
||||
Value::String(val_str) => Some(val_str.clone()),
|
||||
Value::Bool(val_bool) => Some(val_bool.to_string()),
|
||||
@@ -98,7 +98,7 @@ impl IClashTemp {
|
||||
Some(val_str) => {
|
||||
let val_str = val_str.trim();
|
||||
|
||||
let val = match val_str.starts_with(":") {
|
||||
let val = match val_str.starts_with(':') {
|
||||
true => format!("127.0.0.1{val_str}"),
|
||||
false => val_str.to_owned(),
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ use sysproxy::Sysproxy;
|
||||
|
||||
use super::Config;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
||||
pub struct PrfItem {
|
||||
pub uid: Option<String>,
|
||||
|
||||
@@ -101,24 +101,6 @@ impl PrfOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PrfItem {
|
||||
fn default() -> Self {
|
||||
PrfItem {
|
||||
uid: None,
|
||||
itype: None,
|
||||
name: None,
|
||||
desc: None,
|
||||
file: None,
|
||||
url: None,
|
||||
selected: None,
|
||||
extra: None,
|
||||
updated: None,
|
||||
option: None,
|
||||
file_data: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrfItem {
|
||||
/// From partial item
|
||||
/// must contain `itype`
|
||||
@@ -188,7 +170,7 @@ impl PrfItem {
|
||||
let opt_ref = option.as_ref();
|
||||
let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
|
||||
let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
|
||||
let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone());
|
||||
let user_agent = opt_ref.and_then(|o| o.user_agent.clone());
|
||||
|
||||
let mut builder = reqwest::ClientBuilder::new().use_rustls_tls().no_proxy();
|
||||
|
||||
@@ -213,27 +195,24 @@ impl PrfItem {
|
||||
}
|
||||
// 使用系统代理
|
||||
else if with_proxy {
|
||||
match Sysproxy::get_system_proxy() {
|
||||
Ok(p @ Sysproxy { enable: true, .. }) => {
|
||||
let proxy_scheme = format!("http://{}:{}", p.host, p.port);
|
||||
if let Ok(p @ Sysproxy { enable: true, .. }) = Sysproxy::get_system_proxy() {
|
||||
let proxy_scheme = format!("http://{}:{}", p.host, p.port);
|
||||
|
||||
if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
if let Ok(proxy) = reqwest::Proxy::http(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
if let Ok(proxy) = reqwest::Proxy::https(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
if let Ok(proxy) = reqwest::Proxy::all(&proxy_scheme) {
|
||||
builder = builder.proxy(proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let version = match VERSION.get() {
|
||||
Some(v) => format!("clash-verge/v{}", v),
|
||||
None => format!("clash-verge/unknown"),
|
||||
None => "clash-verge/unknown".to_string(),
|
||||
};
|
||||
|
||||
builder = builder.user_agent(user_agent.unwrap_or(version));
|
||||
|
||||
@@ -37,13 +37,13 @@ impl IProfiles {
|
||||
profiles.items = Some(vec![]);
|
||||
}
|
||||
// compatible with the old old old version
|
||||
profiles.items.as_mut().map(|items| {
|
||||
if let Some(items) = profiles.items.as_mut() {
|
||||
for item in items.iter_mut() {
|
||||
if item.uid.is_none() {
|
||||
item.uid = Some(help::get_uid("d"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
profiles
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -152,17 +152,19 @@ impl IProfiles {
|
||||
self.items = Some(vec![]);
|
||||
}
|
||||
|
||||
self.items.as_mut().map(|items| items.push(item));
|
||||
if let Some(items) = self.items.as_mut() {
|
||||
items.push(item)
|
||||
}
|
||||
self.save_file()
|
||||
}
|
||||
|
||||
/// reorder items
|
||||
pub fn reorder(&mut self, active_id: String, over_id: String) -> Result<()> {
|
||||
let mut items = self.items.take().unwrap_or(vec![]);
|
||||
let mut items = self.items.take().unwrap_or_default();
|
||||
let mut old_index = None;
|
||||
let mut new_index = None;
|
||||
|
||||
for i in 0..items.len() {
|
||||
for (i, _) in items.iter().enumerate() {
|
||||
if items[i].uid == Some(active_id.clone()) {
|
||||
old_index = Some(i);
|
||||
}
|
||||
@@ -182,7 +184,7 @@ impl IProfiles {
|
||||
|
||||
/// update the item value
|
||||
pub fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> {
|
||||
let mut items = self.items.take().unwrap_or(vec![]);
|
||||
let mut items = self.items.take().unwrap_or_default();
|
||||
|
||||
for each in items.iter_mut() {
|
||||
if each.uid == Some(uid.clone()) {
|
||||
@@ -255,11 +257,11 @@ impl IProfiles {
|
||||
let current = self.current.as_ref().unwrap_or(&uid);
|
||||
let current = current.clone();
|
||||
|
||||
let mut items = self.items.take().unwrap_or(vec![]);
|
||||
let mut items = self.items.take().unwrap_or_default();
|
||||
let mut index = None;
|
||||
|
||||
// get the index
|
||||
for i in 0..items.len() {
|
||||
for (i, _) in items.iter().enumerate() {
|
||||
if items[i].uid == Some(uid.clone()) {
|
||||
index = Some(i);
|
||||
break;
|
||||
@@ -267,19 +269,19 @@ impl IProfiles {
|
||||
}
|
||||
|
||||
if let Some(index) = index {
|
||||
items.remove(index).file.map(|file| {
|
||||
if let Some(file) = items.remove(index).file {
|
||||
let _ = dirs::app_profiles_dir().map(|path| {
|
||||
let path = path.join(file);
|
||||
if path.exists() {
|
||||
let _ = fs::remove_file(path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// delete the original uid
|
||||
if current == uid {
|
||||
self.current = match items.len() > 0 {
|
||||
self.current = match !items.is_empty() {
|
||||
true => items[0].uid.clone(),
|
||||
false => None,
|
||||
};
|
||||
@@ -299,7 +301,7 @@ impl IProfiles {
|
||||
Some(file) => dirs::app_profiles_dir()?.join(file),
|
||||
None => bail!("failed to get the file field"),
|
||||
};
|
||||
return Ok(help::read_merge_mapping(&file_path)?);
|
||||
return help::read_merge_mapping(&file_path);
|
||||
}
|
||||
bail!("failed to find the current profile \"uid:{current}\"");
|
||||
}
|
||||
|
||||
@@ -83,12 +83,12 @@ fn clash_client_info() -> Result<(String, HeaderMap)> {
|
||||
/// 缩短clash的日志
|
||||
pub fn parse_log(log: String) -> String {
|
||||
if log.starts_with("time=") && log.len() > 33 {
|
||||
return (&log[33..]).to_owned();
|
||||
return (log[33..]).to_owned();
|
||||
}
|
||||
if log.len() > 9 {
|
||||
return (&log[9..]).to_owned();
|
||||
return (log[9..]).to_owned();
|
||||
}
|
||||
return log;
|
||||
log
|
||||
}
|
||||
|
||||
/// 缩短clash -t的错误输出
|
||||
@@ -105,7 +105,7 @@ pub fn parse_check_output(log: String) -> String {
|
||||
};
|
||||
|
||||
if mr > m {
|
||||
return (&log[e..mr]).to_owned();
|
||||
return (log[e..mr]).to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ pub fn parse_check_output(log: String) -> String {
|
||||
let r = log.find("path=").or(Some(log.len()));
|
||||
|
||||
if let (Some(l), Some(r)) = (l, r) {
|
||||
return (&log[(l + 6)..(r - 1)]).to_owned();
|
||||
return (log[(l + 6)..(r - 1)]).to_owned();
|
||||
}
|
||||
|
||||
log
|
||||
|
||||
@@ -35,12 +35,12 @@ impl CoreManager {
|
||||
.map(|pid| {
|
||||
let mut system = System::new();
|
||||
system.refresh_all();
|
||||
system.process(Pid::from_u32(pid)).map(|proc| {
|
||||
if let Some(proc) = system.process(Pid::from_u32(pid)) {
|
||||
if proc.name().contains("clash") {
|
||||
log::debug!(target: "app", "kill old clash process");
|
||||
proc.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
tauri::async_runtime::spawn(async {
|
||||
@@ -68,7 +68,7 @@ impl CoreManager {
|
||||
|
||||
if !output.status.success() {
|
||||
let error = clash_api::parse_check_output(output.stdout.clone());
|
||||
let error = match error.len() > 0 {
|
||||
let error = match !error.is_empty() {
|
||||
true => error,
|
||||
false => output.stdout.clone(),
|
||||
};
|
||||
@@ -110,7 +110,7 @@ impl CoreManager {
|
||||
use super::win_service;
|
||||
|
||||
// 服务模式
|
||||
let enable = { Config::verge().latest().enable_service_mode.clone() };
|
||||
let enable = { Config::verge().latest().enable_service_mode };
|
||||
let enable = enable.unwrap_or(false);
|
||||
|
||||
*self.use_service_mode.lock() = enable;
|
||||
|
||||
@@ -28,7 +28,7 @@ impl Handle {
|
||||
self.app_handle
|
||||
.lock()
|
||||
.as_ref()
|
||||
.map_or(None, |a| a.get_window("main"))
|
||||
.and_then(|a| a.get_window("main"))
|
||||
}
|
||||
|
||||
pub fn refresh_clash() {
|
||||
|
||||
@@ -65,17 +65,17 @@ impl Hotkey {
|
||||
}
|
||||
|
||||
let f = match func.trim() {
|
||||
"open_dashboard" => || feat::open_dashboard(),
|
||||
"open_dashboard" => feat::open_dashboard,
|
||||
"clash_mode_rule" => || feat::change_clash_mode("rule".into()),
|
||||
"clash_mode_global" => || feat::change_clash_mode("global".into()),
|
||||
"clash_mode_direct" => || feat::change_clash_mode("direct".into()),
|
||||
"clash_mode_script" => || feat::change_clash_mode("script".into()),
|
||||
"toggle_system_proxy" => || feat::toggle_system_proxy(),
|
||||
"enable_system_proxy" => || feat::enable_system_proxy(),
|
||||
"disable_system_proxy" => || feat::disable_system_proxy(),
|
||||
"toggle_tun_mode" => || feat::toggle_tun_mode(),
|
||||
"enable_tun_mode" => || feat::enable_tun_mode(),
|
||||
"disable_tun_mode" => || feat::disable_tun_mode(),
|
||||
"toggle_system_proxy" => feat::toggle_system_proxy,
|
||||
"enable_system_proxy" => feat::enable_system_proxy,
|
||||
"disable_system_proxy" => feat::disable_system_proxy,
|
||||
"toggle_tun_mode" => feat::toggle_tun_mode,
|
||||
"enable_tun_mode" => feat::enable_tun_mode,
|
||||
"disable_tun_mode" => feat::disable_tun_mode,
|
||||
|
||||
_ => bail!("invalid function \"{func}\""),
|
||||
};
|
||||
@@ -86,7 +86,7 @@ impl Hotkey {
|
||||
}
|
||||
|
||||
fn unregister(&self, hotkey: &str) -> Result<()> {
|
||||
self.get_manager()?.unregister(&hotkey)?;
|
||||
self.get_manager()?.unregister(hotkey)?;
|
||||
log::info!(target: "app", "unregister hotkey {hotkey}");
|
||||
Ok(())
|
||||
}
|
||||
@@ -110,7 +110,7 @@ impl Hotkey {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_map_from_vec<'a>(hotkeys: &'a Vec<String>) -> HashMap<&'a str, &'a str> {
|
||||
fn get_map_from_vec(hotkeys: &Vec<String>) -> HashMap<&str, &str> {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
hotkeys.iter().for_each(|hotkey| {
|
||||
|
||||
@@ -53,7 +53,7 @@ impl Sysopt {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.clone().unwrap_or(false),
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
)
|
||||
};
|
||||
@@ -66,7 +66,7 @@ impl Sysopt {
|
||||
};
|
||||
|
||||
if enable {
|
||||
let old = Sysproxy::get_system_proxy().map_or(None, |p| Some(p));
|
||||
let old = Sysproxy::get_system_proxy().ok();
|
||||
current.set_system_proxy()?;
|
||||
|
||||
*self.old_sysproxy.lock() = old;
|
||||
@@ -93,7 +93,7 @@ impl Sysopt {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.clone().unwrap_or(false),
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
)
|
||||
};
|
||||
@@ -142,7 +142,7 @@ impl Sysopt {
|
||||
|
||||
/// init the auto launch
|
||||
pub fn init_launch(&self) -> Result<()> {
|
||||
let enable = { Config::verge().latest().enable_auto_launch.clone() };
|
||||
let enable = { Config::verge().latest().enable_auto_launch };
|
||||
let enable = enable.unwrap_or(false);
|
||||
|
||||
let app_exe = current_exe()?;
|
||||
@@ -233,7 +233,7 @@ impl Sysopt {
|
||||
drop(auto_launch);
|
||||
return self.init_launch();
|
||||
}
|
||||
let enable = { Config::verge().latest().enable_auto_launch.clone() };
|
||||
let enable = { Config::verge().latest().enable_auto_launch };
|
||||
let enable = enable.unwrap_or(false);
|
||||
let auto_launch = auto_launch.as_ref().unwrap();
|
||||
|
||||
@@ -271,9 +271,9 @@ impl Sysopt {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.clone().unwrap_or(false),
|
||||
verge.enable_proxy_guard.clone().unwrap_or(false),
|
||||
verge.proxy_guard_duration.clone().unwrap_or(10),
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.enable_proxy_guard.unwrap_or(false),
|
||||
verge.proxy_guard_duration.unwrap_or(10),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ impl Timer {
|
||||
let timer_map = self.timer_map.lock();
|
||||
let delay_timer = self.delay_timer.lock();
|
||||
|
||||
Config::profiles().latest().get_items().map(|items| {
|
||||
if let Some(items) = Config::profiles().latest().get_items() {
|
||||
items
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
@@ -61,7 +61,7 @@ impl Timer {
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ pub fn use_sort(config: Mapping, enable_filter: bool) -> Mapping {
|
||||
.chain(DEFAULT_FIELDS)
|
||||
.for_each(|key| {
|
||||
let key = Value::from(key);
|
||||
config.get(&key).map(|value| {
|
||||
if let Some(value) = config.get(&key) {
|
||||
ret.insert(key, value.clone());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if !enable_filter {
|
||||
@@ -134,9 +134,9 @@ pub fn use_sort(config: Mapping, enable_filter: bool) -> Mapping {
|
||||
|
||||
config_keys.difference(&supported_keys).for_each(|&key| {
|
||||
let key = Value::from(key);
|
||||
config.get(&key).map(|value| {
|
||||
if let Some(value) = config.get(&key) {
|
||||
ret.insert(key, value.clone());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ pub fn use_keys(config: &Mapping) -> Vec<String> {
|
||||
.map(|s| {
|
||||
let mut s = s.to_string();
|
||||
s.make_ascii_lowercase();
|
||||
return s;
|
||||
s
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.clash_core.clone(),
|
||||
verge.enable_tun_mode.clone().unwrap_or(false),
|
||||
verge.enable_builtin_enhanced.clone().unwrap_or(true),
|
||||
verge.enable_clash_fields.clone().unwrap_or(true),
|
||||
verge.enable_tun_mode.unwrap_or(false),
|
||||
verge.enable_builtin_enhanced.unwrap_or(true),
|
||||
verge.enable_clash_fields.unwrap_or(true),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -38,18 +38,18 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
let profiles = Config::profiles();
|
||||
let profiles = profiles.latest();
|
||||
|
||||
let current = profiles.current_mapping().unwrap_or(Mapping::new());
|
||||
let current = profiles.current_mapping().unwrap_or_default();
|
||||
|
||||
let chain = match profiles.chain.as_ref() {
|
||||
Some(chain) => chain
|
||||
.iter()
|
||||
.filter_map(|uid| profiles.get_item(uid).ok())
|
||||
.filter_map(|item| <Option<ChainItem>>::from(item))
|
||||
.filter_map(<Option<ChainItem>>::from)
|
||||
.collect::<Vec<ChainItem>>(),
|
||||
None => vec![],
|
||||
};
|
||||
|
||||
let valid = profiles.valid.clone().unwrap_or(vec![]);
|
||||
let valid = profiles.valid.clone().unwrap_or_default();
|
||||
|
||||
(current, chain, valid)
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ pub fn use_script(script: String, config: Mapping) -> Result<(Mapping, Vec<(Stri
|
||||
if result == "\"\"" {
|
||||
anyhow::bail!("main function should return object");
|
||||
}
|
||||
return Ok(serde_json::from_str::<Mapping>(result.as_str())?);
|
||||
Ok(serde_json::from_str::<Mapping>(result.as_str())?)
|
||||
});
|
||||
|
||||
let mut out = outputs.lock().unwrap();
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn change_clash_mode(mode: String) {
|
||||
|
||||
// 切换系统代理
|
||||
pub fn toggle_system_proxy() {
|
||||
let enable = Config::verge().draft().enable_system_proxy.clone();
|
||||
let enable = Config::verge().draft().enable_system_proxy;
|
||||
let enable = enable.unwrap_or(false);
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
@@ -110,7 +110,7 @@ pub fn disable_system_proxy() {
|
||||
|
||||
// 切换tun模式
|
||||
pub fn toggle_tun_mode() {
|
||||
let enable = Config::verge().data().enable_tun_mode.clone();
|
||||
let enable = Config::verge().data().enable_tun_mode;
|
||||
let enable = enable.unwrap_or(false);
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
@@ -164,14 +164,14 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
|
||||
let mixed_port = patch.get("mixed-port");
|
||||
let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
|
||||
if mixed_port.is_some() && !enable_random_port {
|
||||
let changed = mixed_port.clone().unwrap()
|
||||
let changed = mixed_port.unwrap()
|
||||
!= Config::verge()
|
||||
.latest()
|
||||
.verge_mixed_port
|
||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||
// 检查端口占用
|
||||
if changed {
|
||||
if let Some(port) = mixed_port.clone().unwrap().as_u64() {
|
||||
if let Some(port) = mixed_port.unwrap().as_u64() {
|
||||
if !port_scanner::local_port_available(port as u16) {
|
||||
Config::clash().discard();
|
||||
bail!("port already in use");
|
||||
|
||||
@@ -25,7 +25,10 @@ fn main() -> std::io::Result<()> {
|
||||
#[allow(unused_mut)]
|
||||
let mut builder = tauri::Builder::default()
|
||||
.system_tray(SystemTray::new())
|
||||
.setup(|app| Ok(resolve::resolve_setup(app)))
|
||||
.setup(|app| {
|
||||
resolve::resolve_setup(app);
|
||||
Ok(())
|
||||
})
|
||||
.on_system_tray_event(core::tray::Tray::on_system_tray_event)
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
// common
|
||||
@@ -133,13 +136,13 @@ fn main() -> std::io::Result<()> {
|
||||
if label == "main" {
|
||||
match event {
|
||||
tauri::WindowEvent::Destroyed => {
|
||||
let _ = resolve::save_window_size_position(&app_handle, true);
|
||||
let _ = resolve::save_window_size_position(app_handle, true);
|
||||
}
|
||||
tauri::WindowEvent::CloseRequested { .. } => {
|
||||
let _ = resolve::save_window_size_position(&app_handle, true);
|
||||
let _ = resolve::save_window_size_position(app_handle, true);
|
||||
}
|
||||
tauri::WindowEvent::Moved(_) | tauri::WindowEvent::Resized(_) => {
|
||||
let _ = resolve::save_window_size_position(&app_handle, false);
|
||||
let _ = resolve::save_window_size_position(app_handle, false);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn read_yaml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
|
||||
bail!("file not found \"{}\"", path.display());
|
||||
}
|
||||
|
||||
let yaml_str = fs::read_to_string(&path)
|
||||
let yaml_str = fs::read_to_string(path)
|
||||
.with_context(|| format!("failed to read the file \"{}\"", path.display()))?;
|
||||
|
||||
serde_yaml::from_str::<T>(&yaml_str).with_context(|| {
|
||||
@@ -89,11 +89,11 @@ pub fn open_file(app: tauri::AppHandle, path: PathBuf) -> Result<()> {
|
||||
let code = "code";
|
||||
|
||||
let _ = match Program::from_str(code) {
|
||||
Ok(code) => open(&app.shell_scope(), &path.to_string_lossy(), Some(code)),
|
||||
Ok(code) => open(&app.shell_scope(), path.to_string_lossy(), Some(code)),
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "Can't find VScode `{err}`");
|
||||
// default open
|
||||
open(&app.shell_scope(), &path.to_string_lossy(), None)
|
||||
open(&app.shell_scope(), path.to_string_lossy(), None)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ pub fn delete_log() -> Result<()> {
|
||||
let auto_log_clean = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.data();
|
||||
verge.auto_log_clean.clone().unwrap_or(0)
|
||||
verge.auto_log_clean.unwrap_or(0)
|
||||
};
|
||||
|
||||
let day = match auto_log_clean {
|
||||
@@ -130,10 +130,8 @@ pub fn delete_log() -> Result<()> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
for file in fs::read_dir(&log_dir)? {
|
||||
if let Ok(file) = file {
|
||||
let _ = process_file(file);
|
||||
}
|
||||
for file in fs::read_dir(&log_dir)?.flatten() {
|
||||
let _ = process_file(file);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -310,14 +308,14 @@ pub fn init_scheme() -> Result<()> {
|
||||
|
||||
let app_exe = current_exe()?;
|
||||
let app_exe = dunce::canonicalize(app_exe)?;
|
||||
let app_exe = app_exe.to_string_lossy().to_owned();
|
||||
let app_exe = app_exe.to_string_lossy().into_owned();
|
||||
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let (clash, _) = hkcu.create_subkey("Software\\Classes\\Clash")?;
|
||||
clash.set_value("", &"Clash Verge")?;
|
||||
clash.set_value("URL Protocol", &"Clash Verge URL Scheme Protocol")?;
|
||||
let (default_icon, _) = hkcu.create_subkey("Software\\Classes\\Clash\\DefaultIcon")?;
|
||||
default_icon.set_value("", &format!("{app_exe}"))?;
|
||||
default_icon.set_value("", &app_exe)?;
|
||||
let (command, _) = hkcu.create_subkey("Software\\Classes\\Clash\\Shell\\Open\\Command")?;
|
||||
command.set_value("", &format!("{app_exe} \"%1\""))?;
|
||||
|
||||
@@ -325,6 +323,17 @@ pub fn init_scheme() -> Result<()> {
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn init_scheme() -> Result<()> {
|
||||
let output = std::process::Command::new("xdg-mime")
|
||||
.arg("default")
|
||||
.arg("clash-verge.desktop")
|
||||
.arg("x-scheme-handler/clash")
|
||||
.output()?;
|
||||
if !output.status.success() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"failed to set clash scheme, {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
|
||||
@@ -86,7 +86,7 @@ pub fn resolve_setup(app: &mut App) {
|
||||
log::trace!("init system tray");
|
||||
log_err!(tray::Tray::update_systray(&app.app_handle()));
|
||||
|
||||
let silent_start = { Config::verge().data().enable_silent_start.clone() };
|
||||
let silent_start = { Config::verge().data().enable_silent_start };
|
||||
if !silent_start.unwrap_or(false) {
|
||||
create_window(&app.app_handle());
|
||||
}
|
||||
@@ -240,15 +240,17 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) ->
|
||||
}
|
||||
|
||||
pub async fn resolve_scheme(param: String) {
|
||||
let url = param.trim_start_matches("clash://install-config/?url=");
|
||||
let url = param
|
||||
.trim_start_matches("clash://install-config/?url=")
|
||||
.trim_start_matches("clash://install-config?url=");
|
||||
let option = PrfOption {
|
||||
user_agent: None,
|
||||
with_proxy: Some(true),
|
||||
self_proxy: None,
|
||||
update_interval: None,
|
||||
};
|
||||
if let Ok(item) = PrfItem::from_url(&url, None, None, Some(option)).await {
|
||||
if let Ok(_) = Config::profiles().data().append_item(item) {
|
||||
if let Ok(item) = PrfItem::from_url(url, None, None, Some(option)).await {
|
||||
if Config::profiles().data().append_item(item).is_ok() {
|
||||
notification::Notification::new(crate::utils::dirs::APP_ID)
|
||||
.title("Clash Verge")
|
||||
.body("Import profile success")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.4.6"
|
||||
"version": "1.4.7"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"bundle": {
|
||||
"targets": ["deb", "appimage", "updater"],
|
||||
"deb": {
|
||||
"depends": ["openssl"]
|
||||
"depends": ["openssl"],
|
||||
"desktopTemplate": "./clash-verge.desktop"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,8 @@ export const ProxyItemMini = (props: Props) => {
|
||||
)}
|
||||
<TypeBox component="span">{proxy.type}</TypeBox>
|
||||
{proxy.udp && <TypeBox component="span">UDP</TypeBox>}
|
||||
{proxy.xudp && <TypeBox component="span">XUDP</TypeBox>}
|
||||
{proxy.tfo && <TypeBox component="span">TFO</TypeBox>}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -104,6 +104,10 @@ export const ProxyItem = (props: Props) => {
|
||||
)}
|
||||
{showType && <TypeBox component="span">{proxy.type}</TypeBox>}
|
||||
{showType && proxy.udp && <TypeBox component="span">UDP</TypeBox>}
|
||||
{showType && proxy.xudp && (
|
||||
<TypeBox component="span">XUDP</TypeBox>
|
||||
)}
|
||||
{showType && proxy.tfo && <TypeBox component="span">TFO</TypeBox>}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -31,7 +31,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
props;
|
||||
const { type, group, headState, proxy, proxyCol } = item;
|
||||
|
||||
if (type === 0) {
|
||||
if (type === 0 && !group.hidden) {
|
||||
return (
|
||||
<ListItemButton
|
||||
dense
|
||||
@@ -61,7 +61,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 1) {
|
||||
if (type === 1 && !group.hidden) {
|
||||
return (
|
||||
<ProxyHead
|
||||
sx={{ pl: indent ? 4.5 : 2.5, pr: 3, mt: indent ? 1 : 0.5, mb: 1 }}
|
||||
@@ -74,7 +74,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 2) {
|
||||
if (type === 2 && !group.hidden) {
|
||||
return (
|
||||
<ProxyItem
|
||||
groupName={group.name}
|
||||
@@ -87,7 +87,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 3) {
|
||||
if (type === 3 && !group.hidden) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -105,7 +105,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 4) {
|
||||
if (type === 4 && !group.hidden) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
|
||||
@@ -10,6 +10,7 @@ import { checkUpdate, installUpdate } from "@tauri-apps/api/updater";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { atomUpdateState } from "@/services/states";
|
||||
import { listen, Event, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { portableFlag } from "@/pages/_layout";
|
||||
|
||||
const UpdateLog = styled(Box)(() => ({
|
||||
"h1,h2,h3,ul,ol,p": { margin: "0.5em 0", color: "inherit" },
|
||||
@@ -46,6 +47,10 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
}, [updateInfo]);
|
||||
|
||||
const onUpdate = useLockFn(async () => {
|
||||
if (portableFlag) {
|
||||
Notice.error(t("Portable Updater Error"));
|
||||
return;
|
||||
}
|
||||
if (updateState) return;
|
||||
setUpdateState(true);
|
||||
if (eventListener !== null) {
|
||||
|
||||
@@ -145,5 +145,7 @@
|
||||
"Never Clean": "Never Clean",
|
||||
"Retain 7 Days": "Retain 7 Days",
|
||||
"Retain 30 Days": "Retain 30 Days",
|
||||
"Retain 90 Days": "Retain 90 Days"
|
||||
"Retain 90 Days": "Retain 90 Days",
|
||||
|
||||
"Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it"
|
||||
}
|
||||
|
||||
@@ -115,5 +115,7 @@
|
||||
"disable_system_proxy": "Отключить системный прокси",
|
||||
"toggle_tun_mode": "Переключить режим туннеля",
|
||||
"enable_tun_mode": "Включить режим туннеля",
|
||||
"disable_tun_mode": "Отключить режим туннеля"
|
||||
"disable_tun_mode": "Отключить режим туннеля",
|
||||
|
||||
"Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените вручную"
|
||||
}
|
||||
|
||||
@@ -145,5 +145,7 @@
|
||||
"Never Clean": "不清理",
|
||||
"Retain 7 Days": "保留7天",
|
||||
"Retain 30 Days": "保留30天",
|
||||
"Retain 90 Days": "保留90天"
|
||||
"Retain 90 Days": "保留90天",
|
||||
|
||||
"Portable Updater Error": "便携版不支持应用内更新,请手动下载替换"
|
||||
}
|
||||
|
||||
@@ -119,7 +119,14 @@ export const getProxies = async () => {
|
||||
const generateItem = (name: string) => {
|
||||
if (proxyRecord[name]) return proxyRecord[name];
|
||||
if (providerMap[name]) return providerMap[name];
|
||||
return { name, type: "unknown", udp: false, history: [] };
|
||||
return {
|
||||
name,
|
||||
type: "unknown",
|
||||
udp: false,
|
||||
xudp: false,
|
||||
tfo: false,
|
||||
history: [],
|
||||
};
|
||||
};
|
||||
|
||||
const { GLOBAL: global, DIRECT: direct, REJECT: reject } = proxyRecord;
|
||||
|
||||
3
src/services/types.d.ts
vendored
3
src/services/types.d.ts
vendored
@@ -44,12 +44,15 @@ interface IProxyItem {
|
||||
name: string;
|
||||
type: string;
|
||||
udp: boolean;
|
||||
xudp: boolean;
|
||||
tfo: boolean;
|
||||
history: {
|
||||
time: string;
|
||||
delay: number;
|
||||
}[];
|
||||
all?: string[];
|
||||
now?: string;
|
||||
hidden?: boolean;
|
||||
provider?: string; // 记录是否来自provider
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user