mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-13 22:32:15 +08:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22b51555ee | ||
|
|
5b10331022 | ||
|
|
3ec858eb9f |
Generated
+98
-174
@@ -1119,7 +1119,7 @@ dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"libc",
|
||||
"log",
|
||||
"minisign-verify 0.3.0",
|
||||
"minisign-verify",
|
||||
"nanoid",
|
||||
"network-interface",
|
||||
"objc2",
|
||||
@@ -1131,14 +1131,14 @@ dependencies = [
|
||||
"regex",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest_dav",
|
||||
"rfd",
|
||||
"rfd 0.17.2",
|
||||
"runas",
|
||||
"rustls",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml_ng",
|
||||
"sha2 0.11.0",
|
||||
"sha2 0.11.1",
|
||||
"smartstring",
|
||||
"socket2",
|
||||
"specta",
|
||||
@@ -1175,7 +1175,7 @@ dependencies = [
|
||||
"windows-service",
|
||||
"windows-sys 0.61.2",
|
||||
"winreg 0.56.0",
|
||||
"zip 9.0.1",
|
||||
"zip 9.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1247,7 +1247,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.11.0",
|
||||
"sha2 0.11.1",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"sysproxy",
|
||||
@@ -1462,9 +1462,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.4.2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
|
||||
checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
@@ -4052,7 +4055,7 @@ version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fde178a3caf126c440fa15628147772d8ee590a39477d711353fbe2e58a73a5b"
|
||||
dependencies = [
|
||||
"sha2 0.11.0",
|
||||
"sha2 0.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4167,12 +4170,6 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minisign-verify"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e"
|
||||
|
||||
[[package]]
|
||||
name = "minisign-verify"
|
||||
version = "0.3.0"
|
||||
@@ -5909,6 +5906,29 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfd"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"dispatch2",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
"percent-encoding",
|
||||
"raw-window-handle",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
@@ -6410,9 +6430,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.151"
|
||||
version = "1.0.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||
checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -6597,9 +6617,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
@@ -6622,7 +6642,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"sigchld",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
@@ -6642,17 +6661,6 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "sigchld"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"os_pipe",
|
||||
"signal-hook 0.3.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.1.17"
|
||||
@@ -6663,16 +6671,6 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.8"
|
||||
@@ -6937,9 +6935,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "swift-rs"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e"
|
||||
checksum = "cefd87076fd385308ee4aff597256c902f1fbb4d031de1558efc12f8ffefadd9"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"serde",
|
||||
@@ -7186,9 +7184,9 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
||||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.12.1"
|
||||
version = "2.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed99ee9694a2deb776d91cae48ac7411ddfc89ecae2f9b5041111d8c88f2ace9"
|
||||
checksum = "c404ecf956ff241bf6b39dd688614724e1bf1f63255abb4fc46d1c40371672ea"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -7234,16 +7232,16 @@ dependencies = [
|
||||
"tray-icon",
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com 0.39.1",
|
||||
"webview2-com",
|
||||
"window-vibrancy",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59563ca5b331fd97f27ee9672ec8d36d33bb3c9e2c9f6710a1a5687256052e45"
|
||||
checksum = "2eea0b6302f82c574b21af6fc6ae6e86183b9280853c22621d0abf0936911ffc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
@@ -7262,11 +7260,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e50213e463086ecc283d7e9f51c30cc0fd304ad457425158018be26dbf0d0a80"
|
||||
checksum = "02f468f9a9bcd404f57e5c191d91024e3de953d4b610f78c2907e7110615cb1c"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"base64 0.23.1",
|
||||
"brotli",
|
||||
"ico",
|
||||
"json-patch",
|
||||
@@ -7289,9 +7287,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-macros"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8129fb43bb6e0d6b73ad3315cd172beaab17cd28899c594b1b32c80edbbfd99c"
|
||||
checksum = "131bffec939b20642380317f8403a33c8888489925e14bb965ceaff0d949b1cb"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -7347,9 +7345,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-clipboard-manager"
|
||||
version = "2.4.1"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "333d3b6beeb1c2c7fc040233d4ea7b6c03a9f8f039592b7400833c43fb5b568a"
|
||||
checksum = "640d0789c9db02265a800fded60520df5a3baa4a1b5f40715b83d58842c24fcb"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"log",
|
||||
@@ -7410,13 +7408,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.8.1"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daf9a5c92e39bdd84f22f6be9230e39d0c4e140345f71ffe6058dca4f71127cf"
|
||||
checksum = "3dca325d6e66e9170f2e1b9631722e4e544bcbc51781575d266abdaba697bd51"
|
||||
dependencies = [
|
||||
"log",
|
||||
"raw-window-handle",
|
||||
"rfd",
|
||||
"rfd 0.16.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
@@ -7428,9 +7426,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "466eb32466fe5021b6728b06862f9ff14a9f7e1af890047654e03a96d7c0e1bb"
|
||||
checksum = "213fae2d85d4b76b06de5915d1862db9fa74541171f9d2c15da6ac9bd6e788c6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"dunce",
|
||||
@@ -7452,9 +7450,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-global-shortcut"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bd2e1f725891a1613af8f25bf918ba3357654b0fd3f2d794c0ce76cbdd92ed2"
|
||||
checksum = "93ff17919fe09852d269bd37b1d3d2e993b9dbb514afe7acbf3346c1d3627e2d"
|
||||
dependencies = [
|
||||
"global-hotkey",
|
||||
"log",
|
||||
@@ -7467,9 +7465,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.8.0"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93e9d6b3319e101bc1be27cfa0fb4054d7784a12509c67ead0033b82180e5ed1"
|
||||
checksum = "46f1afc4200ba2e8b596c378d5756d0056febf8755f1563633d98f6bd7fffb2f"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cookie_store",
|
||||
@@ -7486,7 +7484,7 @@ dependencies = [
|
||||
"thiserror 2.0.20",
|
||||
"tokio",
|
||||
"url",
|
||||
"urlpattern 0.3.0",
|
||||
"urlpattern",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7516,9 +7514,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-notification"
|
||||
version = "2.5.1"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533770889abb60a0407d5a32096182f0e6463f5a3dfaa675be94580aa14070e1"
|
||||
checksum = "8cf3cce3ea492b3a8a7f431a4e5dd5d31dc41b2a4a243faa660cbe8095a577bd"
|
||||
dependencies = [
|
||||
"log",
|
||||
"notify-rust",
|
||||
@@ -7531,13 +7529,14 @@ dependencies = [
|
||||
"thiserror 2.0.20",
|
||||
"time",
|
||||
"url",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-opener"
|
||||
version = "2.7.0"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d39404b2572927e0d3ed30a7ca226037f7508d22e79c96ee6ef0d42b6a4b3345"
|
||||
checksum = "85dead674ee41937d042ee855d785f07ee67206f19402200c12b9255964d5ac8"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"glob",
|
||||
@@ -7567,11 +7566,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-shell"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "094bdbc47e5efe36544ba21b3a53ab5c724150236cf55e6c9be46191deb6eab6"
|
||||
checksum = "8567d42b2c7264355daa1df415ec77f52aa42e885924c86a969be2e920e05521"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"libc",
|
||||
"log",
|
||||
"open",
|
||||
"os_pipe",
|
||||
@@ -7584,13 +7584,14 @@ dependencies = [
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.20",
|
||||
"tokio",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.13.1"
|
||||
version = "2.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cb0b2ea3e85ca287990d3859a29cc5cb18024240fd78f62e027fb7963670f18"
|
||||
checksum = "855a336eb389d2c1502244fd48fa2d8cb487a430f691bbaed025195f99a04489"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"dirs 7.0.0",
|
||||
@@ -7598,8 +7599,9 @@ dependencies = [
|
||||
"futures-util",
|
||||
"http",
|
||||
"infer",
|
||||
"libc",
|
||||
"log",
|
||||
"minisign-verify 0.2.5",
|
||||
"minisign-verify",
|
||||
"osakit",
|
||||
"percent-encoding",
|
||||
"reqwest 0.13.5",
|
||||
@@ -7621,9 +7623,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-wdio-webdriver"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52c5e97428174a52b7f4357bbc4535fcce52c6a06c8ee7a379502f7cda1b6045"
|
||||
checksum = "4f76676d510d271d80abcf8b0552987b5b4f0eae5e3f906e9b5660d43c97c62e"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -7647,9 +7649,9 @@ dependencies = [
|
||||
"tracing",
|
||||
"uuid",
|
||||
"webkit2gtk",
|
||||
"webview2-com 0.38.2",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"webview2-com",
|
||||
"windows 0.62.2",
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7688,7 +7690,7 @@ dependencies = [
|
||||
"thiserror 2.0.20",
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com 0.39.1",
|
||||
"webview2-com",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
|
||||
@@ -7714,7 +7716,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com 0.39.1",
|
||||
"webview2-com",
|
||||
"windows 0.62.2",
|
||||
"wry",
|
||||
]
|
||||
@@ -7783,7 +7785,7 @@ dependencies = [
|
||||
"thiserror 2.0.20",
|
||||
"toml 1.1.6+spec-1.1.0",
|
||||
"url",
|
||||
"urlpattern 0.6.0",
|
||||
"urlpattern",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
]
|
||||
@@ -7902,7 +7904,7 @@ dependencies = [
|
||||
"regex",
|
||||
"semver 0.11.0",
|
||||
"sha2 0.9.9",
|
||||
"signal-hook 0.1.17",
|
||||
"signal-hook",
|
||||
"terminfo",
|
||||
"termios",
|
||||
"thiserror 1.0.69",
|
||||
@@ -8073,9 +8075,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.53.2"
|
||||
version = "1.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044"
|
||||
checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -8135,9 +8137,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.19"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
|
||||
checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -8592,47 +8594,6 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-char-property"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
|
||||
dependencies = [
|
||||
"unic-char-range",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-char-range"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
|
||||
|
||||
[[package]]
|
||||
name = "unic-common"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
|
||||
|
||||
[[package]]
|
||||
name = "unic-ucd-ident"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987"
|
||||
dependencies = [
|
||||
"unic-char-property",
|
||||
"unic-char-range",
|
||||
"unic-ucd-version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-ucd-version"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
|
||||
dependencies = [
|
||||
"unic-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
@@ -8692,18 +8653,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlpattern"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"unic-ucd-ident",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlpattern"
|
||||
version = "0.6.0"
|
||||
@@ -9095,20 +9044,6 @@ dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com"
|
||||
version = "0.38.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a"
|
||||
dependencies = [
|
||||
"webview2-com-macros",
|
||||
"webview2-com-sys 0.38.2",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com"
|
||||
version = "0.39.1"
|
||||
@@ -9116,7 +9051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f89fca7a704cee10dcb3654c1dbb8941d1783132f1917358af75bec37a7d7e6"
|
||||
dependencies = [
|
||||
"webview2-com-macros",
|
||||
"webview2-com-sys 0.39.1",
|
||||
"webview2-com-sys",
|
||||
"windows 0.62.2",
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
@@ -9132,17 +9067,6 @@ dependencies = [
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com-sys"
|
||||
version = "0.38.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
|
||||
dependencies = [
|
||||
"thiserror 2.0.20",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webview2-com-sys"
|
||||
version = "0.39.1"
|
||||
@@ -9882,7 +9806,7 @@ dependencies = [
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webkit2gtk-sys",
|
||||
"webview2-com 0.39.1",
|
||||
"webview2-com",
|
||||
"windows 0.62.2",
|
||||
"windows-core 0.62.2",
|
||||
"windows-version",
|
||||
@@ -10150,9 +10074,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "9.0.1"
|
||||
version = "9.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e49ade69c4434c55dd651d36fe05f38e0578db948b773cbc01c48c4b5e560692"
|
||||
checksum = "c2d98561b612a84ae525331a7a094429ef8a5772514ed507ff6db5f54badc971"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bzip2",
|
||||
@@ -10202,27 +10126,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.3"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||
checksum = "057cfd910cfac363a0ada849592624b4c9ff2e10bef504c3433810d78ed96f93"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.2.4"
|
||||
version = "8.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||
checksum = "bdd44c6a7284e91f3717755b24315a302edd9153a01f753c3cba3d765e8eafac"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.16+zstd.1.5.7"
|
||||
version = "2.1.1+zstd.1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||
checksum = "aeec9eaf2dffbbd09201e23bd0ffcbaa33bb8e9266a10734fd7ed90a85eca078"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
|
||||
+4
-4
@@ -61,13 +61,13 @@ tracing-estuary = { git = "https://github.com/Tunglies/tracing-estuary.git", bra
|
||||
tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" }
|
||||
tracing = "0.1.44"
|
||||
|
||||
tauri = { version = "2.12.1" }
|
||||
tauri-plugin-clipboard-manager = "2.4.1"
|
||||
tauri = { version = "2.12.3" }
|
||||
tauri-plugin-clipboard-manager = "2.4.2"
|
||||
parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] }
|
||||
anyhow = "1.0.104"
|
||||
chrono = "0.4.45"
|
||||
criterion = { version = "0.8.2", features = ["async_tokio"] }
|
||||
tokio = { version = "1.53.2", features = [
|
||||
tokio = { version = "1.53.3", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"time",
|
||||
@@ -88,7 +88,7 @@ rust_iso3166 = "0.2.0"
|
||||
smartstring = { version = "1.0.1" }
|
||||
|
||||
serde = { version = "1.0.229" }
|
||||
serde_json = { version = "1.0.151" }
|
||||
serde_json = { version = "1.0.154" }
|
||||
serde_yaml_ng = { version = "0.10.0" }
|
||||
bitflags = { version = "2.13.2" }
|
||||
socket2 = "0.6.5"
|
||||
|
||||
+4
-1
@@ -6,6 +6,10 @@
|
||||
- 修复通过 URL 导入订阅时,即使导入的订阅并非当前使用的订阅,也会重新加载当前配置的问题
|
||||
- 修复「首页」网站测速失败后卡片一直显示测试中的问题
|
||||
|
||||
**🐧 Linux**
|
||||
|
||||
- Linux:修复 deb/rpm 安装包错误包含多余的 `frontend-contract` 可执行文件,导致下游重新打包失败的问题
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -17,7 +21,6 @@
|
||||
<details>
|
||||
<summary><strong> 🚀 优化改进 </strong></summary>
|
||||
|
||||
- 记住「启用系统标题栏」设置,Windows/macOS 即时生效,Linux 重启后生效
|
||||
|
||||
**🖥️ Windows**
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
//! Linux-only termination signal bridge.
|
||||
//!
|
||||
//! Upstream Tauri delivers session-end and termination events to the app on
|
||||
//! Windows and macOS, but has no equivalent on Linux: a desktop session may
|
||||
//! end without any window or run event reaching the process. Linux builds
|
||||
//! keep this crate to listen for SIGTERM, SIGINT and SIGHUP and forward them
|
||||
//! to the app quit flow, so system proxy and TUN cleanup still runs before
|
||||
//! the process dies. Non-Linux builds compile this crate to nothing and must
|
||||
//! not depend on it.
|
||||
|
||||
#![cfg(target_os = "linux")]
|
||||
|
||||
use std::sync::{
|
||||
OnceLock,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
@@ -5,20 +17,13 @@ use std::sync::{
|
||||
|
||||
use clash_verge_logging::{Type, logging};
|
||||
|
||||
#[cfg(unix)]
|
||||
mod unix;
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
|
||||
pub(crate) static RUNTIME: OnceLock<Option<tokio::runtime::Runtime>> = OnceLock::new();
|
||||
pub(crate) static SHUTDOWN_LATCH: ShutdownLatch = ShutdownLatch::new();
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum ShutdownOutcome {
|
||||
Committed,
|
||||
Canceled,
|
||||
}
|
||||
|
||||
/// Serializes signal-triggered cleanups: a signal arriving while a quit
|
||||
/// attempt is still in flight is dropped instead of overlapping it.
|
||||
pub(crate) struct ShutdownLatch {
|
||||
is_cleaning_up: AtomicBool,
|
||||
}
|
||||
@@ -36,17 +41,18 @@ impl ShutdownLatch {
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
fn finish(&self, outcome: ShutdownOutcome) {
|
||||
if matches!(outcome, ShutdownOutcome::Canceled) {
|
||||
self.is_cleaning_up.store(false, Ordering::Release);
|
||||
}
|
||||
fn finish(&self) {
|
||||
self.is_cleaning_up.store(false, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns the Linux signal loop on a dedicated runtime so it survives the
|
||||
/// teardown of any app-owned runtime. The handler runs once per accepted
|
||||
/// signal; the quit flow it invokes owns the exit-or-cancel decision.
|
||||
pub fn register<F, Fut>(f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future<Output = ShutdownOutcome> + Send + 'static,
|
||||
Fut: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
RUNTIME.get_or_init(|| match tokio::runtime::Runtime::new() {
|
||||
Ok(rt) => Some(rt),
|
||||
@@ -61,36 +67,22 @@ where
|
||||
}
|
||||
});
|
||||
|
||||
#[cfg(unix)]
|
||||
unix::register(f);
|
||||
|
||||
#[cfg(windows)]
|
||||
windows::register(f);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{ShutdownLatch, ShutdownOutcome};
|
||||
use super::ShutdownLatch;
|
||||
|
||||
#[test]
|
||||
fn canceled_shutdown_releases_latch_and_permits_next_attempt() {
|
||||
fn finished_attempt_releases_latch_for_the_next_signal() {
|
||||
let latch = ShutdownLatch::new();
|
||||
|
||||
assert!(latch.try_begin());
|
||||
assert!(!latch.try_begin());
|
||||
|
||||
latch.finish(ShutdownOutcome::Canceled);
|
||||
latch.finish();
|
||||
|
||||
assert!(latch.try_begin());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn committed_shutdown_retains_latch_and_suppresses_repeats() {
|
||||
let latch = ShutdownLatch::new();
|
||||
|
||||
assert!(latch.try_begin());
|
||||
latch.finish(ShutdownOutcome::Committed);
|
||||
|
||||
assert!(!latch.try_begin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
|
||||
use crate::{RUNTIME, SHUTDOWN_LATCH, ShutdownOutcome};
|
||||
use crate::{RUNTIME, SHUTDOWN_LATCH};
|
||||
|
||||
pub fn register<F, Fut>(f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future<Output = ShutdownOutcome> + Send + 'static,
|
||||
Fut: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
if let Some(Some(rt)) = RUNTIME.get() {
|
||||
rt.spawn(async move {
|
||||
@@ -60,7 +60,8 @@ where
|
||||
}
|
||||
logging!(info, Type::SystemSignal, "Caught signal {}", signal_name);
|
||||
|
||||
SHUTDOWN_LATCH.finish(f().await);
|
||||
f().await;
|
||||
SHUTDOWN_LATCH.finish();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use tokio::signal::windows;
|
||||
|
||||
use crate::{RUNTIME, SHUTDOWN_LATCH, ShutdownOutcome};
|
||||
|
||||
pub fn register<F, Fut>(f: F)
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future<Output = ShutdownOutcome> + Send + 'static,
|
||||
{
|
||||
if let Some(Some(rt)) = RUNTIME.get() {
|
||||
rt.spawn(async move {
|
||||
let mut ctrl_c = match windows::ctrl_c() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
logging!(error, Type::SystemSignal, "Failed to register Ctrl+C: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut ctrl_close = match windows::ctrl_close() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
logging!(error, Type::SystemSignal, "Failed to register Ctrl+Close: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut ctrl_shutdown = match windows::ctrl_shutdown() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
logging!(error, Type::SystemSignal, "Failed to register Ctrl+Shutdown: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut ctrl_logoff = match windows::ctrl_logoff() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
logging!(error, Type::SystemSignal, "Failed to register Ctrl+Logoff: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
let signal_name;
|
||||
tokio::select! {
|
||||
_ = ctrl_c.recv() => {
|
||||
signal_name = "Ctrl+C";
|
||||
}
|
||||
_ = ctrl_close.recv() => {
|
||||
signal_name = "Ctrl+Close";
|
||||
}
|
||||
_ = ctrl_shutdown.recv() => {
|
||||
signal_name = "Ctrl+Shutdown";
|
||||
}
|
||||
_ = ctrl_logoff.recv() => {
|
||||
signal_name = "Ctrl+Logoff";
|
||||
}
|
||||
}
|
||||
|
||||
if !SHUTDOWN_LATCH.try_begin() {
|
||||
logging!(
|
||||
info,
|
||||
Type::SystemSignal,
|
||||
"Already shutting down, ignoring repeated signal: {}",
|
||||
signal_name
|
||||
);
|
||||
continue;
|
||||
}
|
||||
logging!(info, Type::SystemSignal, "Caught Windows signal: {}", signal_name);
|
||||
|
||||
SHUTDOWN_LATCH.finish(f().await);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logging!(
|
||||
error,
|
||||
Type::SystemSignal,
|
||||
"register shutdown signal failed, RUNTIME is not available"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ try {
|
||||
'run',
|
||||
'-p',
|
||||
'clash-verge',
|
||||
'--bin',
|
||||
'--example',
|
||||
'frontend-contract',
|
||||
'--locked',
|
||||
'-q',
|
||||
|
||||
+18
-15
@@ -29,13 +29,12 @@ perf-harness = ["dep:tauri-plugin-wdio-webdriver"]
|
||||
identifier = "io.github.clash-verge-rev.clash-verge-rev"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.7.1", features = [] }
|
||||
tauri-build = { version = "2.7.2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
clash-verge-draft = { workspace = true }
|
||||
clash-verge-media-unlock = { workspace = true }
|
||||
clash-verge-logging = { workspace = true }
|
||||
clash-verge-signal = { workspace = true }
|
||||
clash-verge-i18n = { workspace = true }
|
||||
clash-verge-limiter = { workspace = true }
|
||||
tauri-plugin-clash-verge-sysinfo = { workspace = true }
|
||||
@@ -60,7 +59,7 @@ bitflags = { workspace = true }
|
||||
socket2 = { workspace = true }
|
||||
warp = { version = "0.4.3", features = ["server"] }
|
||||
open = "5.4.4"
|
||||
rfd = { version = "0.16.0", default-features = false, features = ["common-controls-v6"] }
|
||||
rfd = { version = "0.17.2", default-features = false, features = ["common-controls-v6"] }
|
||||
dirs = "7.0.0"
|
||||
dunce = "1.0.5"
|
||||
nanoid = "0.5"
|
||||
@@ -73,28 +72,28 @@ sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs.git", branch
|
||||
"guard",
|
||||
] }
|
||||
network-interface = { version = "2.0.5", features = ["serde"] }
|
||||
tauri-plugin-shell = "2.4.0"
|
||||
tauri-plugin-opener = "2.7.0"
|
||||
tauri-plugin-dialog = "2.8.1"
|
||||
tauri-plugin-fs = "2.6.0"
|
||||
tauri-plugin-shell = "2.5.0"
|
||||
tauri-plugin-opener = "2.7.1"
|
||||
tauri-plugin-dialog = "2.8.2"
|
||||
tauri-plugin-fs = "2.7.0"
|
||||
tauri-plugin-process = "2.4.0"
|
||||
tauri-plugin-deep-link = "2.6.1"
|
||||
tauri-plugin-window-state = "2.5.0"
|
||||
zip = "9.0.1"
|
||||
zip = "9.0.3"
|
||||
flate2 = "1.1.10"
|
||||
reqwest_dav = "0.3.3"
|
||||
aes-gcm = { version = "0.11.1" }
|
||||
base64 = "0.23.1"
|
||||
minisign-verify = "0.3.0"
|
||||
sha2 = "0.11"
|
||||
sha2 = "0.11.1"
|
||||
getrandom = "0.4.3"
|
||||
futures = "0.3.34"
|
||||
gethostname = "1.1.0"
|
||||
scopeguard = "1.2.0"
|
||||
tauri-plugin-notification = "2.5.1"
|
||||
tauri-plugin-notification = "2.6.0"
|
||||
tokio-stream = "0.1.19"
|
||||
backon = { version = "1.6.0", features = ["tokio-sleep"] }
|
||||
tauri-plugin-http = "2.8.0"
|
||||
tauri-plugin-http = "2.8.2"
|
||||
tracing = { workspace = true }
|
||||
tauri-plugin-devtools = { version = "2.2.2", optional = true }
|
||||
tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", branch = "main" }
|
||||
@@ -108,7 +107,7 @@ rustls = { version = "0.23.45", features = ["ring"] }
|
||||
webpki-roots = "1.0.9"
|
||||
dark-light = "3.0.0"
|
||||
bytes = "1.12.1"
|
||||
tokio-util = { version = "0.7.19", features = ["time"] }
|
||||
tokio-util = { version = "0.7.20", features = ["time"] }
|
||||
specta = { version = "=2.0.0-rc.25", features = ["derive", "function", "serde_json"] }
|
||||
tauri-specta = { version = "=2.0.0-rc.25", features = ["derive", "typescript"] }
|
||||
specta-typescript = "=0.0.12"
|
||||
@@ -116,8 +115,12 @@ specta-typescript = "=0.0.12"
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2.190"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
# Upstream has no session-end signal support on Linux; see crates/clash-verge-signal.
|
||||
clash-verge-signal = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
tauri-plugin-wdio-webdriver = { version = "=1.4.0", optional = true }
|
||||
tauri-plugin-wdio-webdriver = { version = "=1.5.0", optional = true }
|
||||
objc2 = "0.6.5"
|
||||
objc2-foundation = { version = "0.3.2", features = [
|
||||
"NSString",
|
||||
@@ -150,8 +153,8 @@ windows-sys.workspace = true
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-autostart = "2.7.0"
|
||||
tauri-plugin-global-shortcut = "2.4.0"
|
||||
tauri-plugin-updater = "2.13.1"
|
||||
tauri-plugin-global-shortcut = "2.4.1"
|
||||
tauri-plugin-updater = "2.13.3"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { workspace = true }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Dev-only target: Tauri ships everything under src/bin/ to /usr/bin in deb/rpm
|
||||
// bundles (PR #8131), so this generator must stay an example, never a bin.
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut args = std::env::args_os().skip(1);
|
||||
let output = args
|
||||
@@ -73,9 +73,6 @@ pub struct IVerge {
|
||||
|
||||
pub collapse_navbar: Option<bool>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub enable_system_titlebar: Option<bool>,
|
||||
|
||||
pub sysproxy_tray_icon: Option<bool>,
|
||||
|
||||
pub tun_tray_icon: Option<bool>,
|
||||
@@ -377,7 +374,6 @@ impl IVerge {
|
||||
menu_icon: Some("monochrome".into()),
|
||||
notice_position: Some("top-right".into()),
|
||||
collapse_navbar: Some(false),
|
||||
enable_system_titlebar: Some(true),
|
||||
common_tray_icon: Some(false),
|
||||
sysproxy_tray_icon: Some(false),
|
||||
tun_tray_icon: Some(false),
|
||||
@@ -465,7 +461,6 @@ impl IVerge {
|
||||
patch!(proxy_group_tools_position);
|
||||
patch!(notice_position);
|
||||
patch!(collapse_navbar);
|
||||
patch!(enable_system_titlebar);
|
||||
patch!(common_tray_icon);
|
||||
patch!(sysproxy_tray_icon);
|
||||
patch!(tun_tray_icon);
|
||||
|
||||
@@ -67,7 +67,6 @@ verge_registry! {
|
||||
proxy_group_tools_position => NoEffect;
|
||||
notice_position => NoEffect;
|
||||
collapse_navbar => NoEffect;
|
||||
enable_system_titlebar => NoEffect;
|
||||
sysproxy_tray_icon => [TrayIcon];
|
||||
tun_tray_icon => [TrayIcon];
|
||||
enable_tun_mode => Tun;
|
||||
|
||||
@@ -130,7 +130,7 @@ pub async fn open_or_close_dashboard() {
|
||||
logging!(info, Type::Window, "Window toggle result: {result:?}");
|
||||
}
|
||||
|
||||
pub async fn quit() -> clash_verge_signal::ShutdownOutcome {
|
||||
pub async fn quit() {
|
||||
logging!(debug, Type::System, "启动退出流程");
|
||||
// 设置退出标志
|
||||
handle::Handle::global().set_is_exiting();
|
||||
@@ -165,13 +165,11 @@ pub async fn quit() -> clash_verge_signal::ShutdownOutcome {
|
||||
NoticeStatus::AppQuitCoreStopFailed,
|
||||
cleanup_result.stop_error.unwrap_or_default(),
|
||||
);
|
||||
return clash_verge_signal::ShutdownOutcome::Canceled;
|
||||
}
|
||||
|
||||
utils::server::shutdown_embedded_server();
|
||||
let app_handle = handle::Handle::app_handle();
|
||||
app_handle.exit(if cleanup_result.all_success { 0 } else { 1 });
|
||||
clash_verge_signal::ShutdownOutcome::Committed
|
||||
}
|
||||
|
||||
pub async fn clean_async() -> CleanupResult {
|
||||
|
||||
@@ -116,13 +116,9 @@ mod app_init {
|
||||
/// Setup window state management
|
||||
pub fn setup_window_state(app: &tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
logging!(debug, Type::Setup, "初始化窗口状态管理...");
|
||||
// Decorations are config-driven (`enable_system_titlebar`); restoring a stale
|
||||
// value here would override the builder's `.decorations(...)` on window recreate.
|
||||
let state_flags =
|
||||
tauri_plugin_window_state::StateFlags::all() & !tauri_plugin_window_state::StateFlags::DECORATIONS;
|
||||
let window_state_plugin = tauri_plugin_window_state::Builder::new()
|
||||
.with_filename(files::WINDOW_STATE)
|
||||
.with_state_flags(state_flags)
|
||||
.with_state_flags(tauri_plugin_window_state::StateFlags::default())
|
||||
.build();
|
||||
app.handle().plugin(window_state_plugin)?;
|
||||
Ok(())
|
||||
@@ -234,6 +230,7 @@ pub fn run() -> std::process::ExitCode {
|
||||
if let Err(panic) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
resolve::resolve_setup_async();
|
||||
resolve::resolve_setup_sync();
|
||||
#[cfg(target_os = "linux")]
|
||||
resolve::init_signal();
|
||||
})) {
|
||||
log_setup_panic("window-core", panic);
|
||||
|
||||
@@ -20,7 +20,6 @@ use crate::{
|
||||
utils::{init, server, window_manager::WindowManager},
|
||||
};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
use clash_verge_signal;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod dns;
|
||||
@@ -189,6 +188,8 @@ async fn init_silent_updater() {
|
||||
logging!(info, Type::Setup, "Silent updater initialized");
|
||||
}
|
||||
|
||||
// Upstream has no session-end signal support on Linux; see crates/clash-verge-signal.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn init_signal() {
|
||||
logging!(debug, Type::Setup, "Initializing signal handlers...");
|
||||
clash_verge_signal::register(feat::quit);
|
||||
|
||||
@@ -19,6 +19,11 @@ const DEFAULT_HEIGHT: f64 = 700.0;
|
||||
const MINIMAL_WIDTH: f64 = 520.0;
|
||||
const MINIMAL_HEIGHT: f64 = 520.0;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const DEFAULT_DECORATIONS: bool = false;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const DEFAULT_DECORATIONS: bool = true;
|
||||
|
||||
const fn restored_window_size_is_too_small(width: u32, height: u32) -> bool {
|
||||
width < MINIMAL_WIDTH as u32 || height < MINIMAL_HEIGHT as u32
|
||||
}
|
||||
@@ -44,7 +49,6 @@ pub async fn build_new_window() -> Result<WebviewWindow, String> {
|
||||
|
||||
let config = Config::verge().await;
|
||||
let latest = config.latest_arc();
|
||||
let decorations = latest.enable_system_titlebar.unwrap_or(true);
|
||||
let start_page = latest.start_page.as_deref().unwrap_or("/");
|
||||
let initial_theme_mode = match latest.theme_mode.as_deref() {
|
||||
Some("dark") => "dark",
|
||||
@@ -79,7 +83,7 @@ pub async fn build_new_window() -> Result<WebviewWindow, String> {
|
||||
)
|
||||
.title("Clash Verge")
|
||||
.center()
|
||||
.decorations(decorations)
|
||||
.decorations(DEFAULT_DECORATIONS)
|
||||
.fullscreen(false)
|
||||
.inner_size(DEFAULT_WIDTH, DEFAULT_HEIGHT)
|
||||
.min_inner_size(MINIMAL_WIDTH, MINIMAL_HEIGHT)
|
||||
|
||||
@@ -39,8 +39,6 @@ static INSTANCE_LOCK: OnceLock<std::fs::File> = OnceLock::new();
|
||||
const PAC_INITIAL_AVAILABLE: bool = false;
|
||||
static PAC_AVAILABLE: AtomicBool = AtomicBool::new(PAC_INITIAL_AVAILABLE);
|
||||
static COMMANDS_READY: AtomicBool = AtomicBool::new(false);
|
||||
#[cfg(feature = "verge-dev")]
|
||||
static DEV_QUIT_REQUESTED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SingletonDisposition {
|
||||
@@ -164,55 +162,12 @@ fn instance_auth(token: String) -> impl warp::Filter<Extract = (), Error = warp:
|
||||
.untuple_one()
|
||||
}
|
||||
|
||||
#[cfg(feature = "verge-dev")]
|
||||
fn dev_quit_route<F>(
|
||||
token: String,
|
||||
commands_ready: &'static AtomicBool,
|
||||
quit_requested: &'static AtomicBool,
|
||||
trigger: F,
|
||||
) -> impl warp::Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone
|
||||
where
|
||||
F: Fn() + Clone + Send + Sync + 'static,
|
||||
{
|
||||
instance_auth(token)
|
||||
.and(warp::path!("commands" / "dev" / "quit"))
|
||||
.and(warp::post())
|
||||
.and_then(move || {
|
||||
let trigger = trigger.clone();
|
||||
async move {
|
||||
if !commands_ready.load(Ordering::Acquire) {
|
||||
return Ok::<_, warp::Rejection>(warp::reply::with_status(
|
||||
String::from("starting"),
|
||||
warp::http::StatusCode::SERVICE_UNAVAILABLE,
|
||||
));
|
||||
}
|
||||
if quit_requested
|
||||
.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
|
||||
.is_ok()
|
||||
{
|
||||
trigger();
|
||||
}
|
||||
Ok(warp::reply::with_status(
|
||||
String::from("accepted"),
|
||||
warp::http::StatusCode::ACCEPTED,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "verge-dev")]
|
||||
fn release_dev_quit_latch(quit_requested: &AtomicBool, outcome: clash_verge_signal::ShutdownOutcome) {
|
||||
if matches!(outcome, clash_verge_signal::ShutdownOutcome::Canceled) {
|
||||
quit_requested.store(false, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
fn start_embedded_server(listener: tokio::net::TcpListener, token: String) {
|
||||
let (shutdown_tx, shutdown_rx) = oneshot::channel();
|
||||
let _ = SHUTDOWN_SENDER.set(Mutex::new(Some(shutdown_tx)));
|
||||
|
||||
#[cfg(feature = "verge-dev")]
|
||||
let auth = instance_auth(token.clone());
|
||||
let auth = instance_auth(token);
|
||||
#[cfg(not(feature = "verge-dev"))]
|
||||
let auth = instance_auth(token);
|
||||
|
||||
@@ -278,12 +233,6 @@ fn start_embedded_server(listener: tokio::net::TcpListener, token: String) {
|
||||
});
|
||||
|
||||
let commands = auth.clone().and(visible).or(auth.and(scheme)).or(pac);
|
||||
#[cfg(feature = "verge-dev")]
|
||||
let commands = commands.or(dev_quit_route(token, &COMMANDS_READY, &DEV_QUIT_REQUESTED, || {
|
||||
AsyncHandler::spawn(|| async {
|
||||
release_dev_quit_latch(&DEV_QUIT_REQUESTED, crate::feat::quit().await);
|
||||
});
|
||||
}));
|
||||
AsyncHandler::spawn(move || async move {
|
||||
warp::serve(commands)
|
||||
.incoming(listener)
|
||||
|
||||
@@ -202,9 +202,15 @@
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 36px;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
|
||||
&-drag-region {
|
||||
align-self: stretch;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-content__left .the-logo {
|
||||
@@ -229,9 +235,16 @@
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 36px;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
|
||||
&-drag-region {
|
||||
align-self: stretch;
|
||||
flex: 1 1 auto;
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-content__left {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Close, CropSquare, FilterNone, Minimize } from '@mui/icons-material'
|
||||
import { Box, IconButton } from '@mui/material'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import {
|
||||
type MouseEvent,
|
||||
forwardRef,
|
||||
type PointerEvent,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
} from 'react'
|
||||
|
||||
import { useWindowControls } from '@/hooks/use-window'
|
||||
import getSystem from '@/utils/get-system'
|
||||
|
||||
const RESIZE_HANDLES = [
|
||||
@@ -21,7 +21,9 @@ const RESIZE_HANDLES = [
|
||||
{ direction: 'NorthWest', position: 'north-west' },
|
||||
] as const
|
||||
|
||||
export const WindowResizeHandles = ({ maximized }: { maximized: boolean }) => {
|
||||
export const WindowResizeHandles = () => {
|
||||
const { currentWindow, maximized } = useWindowControls()
|
||||
|
||||
const startResizeDragging = useCallback(
|
||||
(event: PointerEvent<HTMLDivElement>) => {
|
||||
if (event.button !== 0) return
|
||||
@@ -31,14 +33,14 @@ export const WindowResizeHandles = ({ maximized }: { maximized: boolean }) => {
|
||||
const handle = RESIZE_HANDLES.find((item) => item.direction === direction)
|
||||
|
||||
if (handle) {
|
||||
void getCurrentWindow()
|
||||
void currentWindow
|
||||
.startResizeDragging(handle.direction)
|
||||
.catch((error) =>
|
||||
console.warn('[WindowResizeHandles] 调整窗口大小失败:', error),
|
||||
)
|
||||
}
|
||||
},
|
||||
[],
|
||||
[currentWindow],
|
||||
)
|
||||
|
||||
if (getSystem() !== 'linux' || maximized) return null
|
||||
@@ -61,77 +63,44 @@ export const WindowResizeHandles = ({ maximized }: { maximized: boolean }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const WindowControls = ({
|
||||
maximized,
|
||||
setMaximized,
|
||||
}: {
|
||||
maximized: boolean
|
||||
setMaximized: (value: boolean) => void
|
||||
}) => {
|
||||
export const WindowControls = forwardRef(function WindowControls(props, ref) {
|
||||
const OS = getSystem()
|
||||
const {
|
||||
currentWindow,
|
||||
maximized,
|
||||
minimize,
|
||||
close,
|
||||
toggleFullscreen,
|
||||
toggleMaximize,
|
||||
} = useWindowControls()
|
||||
|
||||
const close = useCallback(async () => {
|
||||
// Delay one frame so the UI can clear :hover before the window hides.
|
||||
await new Promise((resolve) => setTimeout(resolve, 20))
|
||||
await getCurrentWindow().close()
|
||||
}, [])
|
||||
|
||||
const minimize = useCallback(async () => {
|
||||
// Delay one frame so the UI can clear :hover before the window hides.
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await getCurrentWindow().minimize()
|
||||
}, [])
|
||||
|
||||
const toggleMaximize = useCallback(async () => {
|
||||
const currentWindow = getCurrentWindow()
|
||||
if (await currentWindow.isMaximized()) {
|
||||
await currentWindow.unmaximize()
|
||||
setMaximized(false)
|
||||
} else {
|
||||
await currentWindow.maximize()
|
||||
setMaximized(true)
|
||||
}
|
||||
}, [setMaximized])
|
||||
|
||||
useEffect(() => {
|
||||
getCurrentWindow().setMinimizable(true)
|
||||
}, [])
|
||||
|
||||
const handleTitlebarMouseDown = useCallback(
|
||||
(event: MouseEvent<HTMLDivElement>) => {
|
||||
// Left button only, and only on the first press: detail 2 is the second
|
||||
// press of a double-click, which `handleTitlebarDoubleClick` turns into maximize.
|
||||
if (event.button !== 0 || event.detail !== 1) return
|
||||
// Only the empty bar area drags; the control buttons keep their own clicks.
|
||||
if (event.target !== event.currentTarget) return
|
||||
event.preventDefault()
|
||||
void getCurrentWindow()
|
||||
.startDragging()
|
||||
.catch((error) => console.warn('[WindowControls] 开始拖动失败:', error))
|
||||
},
|
||||
[],
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
currentWindow,
|
||||
maximized,
|
||||
minimize,
|
||||
close,
|
||||
toggleFullscreen,
|
||||
toggleMaximize,
|
||||
}),
|
||||
[
|
||||
currentWindow,
|
||||
maximized,
|
||||
minimize,
|
||||
close,
|
||||
toggleFullscreen,
|
||||
toggleMaximize,
|
||||
],
|
||||
)
|
||||
|
||||
const handleTitlebarDoubleClick = useCallback(
|
||||
(event: MouseEvent<HTMLDivElement>) => {
|
||||
if (event.target !== event.currentTarget) return
|
||||
void toggleMaximize().catch((error) =>
|
||||
console.warn('[WindowControls] 切换最大化失败:', error),
|
||||
)
|
||||
},
|
||||
[toggleMaximize],
|
||||
)
|
||||
// 通过前端对 tauri 窗口进行翻转全屏时会短暂地与系统图标重叠渲染。
|
||||
// 这可能是上游缺陷,保险起见跨平台以窗口的最大化翻转为准。
|
||||
|
||||
return (
|
||||
<Box
|
||||
onMouseDown={handleTitlebarMouseDown}
|
||||
onDoubleClick={handleTitlebarDoubleClick}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: OS === 'macos' ? 'flex-start' : 'flex-end',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
px: 1,
|
||||
gap: 1,
|
||||
alignItems: 'center',
|
||||
'> button': {
|
||||
@@ -217,4 +186,4 @@ export const WindowControls = ({
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -12,21 +12,16 @@ import {
|
||||
} from '@mui/material'
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { join } from '@tauri-apps/api/path'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { open as openDialog } from '@tauri-apps/plugin-dialog'
|
||||
import { exists } from '@tauri-apps/plugin-fs'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import {
|
||||
BaseDialog,
|
||||
type DialogRef,
|
||||
Switch,
|
||||
TooltipIcon,
|
||||
} from '@/components/base'
|
||||
import { BaseDialog, DialogRef, Switch, TooltipIcon } from '@/components/base'
|
||||
import { DEFAULT_HOVER_DELAY } from '@/components/proxy/proxy-group-navigator'
|
||||
import { useVerge } from '@/hooks/use-verge'
|
||||
import { copyIconFile, getAppDir, restartApp } from '@/services/cmds'
|
||||
import { useWindowDecorations } from '@/hooks/use-window'
|
||||
import { copyIconFile, getAppDir } from '@/services/cmds'
|
||||
import { mutate } from '@/services/mutate'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import getSystem from '@/utils/get-system'
|
||||
@@ -63,6 +58,8 @@ export const LayoutViewer = forwardRef<DialogRef>((_, ref) => {
|
||||
const [sysproxyIcon, setSysproxyIcon] = useState('')
|
||||
const [tunIcon, setTunIcon] = useState('')
|
||||
|
||||
const { decorated, toggleDecorations } = useWindowDecorations()
|
||||
|
||||
useEffect(() => {
|
||||
initIconPath()
|
||||
}, [])
|
||||
@@ -126,50 +123,17 @@ export const LayoutViewer = forwardRef<DialogRef>((_, ref) => {
|
||||
<List>
|
||||
<Item>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<span>
|
||||
{t(
|
||||
'settings.components.verge.layout.fields.enableSystemTitlebar',
|
||||
)}
|
||||
</span>
|
||||
<TooltipIcon
|
||||
title={t(
|
||||
'settings.components.verge.layout.tooltips.enableSystemTitlebar',
|
||||
)}
|
||||
sx={{ opacity: '0.7' }}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
primary={t(
|
||||
'settings.components.verge.layout.fields.preferSystemTitlebar',
|
||||
)}
|
||||
/>
|
||||
<GuardState
|
||||
value={verge?.enable_system_titlebar ?? true}
|
||||
value={decorated}
|
||||
valueProps="checked"
|
||||
onCatch={onError}
|
||||
onFormat={onSwitchFormat}
|
||||
onChange={(e) => onChangeData({ enable_system_titlebar: e })}
|
||||
onGuard={async (e) => {
|
||||
await patchVerge({ enable_system_titlebar: e })
|
||||
if (OS === 'linux') {
|
||||
void mutate(() => restartApp(), {
|
||||
id: 'restart-app',
|
||||
errorNotice: false,
|
||||
}).catch((error) => {
|
||||
console.warn('[LayoutViewer] failed to restart app:', error)
|
||||
})
|
||||
} else {
|
||||
const currentWindow = getCurrentWindow()
|
||||
try {
|
||||
await currentWindow.setDecorations(e)
|
||||
// macOS clears the Miniaturizable style bit when decorations are disabled; re-enable minimize.
|
||||
await currentWindow.setMinimizable(true)
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'[LayoutViewer] failed to apply system titlebar setting:',
|
||||
error,
|
||||
)
|
||||
}
|
||||
}
|
||||
onChange={async () => {
|
||||
await toggleDecorations()
|
||||
}}
|
||||
>
|
||||
<Switch edge="end" />
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import debounce from '@/utils/debounce'
|
||||
|
||||
export const useWindowMaximized = (enabled: boolean) => {
|
||||
const [maximized, setMaximized] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return
|
||||
|
||||
const currentWindow = getCurrentWindow()
|
||||
let isUnmounted = false
|
||||
|
||||
const syncMaximized = async () => {
|
||||
if (isUnmounted) return
|
||||
try {
|
||||
setMaximized(await currentWindow.isMaximized())
|
||||
} catch (error) {
|
||||
console.warn('[useWindowMaximized] 读取最大化状态失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
void syncMaximized()
|
||||
|
||||
const unlistenPromise = currentWindow.onResized(
|
||||
debounce(syncMaximized, 300),
|
||||
)
|
||||
|
||||
return () => {
|
||||
isUnmounted = true
|
||||
unlistenPromise
|
||||
.then((unlisten) => unlisten())
|
||||
.catch((err) =>
|
||||
console.warn('[useWindowMaximized] 清理监听器失败:', err),
|
||||
)
|
||||
}
|
||||
}, [enabled])
|
||||
|
||||
return { maximized, setMaximized }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { use } from 'react'
|
||||
|
||||
import { WindowContext, type WindowContextType } from '@/providers/window'
|
||||
|
||||
const useWindow = () => {
|
||||
const context = use(WindowContext)
|
||||
if (context === undefined) {
|
||||
throw new Error('useWindow must be used within WindowProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
export const useWindowControls = () => {
|
||||
const {
|
||||
maximized,
|
||||
minimize,
|
||||
toggleMaximize,
|
||||
close,
|
||||
toggleFullscreen,
|
||||
currentWindow,
|
||||
} = useWindow()
|
||||
return {
|
||||
maximized,
|
||||
minimize,
|
||||
toggleMaximize,
|
||||
close,
|
||||
toggleFullscreen,
|
||||
currentWindow,
|
||||
} satisfies Pick<
|
||||
WindowContextType,
|
||||
| 'maximized'
|
||||
| 'minimize'
|
||||
| 'toggleMaximize'
|
||||
| 'close'
|
||||
| 'toggleFullscreen'
|
||||
| 'currentWindow'
|
||||
>
|
||||
}
|
||||
|
||||
export const useWindowDecorations = () => {
|
||||
const { decorated, toggleDecorations, refreshDecorated } = useWindow()
|
||||
return { decorated, toggleDecorations, refreshDecorated } satisfies Pick<
|
||||
WindowContextType,
|
||||
'decorated' | 'toggleDecorations' | 'refreshDecorated'
|
||||
>
|
||||
}
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "إعدادات التخطيط",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "تفعيل شريط عنوان النظام",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "مخطط حركة المرور",
|
||||
"memoryUsage": "استهلاك الذاكرة",
|
||||
"proxyGroupIcon": "أيقونة مجموعة الوكلاء",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "إيقاف عرض إحصاءات حركة المرور مؤقتًا عند فقدان التركيز"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "استخدام شريط عنوان النظام الأصلي بدلاً من شريط العنوان المخصص المدمج (يلزم إعادة التشغيل على Linux).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Layout-Einstellungen",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "System-Titelleiste aktivieren",
|
||||
"preferSystemTitlebar": "System-Titelleiste bevorzugen",
|
||||
"trafficGraph": "Verkehrsdiagramm",
|
||||
"memoryUsage": "Kern-Speichernutzung",
|
||||
"proxyGroupIcon": "Proxy-Gruppen-Symbol",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Rendering der Verkehrsstatistiken bei Fokusverlust pausieren"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Die native Titelleiste des Systems anstelle der integrierten benutzerdefinierten Titelleiste verwenden (unter Linux ist ein Neustart erforderlich).",
|
||||
"hoverNavigator": "Beim Darüberfahren mit der Maus über die Buchstaben automatisch zur passenden Proxy-Gruppe scrollen",
|
||||
"hoverNavigatorDelay": "Wartezeit vor dem automatischen Scrollen beim Darüberfahren, in Millisekunden"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Layout Setting",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Enable System Titlebar",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "Traffic Graph",
|
||||
"memoryUsage": "Core Usage",
|
||||
"proxyGroupIcon": "Proxy Group Icon",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Pause rendering traffic statistics when blurred"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Use the system's native title bar instead of the built-in custom title bar (restart required on Linux).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Configuración de la interfaz",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Activar barra de título del sistema",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "Gráfico de tráfico",
|
||||
"memoryUsage": "Uso de memoria del núcleo",
|
||||
"proxyGroupIcon": "Icono del grupo de proxy",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Pausar el renderizado de estadísticas de tráfico al perder el foco"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Usar la barra de título nativa del sistema en lugar de la barra de título personalizada integrada (se requiere reiniciar en Linux).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "تنظیمات چیدمان",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "فعالسازی نوار عنوان سیستم",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "نمودار ترافیک",
|
||||
"memoryUsage": "استفاده از حافظه",
|
||||
"proxyGroupIcon": "آیکون گروه پراکسی",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "توقف رندر آمار ترافیک هنگام از دست رفتن فوکوس"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "استفاده از نوار عنوان بومی سیستم بهجای نوار عنوان سفارشی داخلی (در لینوکس نیاز به راهاندازی مجدد است).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Pengaturan Tata Letak",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Aktifkan bilah judul sistem",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "Grafik Lalu Lintas",
|
||||
"memoryUsage": "Penggunaan Memori",
|
||||
"proxyGroupIcon": "Ikon Grup Proksi",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Jeda render statistik lalu lintas saat jendela tidak fokus"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Gunakan bilah judul asli sistem sebagai ganti bilah judul kustom bawaan (perlu mulai ulang di Linux).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "レイアウト設定",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "システムタイトルバーを有効にする",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "トラフィックグラフ",
|
||||
"memoryUsage": "コアメモリ使用量",
|
||||
"proxyGroupIcon": "プロキシグループアイコン",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "フォーカスを失ったときにトラフィック統計の描画を一時停止"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "内蔵のカスタムタイトルバーの代わりにシステム標準のタイトルバーを使用します(Linux では再起動が必要です)。",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "레이아웃 설정",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "시스템 제목 표시줄 활성화",
|
||||
"preferSystemTitlebar": "시스템 제목 표시줄 사용",
|
||||
"trafficGraph": "트래픽 그래프",
|
||||
"memoryUsage": "메모리 사용량",
|
||||
"proxyGroupIcon": "프록시 그룹 아이콘",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "포커스를 잃으면 트래픽 통계 렌더링 일시 중지"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "내장 사용자 지정 제목 표시줄 대신 시스템 기본 제목 표시줄을 사용합니다(Linux에서는 다시 시작해야 함).",
|
||||
"hoverNavigator": "알파벳에 마우스를 올리면 해당 프록시 그룹으로 자동 스크롤합니다",
|
||||
"hoverNavigatorDelay": "호버 시 자동 스크롤까지의 지연(밀리초)"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Configurações de Layout",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Ativar barra de título do sistema",
|
||||
"preferSystemTitlebar": "Preferir Barra de Título do Sistema",
|
||||
"trafficGraph": "Gráfico de Tráfego",
|
||||
"memoryUsage": "Uso do Núcleo",
|
||||
"proxyGroupIcon": "Ícone do Grupo de Proxy",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Pausar a renderização das estatísticas de tráfego quando sem foco"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Usar a barra de título nativa do sistema em vez da barra de título personalizada integrada (é necessário reiniciar no Linux).",
|
||||
"hoverNavigator": "Rola automaticamente até o grupo de proxy correspondente ao passar o mouse sobre as letras do alfabeto",
|
||||
"hoverNavigatorDelay": "Atraso antes da rolagem automática ao passar o mouse, em milissegundos"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Настройки раскладки",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Включить системную панель заголовка",
|
||||
"preferSystemTitlebar": "Использовать системную панель заголовка",
|
||||
"trafficGraph": "График трафика",
|
||||
"memoryUsage": "Использование памяти",
|
||||
"proxyGroupIcon": "Значок группы прокси",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "При потере фокуса приостанавливать отрисовку статистики трафика"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Использовать системную панель заголовка вместо встроенной настраиваемой (в Linux требуется перезапуск).",
|
||||
"hoverNavigator": "Автоматически прокручивает к группе прокси при наведении на буквы",
|
||||
"hoverNavigatorDelay": "Задержка перед прокруткой при наведении (в миллисекундах)"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Düzen Ayarı",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Sistem başlık çubuğunu etkinleştir",
|
||||
"preferSystemTitlebar": "Sistem Başlık Çubuğunu Tercih Et",
|
||||
"trafficGraph": "Trafik Grafiği",
|
||||
"memoryUsage": "Çekirdek Kullanımı",
|
||||
"proxyGroupIcon": "Vekil Grup Simgesi",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Odak kaybolduğunda trafik istatistiklerinin işlenmesini duraklat"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Yerleşik özel başlık çubuğu yerine sistemin yerel başlık çubuğunu kullan (Linux'ta yeniden başlatma gerekir).",
|
||||
"hoverNavigator": "Alfabe harflerinin üzerine gelindiğinde ilgili vekil grubuna otomatik olarak kaydırır",
|
||||
"hoverNavigatorDelay": "Üzerine gelindiğinde otomatik kaydırmadan önceki gecikme, milisaniye cinsinden"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "Расположение көйләүләре",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "Enable System Titlebar",
|
||||
"preferSystemTitlebar": "Prefer System Titlebar",
|
||||
"trafficGraph": "Трафик графигы",
|
||||
"memoryUsage": "Хәтер куллану",
|
||||
"proxyGroupIcon": "Прокси төркеме иконкасы",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "Фокус югалганда трафик статистикасын сызуны туктатып тору"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "Use the system's native title bar instead of the built-in custom title bar (restart required on Linux).",
|
||||
"hoverNavigator": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
|
||||
"hoverNavigatorDelay": "Delay before auto scrolling when hovering, in milliseconds"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "界面设置",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "启用系统标题栏",
|
||||
"preferSystemTitlebar": "优先使用系统标题栏",
|
||||
"trafficGraph": "流量图显",
|
||||
"memoryUsage": "内核占用",
|
||||
"proxyGroupIcon": "代理组图标",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "失去焦点时暂停渲染流量统计"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "使用系统原生标题栏替代内置的自定义标题栏(Linux 下需重启生效)",
|
||||
"hoverNavigator": "鼠标悬停在字母上时自动滚动到对应代理组",
|
||||
"hoverNavigatorDelay": "鼠标悬停后触发自动跳转前等待的毫秒数"
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"layout": {
|
||||
"title": "介面設定",
|
||||
"fields": {
|
||||
"enableSystemTitlebar": "啟用系統標題欄",
|
||||
"preferSystemTitlebar": "優先使用系統標題欄",
|
||||
"trafficGraph": "流量圖表",
|
||||
"memoryUsage": "內核佔用",
|
||||
"proxyGroupIcon": "代理組圖示",
|
||||
@@ -251,7 +251,6 @@
|
||||
"pauseRenderTrafficStatsOnBlur": "失去焦點時暫停渲染流量統計"
|
||||
},
|
||||
"tooltips": {
|
||||
"enableSystemTitlebar": "使用系統原生標題欄取代內建的自訂標題欄(Linux 需重新啟動生效)",
|
||||
"hoverNavigator": "滑鼠懸停在字母上時自動捲動到對應代理組",
|
||||
"hoverNavigatorDelay": "滑鼠懸停後觸發自動跳轉前等待的毫秒數"
|
||||
},
|
||||
|
||||
+6
-3
@@ -12,6 +12,7 @@ import { BaseErrorBoundary } from './components/base'
|
||||
import { router } from './pages/_routers'
|
||||
import { preloadHomePageCards } from './pages/home'
|
||||
import { AppDataProvider } from './providers/app-data-provider'
|
||||
import { WindowProvider } from './providers/window'
|
||||
import { FALLBACK_LANGUAGE, initializeLanguage } from './services/i18n'
|
||||
import {
|
||||
preloadAppData,
|
||||
@@ -49,9 +50,11 @@ const initializeApp = (initialThemeMode: 'light' | 'dark') => {
|
||||
<ComposeContextProvider contexts={contexts}>
|
||||
<BaseErrorBoundary>
|
||||
<SWRConfig value={swrConfig}>
|
||||
<AppDataProvider>
|
||||
<RouterProvider router={router} />
|
||||
</AppDataProvider>
|
||||
<WindowProvider>
|
||||
<AppDataProvider>
|
||||
<RouterProvider router={router} />
|
||||
</AppDataProvider>
|
||||
</WindowProvider>
|
||||
</SWRConfig>
|
||||
</BaseErrorBoundary>
|
||||
</ComposeContextProvider>
|
||||
|
||||
+13
-9
@@ -1,7 +1,7 @@
|
||||
import { Paper, ThemeProvider } from '@mui/material'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Outlet, useNavigate } from 'react-router'
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from '@/components/layout/window-controller'
|
||||
import { useI18n } from '@/hooks/use-i18n'
|
||||
import { useVerge } from '@/hooks/use-verge'
|
||||
import { useWindowMaximized } from '@/hooks/use-window-maximized'
|
||||
import { useWindowDecorations } from '@/hooks/use-window'
|
||||
import { useEventBus } from '@/services/bus'
|
||||
import { handleNoticeMessage } from '@/services/notice-handlers'
|
||||
import { useThemeMode } from '@/services/states'
|
||||
@@ -46,17 +46,21 @@ const Layout = () => {
|
||||
const { switchLanguage } = useI18n()
|
||||
const navigate = useNavigate()
|
||||
const themeReady = useMemo(() => Boolean(theme), [theme])
|
||||
const showCustomTitlebar = verge?.enable_system_titlebar === false
|
||||
const { maximized, setMaximized } = useWindowMaximized(showCustomTitlebar)
|
||||
const windowControlsRef = useRef<any>(null)
|
||||
const { decorated } = useWindowDecorations()
|
||||
|
||||
const customTitlebar = useMemo(
|
||||
() =>
|
||||
showCustomTitlebar ? (
|
||||
decorated === false ? (
|
||||
<div className="the_titlebar">
|
||||
<WindowControls maximized={maximized} setMaximized={setMaximized} />
|
||||
<div
|
||||
className="the_titlebar-drag-region"
|
||||
data-tauri-drag-region="true"
|
||||
/>
|
||||
<WindowControls ref={windowControlsRef} />
|
||||
</div>
|
||||
) : null,
|
||||
[showCustomTitlebar, maximized, setMaximized],
|
||||
[decorated],
|
||||
)
|
||||
|
||||
useLoadingOverlay(themeReady)
|
||||
@@ -150,9 +154,9 @@ const Layout = () => {
|
||||
: {},
|
||||
]}
|
||||
>
|
||||
{showCustomTitlebar && <WindowResizeHandles maximized={maximized} />}
|
||||
{decorated === false && <WindowResizeHandles />}
|
||||
|
||||
{/* Custom titlebar - rendered only when the system titlebar is not preferred, memoized for performance */}
|
||||
{/* Custom titlebar - rendered only when decorated is false, memoized for performance */}
|
||||
{customTitlebar}
|
||||
|
||||
<div className="layout-content">
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export { WindowContext } from './window-context'
|
||||
export type { WindowContextType } from './window-context'
|
||||
export { WindowProvider } from './window-provider'
|
||||
@@ -0,0 +1,18 @@
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { createContext } from 'react'
|
||||
|
||||
export interface WindowContextType {
|
||||
decorated: boolean | null
|
||||
maximized: boolean | null
|
||||
toggleDecorations: () => Promise<void>
|
||||
refreshDecorated: () => Promise<boolean>
|
||||
minimize: () => Promise<void>
|
||||
close: () => Promise<void>
|
||||
toggleMaximize: () => Promise<void>
|
||||
toggleFullscreen: () => Promise<void>
|
||||
currentWindow: ReturnType<typeof getCurrentWindow>
|
||||
}
|
||||
|
||||
export const WindowContext = createContext<WindowContextType | undefined>(
|
||||
undefined,
|
||||
)
|
||||
@@ -0,0 +1,111 @@
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import debounce from '@/utils/debounce'
|
||||
|
||||
import { WindowContext } from './window-context'
|
||||
|
||||
export const WindowProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const currentWindow = useMemo(() => getCurrentWindow(), [])
|
||||
const [decorated, setDecorated] = useState<boolean | null>(null)
|
||||
const [maximized, setMaximized] = useState<boolean | null>(null)
|
||||
|
||||
const close = useCallback(async () => {
|
||||
// Delay one frame so the UI can clear :hover before the window hides.
|
||||
await new Promise((resolve) => setTimeout(resolve, 20))
|
||||
await currentWindow.close()
|
||||
}, [currentWindow])
|
||||
const minimize = useCallback(async () => {
|
||||
// Delay one frame so the UI can clear :hover before the window hides.
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await currentWindow.minimize()
|
||||
}, [currentWindow])
|
||||
|
||||
useEffect(() => {
|
||||
let isUnmounted = false
|
||||
let lastWidth = -1
|
||||
let lastHeight = -1
|
||||
|
||||
const checkMaximized = debounce(
|
||||
async (event: { payload: { width: number; height: number } }) => {
|
||||
if (isUnmounted) return
|
||||
const { width, height } = event.payload
|
||||
if (width === lastWidth && height === lastHeight) return
|
||||
lastWidth = width
|
||||
lastHeight = height
|
||||
const value = await currentWindow.isMaximized()
|
||||
setMaximized(value)
|
||||
},
|
||||
300,
|
||||
)
|
||||
|
||||
const unlistenPromise = currentWindow.onResized(checkMaximized)
|
||||
|
||||
return () => {
|
||||
isUnmounted = true
|
||||
unlistenPromise
|
||||
.then((unlisten) => unlisten())
|
||||
.catch((err) => console.warn('[WindowProvider] 清理监听器失败:', err))
|
||||
}
|
||||
}, [currentWindow])
|
||||
|
||||
const toggleMaximize = useCallback(async () => {
|
||||
if (await currentWindow.isMaximized()) {
|
||||
await currentWindow.unmaximize()
|
||||
setMaximized(false)
|
||||
} else {
|
||||
await currentWindow.maximize()
|
||||
setMaximized(true)
|
||||
}
|
||||
}, [currentWindow])
|
||||
|
||||
const toggleFullscreen = useCallback(async () => {
|
||||
await currentWindow.setFullscreen(!(await currentWindow.isFullscreen()))
|
||||
}, [currentWindow])
|
||||
|
||||
const refreshDecorated = useCallback(async () => {
|
||||
const val = await currentWindow.isDecorated()
|
||||
setDecorated(val)
|
||||
return val
|
||||
}, [currentWindow])
|
||||
|
||||
const toggleDecorations = useCallback(async () => {
|
||||
const currentVal = await currentWindow.isDecorated()
|
||||
await currentWindow.setDecorations(!currentVal)
|
||||
setDecorated(!currentVal)
|
||||
}, [currentWindow])
|
||||
|
||||
useEffect(() => {
|
||||
refreshDecorated()
|
||||
currentWindow.setMinimizable?.(true)
|
||||
}, [currentWindow, refreshDecorated])
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
decorated,
|
||||
maximized,
|
||||
toggleDecorations,
|
||||
refreshDecorated,
|
||||
minimize,
|
||||
close,
|
||||
toggleMaximize,
|
||||
toggleFullscreen,
|
||||
currentWindow,
|
||||
}),
|
||||
[
|
||||
decorated,
|
||||
maximized,
|
||||
toggleDecorations,
|
||||
refreshDecorated,
|
||||
minimize,
|
||||
close,
|
||||
toggleMaximize,
|
||||
toggleFullscreen,
|
||||
currentWindow,
|
||||
],
|
||||
)
|
||||
|
||||
return <WindowContext value={contextValue}>{children}</WindowContext>
|
||||
}
|
||||
@@ -375,7 +375,6 @@ export type IVerge_Deserialize = {
|
||||
proxy_group_tools_position?: string | null
|
||||
notice_position?: string | null
|
||||
collapse_navbar?: boolean | null
|
||||
enable_system_titlebar?: boolean | null
|
||||
sysproxy_tray_icon?: boolean | null
|
||||
tun_tray_icon?: boolean | null
|
||||
enable_tun_mode?: boolean | null
|
||||
@@ -466,7 +465,6 @@ export type IVerge_Serialize = {
|
||||
proxy_group_tools_position?: string | null
|
||||
notice_position?: string | null
|
||||
collapse_navbar: boolean | null
|
||||
enable_system_titlebar?: boolean | null
|
||||
sysproxy_tray_icon: boolean | null
|
||||
tun_tray_icon: boolean | null
|
||||
enable_tun_mode: boolean | null
|
||||
|
||||
@@ -533,7 +533,7 @@ export const translationKeys = [
|
||||
'settings.components.verge.theme.actions.editCss',
|
||||
'settings.components.verge.theme.dialogs.editCssTitle',
|
||||
'settings.components.verge.layout.title',
|
||||
'settings.components.verge.layout.fields.enableSystemTitlebar',
|
||||
'settings.components.verge.layout.fields.preferSystemTitlebar',
|
||||
'settings.components.verge.layout.fields.trafficGraph',
|
||||
'settings.components.verge.layout.fields.memoryUsage',
|
||||
'settings.components.verge.layout.fields.proxyGroupIcon',
|
||||
@@ -551,7 +551,6 @@ export const translationKeys = [
|
||||
'settings.components.verge.layout.fields.enableTrayIcon',
|
||||
'settings.components.verge.layout.fields.enableTraySpeed',
|
||||
'settings.components.verge.layout.fields.pauseRenderTrafficStatsOnBlur',
|
||||
'settings.components.verge.layout.tooltips.enableSystemTitlebar',
|
||||
'settings.components.verge.layout.tooltips.hoverNavigator',
|
||||
'settings.components.verge.layout.tooltips.hoverNavigatorDelay',
|
||||
'settings.components.verge.layout.options.icon.monochrome',
|
||||
|
||||
@@ -746,7 +746,6 @@ export interface TranslationResources {
|
||||
fields: {
|
||||
collapseNavBar: string
|
||||
commonTrayIcon: string
|
||||
enableSystemTitlebar: string
|
||||
enableTrayIcon: string
|
||||
enableTraySpeed: string
|
||||
hoverNavigator: string
|
||||
@@ -754,6 +753,7 @@ export interface TranslationResources {
|
||||
memoryUsage: string
|
||||
navIcon: string
|
||||
pauseRenderTrafficStatsOnBlur: string
|
||||
preferSystemTitlebar: string
|
||||
proxyGroupIcon: string
|
||||
proxyGroupsDisplayMode: string
|
||||
showOutboundModesInline: string
|
||||
@@ -783,7 +783,6 @@ export interface TranslationResources {
|
||||
}
|
||||
title: string
|
||||
tooltips: {
|
||||
enableSystemTitlebar: string
|
||||
hoverNavigator: string
|
||||
hoverNavigatorDelay: string
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function getSystem() {
|
||||
|
||||
if (/win64|win32/i.test(ua) || platform === 'win32') return 'windows'
|
||||
|
||||
if (/linux/i.test(ua) || platform === 'linux') return 'linux'
|
||||
if (/linux/i.test(ua)) return 'linux'
|
||||
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user