mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-04 06:02:08 +08:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcacd5e0e6 | ||
|
|
d8cce2ee2c | ||
|
|
e69c8aeccf | ||
|
|
d2c6eafc9e |
Generated
+123
-187
@@ -150,7 +150,7 @@ dependencies = [
|
|||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-core-graphics",
|
"objc2-core-graphics",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"parking_lot 0.12.5",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
"wl-clipboard-rs",
|
"wl-clipboard-rs",
|
||||||
@@ -159,9 +159,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
version = "1.9.3"
|
version = "1.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "380962b3d93b99642e50b9febf72c071e97e8b32d86eae9cf4ef582bb960ae6e"
|
checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustversion",
|
"rustversion",
|
||||||
]
|
]
|
||||||
@@ -1117,7 +1117,7 @@ dependencies = [
|
|||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"open",
|
"open",
|
||||||
"parking_lot 0.13.0",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest 0.13.5",
|
"reqwest 0.13.5",
|
||||||
@@ -1175,7 +1175,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"criterion",
|
"criterion",
|
||||||
"parking_lot 0.13.0",
|
"parking_lot",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1198,7 +1198,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"flexi_logger",
|
"flexi_logger",
|
||||||
"log",
|
"log",
|
||||||
"parking_lot 0.13.0",
|
"parking_lot",
|
||||||
"tracing-estuary",
|
"tracing-estuary",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1255,8 +1255,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "facfbc410a385e0b0cbca8179dd9e363ed70e8455960bf7545137e90ca753b66"
|
checksum = "facfbc410a385e0b0cbca8179dd9e363ed70e8455960bf7545137e90ca753b66"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"lock_api 0.4.14",
|
"lock_api",
|
||||||
"parking_lot_core 0.9.12",
|
"parking_lot_core",
|
||||||
"polonius-the-crab",
|
"polonius-the-crab",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1333,7 +1333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1767,18 +1767,8 @@ version = "0.23.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
|
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core 0.23.0",
|
"darling_core",
|
||||||
"darling_macro 0.23.0",
|
"darling_macro",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.24.1",
|
|
||||||
"darling_macro 0.24.1",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1794,41 +1784,17 @@ dependencies = [
|
|||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff"
|
|
||||||
dependencies = [
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn 3.0.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.23.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
|
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core 0.23.0",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.24.1",
|
|
||||||
"quote",
|
|
||||||
"syn 3.0.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashmap"
|
name = "dashmap"
|
||||||
version = "6.2.1"
|
version = "6.2.1"
|
||||||
@@ -1838,9 +1804,9 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
"lock_api 0.4.14",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core 0.9.12",
|
"parking_lot_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1918,9 +1884,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "devtools-core"
|
name = "devtools-core"
|
||||||
version = "0.4.2"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9e85926bda763dd434fcfbcfb24af4b2c1a8c3e3c34bcd5d844c48f655cca51"
|
checksum = "c53d416e473377276435d49d731a75d253b96ee4339831cd85653702b94d8298"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"devtools-wire-format",
|
"devtools-wire-format",
|
||||||
@@ -2048,7 +2014,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users 0.5.2",
|
"redox_users 0.5.2",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2307,7 +2273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2823,7 +2789,7 @@ dependencies = [
|
|||||||
"gobject-sys 0.21.5",
|
"gobject-sys 0.21.5",
|
||||||
"libc",
|
"libc",
|
||||||
"system-deps 7.0.8",
|
"system-deps 7.0.8",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3377,7 +3343,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core 0.62.2",
|
"windows-core 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3391,12 +3357,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ico"
|
name = "ico"
|
||||||
version = "0.6.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75e94d66081e4d8dcd098bd8dc5254800fea14a26389b298410158d834de167"
|
checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"png",
|
"png 0.17.16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3582,7 +3548,7 @@ dependencies = [
|
|||||||
"byteorder-lite",
|
"byteorder-lite",
|
||||||
"moxcms",
|
"moxcms",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"png",
|
"png 0.18.1",
|
||||||
"tiff",
|
"tiff",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3891,7 +3857,7 @@ dependencies = [
|
|||||||
"http",
|
"http",
|
||||||
"httparse",
|
"httparse",
|
||||||
"libc",
|
"libc",
|
||||||
"parking_lot 0.12.5",
|
"parking_lot",
|
||||||
"path-tree",
|
"path-tree",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rand 0.10.2",
|
"rand 0.10.2",
|
||||||
@@ -4051,20 +4017,11 @@ dependencies = [
|
|||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "65d91b22da179613dcf4d6ec8349563f52a363f6849e03b00dd0a185ec4a59af"
|
|
||||||
dependencies = [
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.35"
|
version = "0.4.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c"
|
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru-slab"
|
name = "lru-slab"
|
||||||
@@ -4074,9 +4031,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lzma-rust2"
|
name = "lzma-rust2"
|
||||||
version = "0.24.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "490750560fa7851fbbf5d3ab1a8750f09350ed361ed8aed85b1e1e40587812ee"
|
checksum = "f1c46f3fcd2e888afdb01a07efc071cb21300e07c68d32c3e8b01b5c8cb1fcaa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sha2 0.11.1",
|
"sha2 0.11.1",
|
||||||
]
|
]
|
||||||
@@ -4254,10 +4211,10 @@ dependencies = [
|
|||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"png",
|
"png 0.18.1",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4424,7 +4381,7 @@ version = "0.50.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4806,7 +4763,7 @@ version = "1.21.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parking_lot_core 0.9.12",
|
"parking_lot_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4829,9 +4786,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "5.4.5"
|
version = "5.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d8c8b8e725ad26404d6896eb2f064294a0a7b4f1d9120210d85544684c4ca95"
|
checksum = "aa576c76302b7b808eecc68061e67336c47833ef9d22caa74dda10fa9675eebc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
"dunce",
|
||||||
"is-wsl",
|
"is-wsl",
|
||||||
@@ -4901,7 +4858,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4965,18 +4922,8 @@ version = "0.12.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api 0.4.14",
|
"lock_api",
|
||||||
"parking_lot_core 0.9.12",
|
"parking_lot_core",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9cf937ca4e1d0b7578784559063422fc39ae7c5a00f02471f2614d5486fd226"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api 0.5.0",
|
|
||||||
"parking_lot_core 0.10.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4987,19 +4934,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.5.18",
|
"redox_syscall",
|
||||||
"smallvec",
|
|
||||||
"windows-link 0.2.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9cfff060068cc18aa7815010fcaf80c68c7fb9e85fc7f5c0f9bf142c21d19826"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"redox_syscall 0.9.4",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
@@ -5290,6 +5225,19 @@ dependencies = [
|
|||||||
"plotters-backend",
|
"plotters-backend",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide 0.8.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
@@ -5575,7 +5523,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5719,15 +5667,6 @@ dependencies = [
|
|||||||
"bitflags 2.13.2",
|
"bitflags 2.13.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.9.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "737970939a87c6fa31e7acad13307bccbb017a073b695b6089a2c484f929e20e"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.13.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@@ -5925,9 +5864,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rfd"
|
name = "rfd"
|
||||||
version = "0.17.2"
|
version = "0.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220"
|
checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"dispatch2",
|
"dispatch2",
|
||||||
@@ -5935,18 +5874,16 @@ dependencies = [
|
|||||||
"gobject-sys 0.18.0",
|
"gobject-sys 0.18.0",
|
||||||
"gtk-sys",
|
"gtk-sys",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
|
||||||
"log",
|
"log",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"percent-encoding",
|
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6090,7 +6027,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.4.15",
|
"linux-raw-sys 0.4.15",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6103,7 +6040,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6162,7 +6099,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6540,7 +6477,7 @@ version = "3.21.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
|
checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling 0.23.0",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
@@ -6782,7 +6719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6800,7 +6737,7 @@ dependencies = [
|
|||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"redox_syscall 0.5.18",
|
"redox_syscall",
|
||||||
"tracing",
|
"tracing",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
@@ -6835,9 +6772,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specta"
|
name = "specta"
|
||||||
version = "2.0.0-rc.26"
|
version = "2.0.0-rc.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed155e448f42fc4be7a5cbc12bd43f6c549981f7c32fcba429ff6bc57cc4f30c"
|
checksum = "38f9a30cbcbb7011f1da7d73483983bf838af123883e45f2b36ed76328df9c50"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"paste",
|
"paste",
|
||||||
"rustc_version 0.4.1",
|
"rustc_version 0.4.1",
|
||||||
@@ -6847,9 +6784,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specta-macros"
|
name = "specta-macros"
|
||||||
version = "2.0.0-rc.26"
|
version = "2.0.0-rc.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b34b2516e16a9ddd3dc4e73cd6454cfe21fe209f8cb5a6f37346fe3774d759b3"
|
checksum = "2ce14957ecc2897f1f848b8255b6531d13ddf49cbcf506b7c2c9fb1d005593bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -6859,9 +6796,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specta-serde"
|
name = "specta-serde"
|
||||||
version = "0.0.13"
|
version = "0.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4983177ed0eb28235080261953de5f9ebae8a2d107851b5852420bd2ab246245"
|
checksum = "ee8a72b755ddb8949fd8f17c5db43f0e8a806ea587d9bc602ee3f73240c00029"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"specta",
|
"specta",
|
||||||
"specta-macros",
|
"specta-macros",
|
||||||
@@ -6869,18 +6806,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specta-typescript"
|
name = "specta-typescript"
|
||||||
version = "0.0.13"
|
version = "0.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ecbe75dc1d27b36141b50b02b7c73bed00945710cee6edffa86d296a159a6f9"
|
checksum = "639404ee95557f2f8b7e4cb773ffefd45304c7ab8ba21ac83b69051595e083c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"specta",
|
"specta",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "specta-util"
|
name = "specta-util"
|
||||||
version = "0.0.13"
|
version = "0.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9bf531215ea70fba8264edecf98f12600462cf359f2038602a47aeda5ecd5b8"
|
checksum = "29b1fc02b446f7244a92924fe68c0555921209f1d342990cd1539e9138e69502"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"specta",
|
"specta",
|
||||||
]
|
]
|
||||||
@@ -6910,7 +6847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
|
checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"parking_lot 0.12.5",
|
"parking_lot",
|
||||||
"phf_shared 0.13.1",
|
"phf_shared 0.13.1",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
]
|
]
|
||||||
@@ -7046,9 +6983,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.40.1"
|
version = "0.39.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e8a3edbe0394ce115f3917a00349dd242be09eb5a091ed509eaf67b55cfb8a8"
|
checksum = "d2071df9448915b71c4fe6d25deaf1c22f12bd234f01540b77312bb8e41361e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -7157,7 +7094,7 @@ dependencies = [
|
|||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"objc2-ui-kit",
|
"objc2-ui-kit",
|
||||||
"parking_lot 0.12.5",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"tao-macros",
|
"tao-macros",
|
||||||
@@ -7211,9 +7148,9 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "2.12.5"
|
version = "2.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fb0244332cfb9cee7e2a568bf5da29a36ed8fdbd717f6f47a66b6b7b358c072"
|
checksum = "f316751027fc2644221d1a448564d519efb07067fda584879d9cda966391d212"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -7266,9 +7203,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-build"
|
name = "tauri-build"
|
||||||
version = "2.7.4"
|
version = "2.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adddb0e648752aaac5da9c3c3c6a68e1e87cab55e3b757b18a9441ef8c3ac614"
|
checksum = "641dd5fd297c99ab92717b0428cca5b9c6f960b2ac96ca131b3eebc9d70b8ddc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
@@ -7289,16 +7226,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "2.7.4"
|
version = "2.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb37631cf71dab5e8ab55e1bdd701e18a52653d90b78e71d0e5598b1e0a61316"
|
checksum = "a6585c5b536c00f039d12ce70a9755172d5423bbcfd3969863baa70314c3e02f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.23.1",
|
"base64 0.23.1",
|
||||||
"brotli",
|
"brotli",
|
||||||
"ico",
|
"ico",
|
||||||
"json-patch",
|
"json-patch",
|
||||||
"plist",
|
"plist",
|
||||||
"png",
|
"png 0.18.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"semver 1.0.28",
|
"semver 1.0.28",
|
||||||
@@ -7316,9 +7253,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "2.7.4"
|
version = "2.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cc38db58854c10fb5f91a887ed8bf82d3239bb92b5d8db86eda09e96d9963d1"
|
checksum = "e2e83a0cfa1bae376e8fbbdc0b1692707aed50cd6072ce85cae4789af5d6c19f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -7364,7 +7301,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"deelevate",
|
"deelevate",
|
||||||
"libc",
|
"libc",
|
||||||
"parking_lot 0.13.0",
|
"parking_lot",
|
||||||
"serde",
|
"serde",
|
||||||
"specta",
|
"specta",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
@@ -7389,9 +7326,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-deep-link"
|
name = "tauri-plugin-deep-link"
|
||||||
version = "2.6.3"
|
version = "2.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab551d9bec27bb79d1c7fe5ed38c5cfd1cebb86efa745acc65f5853f345f6e56"
|
checksum = "1b3c64e24ebcbc63aaa2d88a9c51e2507084b46620baf39ecb0baa0738a08bb4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
"dunce",
|
||||||
"plist",
|
"plist",
|
||||||
@@ -7410,9 +7347,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-devtools"
|
name = "tauri-plugin-devtools"
|
||||||
version = "2.2.3"
|
version = "2.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "299a62101a16c14b914ebfaf529b4b64ad9ca534a0ece1c21fc9308d1e3ba9db"
|
checksum = "1acb4d1b8490ee79166b72c3f8c989e066650a11aa94dfd0d71fb05c61cdbed0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-stream",
|
"async-stream",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -7437,9 +7374,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-dialog"
|
name = "tauri-plugin-dialog"
|
||||||
version = "2.8.4"
|
version = "2.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce0fb9c2b6d34a9720627ed930ebc8af26f61e648695aecaeb03d5c33c5896f5"
|
checksum = "b7461aaacf1901915ea7b9f5cd74f8224a351ed96af0a62c07fce934003cb34b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
@@ -7543,13 +7480,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-notification"
|
name = "tauri-plugin-notification"
|
||||||
version = "2.8.0"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bc6c194a95a535abdfbe3bc1af9a43935b8b9b29c216b8e71af8b59132703cf"
|
checksum = "b939d7b19c8af1381a72ef8474b3aba2b56c1ddac2c23f0c8e96abbcf86b198b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"notify-rust",
|
"notify-rust",
|
||||||
"rand 0.10.2",
|
"rand 0.9.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
@@ -7595,9 +7532,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-shell"
|
name = "tauri-plugin-shell"
|
||||||
version = "2.6.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7375b25f72f70f6168f27f1ba3a413e30eaa0a2098cff53a4046ebfe9e2f142d"
|
checksum = "8567d42b2c7264355daa1df415ec77f52aa42e885924c86a969be2e920e05521"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -7652,9 +7589,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-wdio-webdriver"
|
name = "tauri-plugin-wdio-webdriver"
|
||||||
version = "1.5.1"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a775b0b59f6f12b38d1f28667311a89cd07f532f540e27d65c6eadfba1156d8"
|
checksum = "4f76676d510d271d80abcf8b0552987b5b4f0eae5e3f906e9b5660d43c97c62e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -7725,9 +7662,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "2.12.3"
|
version = "2.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1aa9d8b7a120f879f44fdc1053f7b7dbf416bf0bbc6a72b714dec46b782b52f"
|
checksum = "8d61892587aea2a85245bcaec98c6fe46268874c0a0deae5535fb71ca7b93eae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@@ -7735,6 +7672,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"softbuffer",
|
"softbuffer",
|
||||||
@@ -7751,12 +7689,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-specta"
|
name = "tauri-specta"
|
||||||
version = "2.0.0-rc.26"
|
version = "2.0.0-rc.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe71fc209fa4c49f959644f1ae2d70f72d5675bcb3d3ad8518122fa7b330994e"
|
checksum = "ee080f36d2ac17ce2f3a82fb53f02d664e8345457de51b56dad3c394dacc41a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"paste",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"specta",
|
"specta",
|
||||||
@@ -7770,15 +7707,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-specta-macros"
|
name = "tauri-specta-macros"
|
||||||
version = "2.0.0-rc.26"
|
version = "2.0.0-rc.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dbf5689a1dbf2611e2351b79ba042ca089d0a3ce45274695e79084cd732a5aec"
|
checksum = "6a59dfdce06c98d8d211619bea5fdb39486d8a8c558e12b2d2ce255972320012"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling 0.24.1",
|
"darling",
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 3.0.5",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7848,10 +7785,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8104,9 +8041,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.54.1"
|
version = "1.53.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3"
|
checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -8462,7 +8399,7 @@ dependencies = [
|
|||||||
"flexi_logger",
|
"flexi_logger",
|
||||||
"log",
|
"log",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"parking_lot 0.12.5",
|
"parking_lot",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
@@ -8514,10 +8451,10 @@ dependencies = [
|
|||||||
"objc2-core-graphics",
|
"objc2-core-graphics",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"png",
|
"png 0.18.1",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8626,7 +8563,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -9072,9 +9009,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "1.0.11"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f5f280bbb2b287bc8e7de7e3852945a0ff50d1bbcb5ed42b6c7a568c546df171"
|
checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
@@ -9168,7 +9105,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -9189,7 +9126,7 @@ dependencies = [
|
|||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -9764,7 +9701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10096,9 +10033,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zip"
|
name = "zip"
|
||||||
version = "9.3.0"
|
version = "9.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eaeb7f16d2605b49aef586996ded29e65642fab7259a3077e537351df6d80426"
|
checksum = "1156b39d142a34b999c2310a50455e0cb3760bf7efad0122f796d813bee26ccb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"bzip2",
|
"bzip2",
|
||||||
@@ -10109,7 +10046,6 @@ dependencies = [
|
|||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"hmac",
|
"hmac",
|
||||||
"indexmap 2.14.0",
|
"indexmap 2.14.0",
|
||||||
"libc",
|
|
||||||
"lzma-rust2",
|
"lzma-rust2",
|
||||||
"memchr",
|
"memchr",
|
||||||
"nix",
|
"nix",
|
||||||
|
|||||||
+4
-4
@@ -61,20 +61,20 @@ tracing-estuary = { git = "https://github.com/Tunglies/tracing-estuary.git", bra
|
|||||||
tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" }
|
tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
|
|
||||||
tauri = { version = "2.12.5" }
|
tauri = { version = "2.12.4" }
|
||||||
tauri-plugin-clipboard-manager = "2.5.0"
|
tauri-plugin-clipboard-manager = "2.5.0"
|
||||||
parking_lot = "0.13.0"
|
parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] }
|
||||||
anyhow = "1.0.104"
|
anyhow = "1.0.104"
|
||||||
chrono = "0.4.45"
|
chrono = "0.4.45"
|
||||||
criterion = { version = "0.8.2", features = ["async_tokio"] }
|
criterion = { version = "0.8.2", features = ["async_tokio"] }
|
||||||
tokio = { version = "1.54.1", features = [
|
tokio = { version = "1.53.3", features = [
|
||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
"macros",
|
"macros",
|
||||||
"time",
|
"time",
|
||||||
"sync",
|
"sync",
|
||||||
] }
|
] }
|
||||||
flexi_logger = "0.31.10"
|
flexi_logger = "0.31.10"
|
||||||
log = "0.4.35"
|
log = "0.4.34"
|
||||||
regex = "1.13.1"
|
regex = "1.13.1"
|
||||||
reqwest = { version = "0.13.5", features = [
|
reqwest = { version = "0.13.5", features = [
|
||||||
"json",
|
"json",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
specta = { version = "=2.0.0-rc.26", features = ["derive", "function"] }
|
specta = { version = "=2.0.0-rc.25", features = ["derive", "function"] }
|
||||||
clash-verge-logging = { workspace = true }
|
clash-verge-logging = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ edition = "2024"
|
|||||||
rust-version = "1.91"
|
rust-version = "1.91"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
specta = { version = "=2.0.0-rc.26", features = ["derive", "function"] }
|
specta = { version = "=2.0.0-rc.25", features = ["derive", "function"] }
|
||||||
tauri = { workspace = true }
|
tauri = { workspace = true }
|
||||||
tauri-plugin-clipboard-manager = { workspace = true }
|
tauri-plugin-clipboard-manager = { workspace = true }
|
||||||
parking_lot = { workspace = true }
|
parking_lot = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
# sysinfo 0.38.2 conflicts with dark-light
|
# sysinfo 0.38.2 conflicts with dark-light
|
||||||
# see https://github.com/GuillaumeGomez/sysinfo/issues/1623
|
# see https://github.com/GuillaumeGomez/sysinfo/issues/1623
|
||||||
sysinfo = { version = "0.40.1", features = ["network", "system"] }
|
sysinfo = { version = "0.39.6", features = ["network", "system"] }
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
libc = "0.2.191"
|
libc = "0.2.191"
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ pub struct SysInfo {
|
|||||||
impl Default for SysInfo {
|
impl Default for SysInfo {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let system_name = System::name().unwrap_or_else(|_| "Null".into());
|
let system_name = System::name().unwrap_or_else(|| "Null".into());
|
||||||
let system_version = System::long_os_version().unwrap_or_else(|_| "Null".into());
|
let system_version = System::long_os_version().unwrap_or_else(|| "Null".into());
|
||||||
let system_kernel_version = System::kernel_version().unwrap_or_else(|_| "Null".into());
|
let system_kernel_version = System::kernel_version().unwrap_or_else(|| "Null".into());
|
||||||
let system_arch = System::cpu_arch();
|
let system_arch = System::cpu_arch();
|
||||||
Self {
|
Self {
|
||||||
system_name,
|
system_name,
|
||||||
@@ -130,14 +130,9 @@ pub fn current_gid() -> u32 {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn list_network_interfaces() -> Vec<String> {
|
pub fn list_network_interfaces() -> Vec<String> {
|
||||||
let Ok(mut networks) = Networks::new() else {
|
let mut networks = Networks::new();
|
||||||
return Vec::new();
|
|
||||||
};
|
|
||||||
networks.refresh(false);
|
networks.refresh(false);
|
||||||
networks
|
networks.keys().map(|name| name.to_owned()).collect()
|
||||||
.keys()
|
|
||||||
.map(|name| name.to_string_lossy().into_owned())
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -256,6 +256,40 @@ export default defineConfig([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['scripts/react/*.{mjs,mts,ts,tsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
globals: { ...globals.browser, ...globals.node },
|
||||||
|
parserOptions: {
|
||||||
|
projectService: false,
|
||||||
|
project: './scripts/react/tsconfig.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import-x/resolver-next': [
|
||||||
|
createTypeScriptImportResolver({
|
||||||
|
project: './scripts/react/tsconfig.json',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['scripts/react/*.{mjs,mts}'],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
projectService: false,
|
||||||
|
project: './scripts/react/tsconfig.node.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['scripts/react/{boundaries,material,scene}.tsx'],
|
||||||
|
// The isolated fixtures use full reloads and preserve aliased Hook names.
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': 'off',
|
||||||
|
'@eslint-react/no-unnecessary-use-prefix': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ['src/**/*.{ts,tsx,js,jsx,mts,mjs}'],
|
files: ['src/**/*.{ts,tsx,js,jsx,mts,mjs}'],
|
||||||
rules: ipcBoundaryRules(),
|
rules: ipcBoundaryRules(),
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://unpkg.com/knip@6/schema.json",
|
"$schema": "https://unpkg.com/knip@6/schema.json",
|
||||||
"entry": ["src/polyfills/*.js!", "scripts/check-contract-changes.mjs!"],
|
"entry": [
|
||||||
|
"src/polyfills/*.js!",
|
||||||
|
"scripts/check-contract-changes.mjs!",
|
||||||
|
"scripts/react/scene.tsx!",
|
||||||
|
"scripts/react/profiler.ts!",
|
||||||
|
"scripts/react/boundaries.tsx!",
|
||||||
|
"scripts/react/material.tsx!",
|
||||||
|
"scripts/react/yaml.ts!",
|
||||||
|
"scripts/react/wdyr.ts!"
|
||||||
|
],
|
||||||
"project": ["src/**/*.{js,jsx,ts,tsx,sass,scss}!", "scripts/**/*.{js,mjs}!"],
|
"project": ["src/**/*.{js,jsx,ts,tsx,sass,scss}!", "scripts/**/*.{js,mjs}!"],
|
||||||
"include": [
|
"include": [
|
||||||
"files",
|
"files",
|
||||||
|
|||||||
+12
-5
@@ -40,7 +40,11 @@
|
|||||||
"perf:build": "node scripts/perf/build.mjs",
|
"perf:build": "node scripts/perf/build.mjs",
|
||||||
"perf:run": "node scripts/perf/run.mjs",
|
"perf:run": "node scripts/perf/run.mjs",
|
||||||
"perf:compare": "node scripts/perf/compare.mjs",
|
"perf:compare": "node scripts/perf/compare.mjs",
|
||||||
"perf:test": "node --test scripts/perf/report.test.mjs"
|
"perf:test": "node --test scripts/perf/report.test.mjs",
|
||||||
|
"dev:profile": "cross-env CVR_REACT_DIAGNOSTICS=profiler node scripts/dev.mjs dev",
|
||||||
|
"react:ab": "node scripts/react/ab.mjs",
|
||||||
|
"dev:wdyr": "cross-env CVR_REACT_DIAGNOSTICS=wdyr node scripts/dev.mjs dev",
|
||||||
|
"audit:react": "node scripts/react/doctor.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/collision": "^0.5.0",
|
"@dnd-kit/collision": "^0.5.0",
|
||||||
@@ -56,7 +60,7 @@
|
|||||||
"@tanstack/react-virtual": "^3.14.13",
|
"@tanstack/react-virtual": "^3.14.13",
|
||||||
"@tauri-apps/api": "2.12.4",
|
"@tauri-apps/api": "2.12.4",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.5.0",
|
"@tauri-apps/plugin-clipboard-manager": "2.5.0",
|
||||||
"@tauri-apps/plugin-dialog": "2.8.4",
|
"@tauri-apps/plugin-dialog": "2.8.3",
|
||||||
"@tauri-apps/plugin-fs": "2.7.1",
|
"@tauri-apps/plugin-fs": "2.7.1",
|
||||||
"@tauri-apps/plugin-http": "2.8.3",
|
"@tauri-apps/plugin-http": "2.8.3",
|
||||||
"@tauri-apps/plugin-opener": "2.7.2",
|
"@tauri-apps/plugin-opener": "2.7.2",
|
||||||
@@ -94,7 +98,7 @@
|
|||||||
"@biomejs/biome": "^2.5.14",
|
"@biomejs/biome": "^2.5.14",
|
||||||
"@eslint-react/eslint-plugin": "^5.20.5",
|
"@eslint-react/eslint-plugin": "^5.20.5",
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@tauri-apps/cli": "2.12.4",
|
"@tauri-apps/cli": "2.12.3",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^26.0.0",
|
"@types/node": "^26.0.0",
|
||||||
"@types/react": "19.3.0",
|
"@types/react": "19.3.0",
|
||||||
@@ -102,7 +106,7 @@
|
|||||||
"@types/validator": "^13.15.10",
|
"@types/validator": "^13.15.10",
|
||||||
"@vitejs/plugin-legacy": "^8.2.3",
|
"@vitejs/plugin-legacy": "^8.2.3",
|
||||||
"@vitejs/plugin-react": "^6.1.1",
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
"@wdio/tauri-service": "1.5.1",
|
"@wdio/tauri-service": "1.5.0",
|
||||||
"adm-zip": "^0.6.1",
|
"adm-zip": "^0.6.1",
|
||||||
"axios": "^1.20.0",
|
"axios": "^1.20.0",
|
||||||
"cli-color": "^2.0.4",
|
"cli-color": "^2.0.4",
|
||||||
@@ -134,7 +138,10 @@
|
|||||||
"vite-plugin-svgr": "^5.2.0",
|
"vite-plugin-svgr": "^5.2.0",
|
||||||
"vitest": "^5.0.1",
|
"vitest": "^5.0.1",
|
||||||
"webdriverio": "10.1.0",
|
"webdriverio": "10.1.0",
|
||||||
"ws": "8.22.1"
|
"ws": "8.22.1",
|
||||||
|
"playwright": "1.64.1",
|
||||||
|
"@welldone-software/why-did-you-render": "10.0.1",
|
||||||
|
"react-doctor": "0.9.21"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{ts,tsx,js,mjs}": [
|
"*.{ts,tsx,js,mjs}": [
|
||||||
|
|||||||
Generated
+1104
-166
File diff suppressed because it is too large
Load Diff
@@ -113,27 +113,6 @@
|
|||||||
"ghcr.io/devcontainers/features/rust"
|
"ghcr.io/devcontainers/features/rust"
|
||||||
],
|
],
|
||||||
"groupName": "Rust toolchain"
|
"groupName": "Rust toolchain"
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Update the Specta contract toolchain together",
|
|
||||||
"matchManagers": ["cargo"],
|
|
||||||
"matchPackageNames": ["specta", "tauri-specta", "specta-typescript"],
|
|
||||||
"groupName": "specta",
|
|
||||||
"groupSlug": "specta",
|
|
||||||
"prCreation": "immediate",
|
|
||||||
"automerge": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Keep Specta aligned with the supported tauri-specta release",
|
|
||||||
"matchManagers": ["cargo"],
|
|
||||||
"matchPackageNames": ["specta", "tauri-specta"],
|
|
||||||
"allowedVersions": "/^2\\.0\\.0-rc\\.26$/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Keep the TypeScript exporter compatible with Specta rc.26",
|
|
||||||
"matchManagers": ["cargo"],
|
|
||||||
"matchPackageNames": ["specta-typescript"],
|
|
||||||
"allowedVersions": "/^0\\.0\\.13$/"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"customManagers": [
|
"customManagers": [
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# React diagnostics
|
||||||
|
|
||||||
|
`pnpm dev:profile` runs the usual development launcher with a root React
|
||||||
|
Profiler. In WebView DevTools, `window.__CVR_REACT_PROFILER__.read()` returns
|
||||||
|
copies of the latest 1,000 standard Profiler callback records; `.clear()` drops
|
||||||
|
them. Records contain timing and commit metadata, never business props. Normal
|
||||||
|
development and production builds do not load the collector.
|
||||||
|
|
||||||
|
`pnpm dev:wdyr` instead initializes why-did-you-render before loading the app
|
||||||
|
and uses its development JSX runtime. It reports avoidable renders for
|
||||||
|
`ProxyItem`, `ProxyItemMini` and `ProxyTunCard` in the console. The modes are
|
||||||
|
mutually exclusive; `CVR_REACT_DIAGNOSTICS` accepts only `profiler` or `wdyr` on
|
||||||
|
the development server. Each mode uses its own Vite cache. Production builds
|
||||||
|
ignore this variable and include neither diagnostic entry nor runtime.
|
||||||
|
|
||||||
|
`pnpm audit:react` scans supported source files under `src`. Pass file paths to
|
||||||
|
limit the scan, for example `pnpm audit:react src/hooks/use-proxy-delay-state.ts`;
|
||||||
|
add `--json` for the original structured report. Diagnostics are advisory.
|
||||||
|
Execution errors and incomplete scans fail the command. Telemetry, remote scores
|
||||||
|
and supply-chain scanning are disabled; the command does not fix code, erase
|
||||||
|
historical diagnostics or run in CI.
|
||||||
|
|
||||||
|
Install the browser explicitly with `pnpm exec playwright install chromium`.
|
||||||
|
Then run `pnpm react:ab --base <ref> --head <ref>`. Both Git trees run against
|
||||||
|
one installed dependency set and the same fixed DNS, delay-hook and proxy-tab
|
||||||
|
fixtures. The command never installs a browser or changes either checkout.
|
||||||
|
It retains source hashes, dependency identity, browser/environment information,
|
||||||
|
behavior assertions, render observations and profiles under `/tmp/cvr-react-ab-*`.
|
||||||
|
Each version and mode has separate Vite caches and output. Three pairs alternate
|
||||||
|
order in ordinary development, Strict Mode and production. A behavior failure
|
||||||
|
returns a nonzero exit status. DNS stale serialization and same-value renders
|
||||||
|
are observations so a known baseline can be compared with its fix. Append
|
||||||
|
`--assert dns` to require the head version to keep the latest serialized YAML in sync with
|
||||||
|
continuous field edits; this is the focused DNS regression assertion.
|
||||||
|
`--assert delay` requires same-value delay updates to retain their reference and memoized consumer,
|
||||||
|
while each changed field (including clearing elapsed time) propagates.
|
||||||
|
`--assert tabs` requires zero tab renders during unrelated parent updates. Use
|
||||||
|
`--assert dns --assert delay --assert tabs` for a cumulative candidate.
|
||||||
|
|
||||||
|
The fixtures execute the actual selected components and hook. IPC, data,
|
||||||
|
editor and UI rendering boundaries are replaced, and outgoing network requests
|
||||||
|
are rejected. DNS serialization is observed at `js-yaml.dump`; tab execution is
|
||||||
|
observed at the Material Paper boundary. These are component results, not native
|
||||||
|
Tauri integration, real DNS/proxy/TUN writes, or whole-application CPU/RSS gains.
|
||||||
|
Production React does not emit Profiler callbacks. Timing is diagnostic and has
|
||||||
|
no hard acceptance threshold; measure native release CPU/RSS separately and
|
||||||
|
calibrate A/A before claiming a performance gain. Keep raw reports out of Git.
|
||||||
@@ -0,0 +1,596 @@
|
|||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { spawnSync } from 'node:child_process'
|
||||||
|
import { createHash } from 'node:crypto'
|
||||||
|
import {
|
||||||
|
cp,
|
||||||
|
mkdir,
|
||||||
|
mkdtemp,
|
||||||
|
readFile,
|
||||||
|
readdir,
|
||||||
|
realpath,
|
||||||
|
symlink,
|
||||||
|
writeFile,
|
||||||
|
} from 'node:fs/promises'
|
||||||
|
import os from 'node:os'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { parseArgs } from 'node:util'
|
||||||
|
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import { chromium } from 'playwright'
|
||||||
|
import { build, createServer, preview } from 'vite'
|
||||||
|
|
||||||
|
const { values } = parseArgs({
|
||||||
|
options: {
|
||||||
|
base: { type: 'string' },
|
||||||
|
head: { type: 'string' },
|
||||||
|
assert: { type: 'string', multiple: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (!values.base || !values.head)
|
||||||
|
throw new Error('Usage: pnpm react:ab --base <ref> --head <ref>')
|
||||||
|
const assertions = new Set(values.assert ?? [])
|
||||||
|
for (const name of assertions) {
|
||||||
|
if (!['dns', 'delay', 'tabs'].includes(name))
|
||||||
|
throw new Error(`Unknown regression assertion: ${name}`)
|
||||||
|
}
|
||||||
|
const harness = path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
const root = path.resolve(harness, '../..')
|
||||||
|
const output = await mkdtemp('/tmp/cvr-react-ab-')
|
||||||
|
const dependencies = path.join(root, 'node_modules')
|
||||||
|
const frozenHarness = path.join(output, 'harness')
|
||||||
|
await cp(harness, frozenHarness, {
|
||||||
|
recursive: true,
|
||||||
|
filter: (file) => !path.basename(file).startsWith('tsconfig'),
|
||||||
|
})
|
||||||
|
const files = [
|
||||||
|
'src/components/setting/mods/dns-viewer.tsx',
|
||||||
|
'src/hooks/use-proxy-delay-state.ts',
|
||||||
|
'src/components/home/proxy-tun-card.tsx',
|
||||||
|
]
|
||||||
|
const hash = (content) => createHash('sha256').update(content).digest('hex')
|
||||||
|
function git(...args) {
|
||||||
|
const result = spawnSync('git', args, {
|
||||||
|
cwd: root,
|
||||||
|
maxBuffer: 128 * 1024 * 1024,
|
||||||
|
})
|
||||||
|
if (result.status !== 0) throw new Error(result.stderr.toString())
|
||||||
|
return result.stdout
|
||||||
|
}
|
||||||
|
const manifest = {
|
||||||
|
assertions: [...assertions],
|
||||||
|
environment: {
|
||||||
|
platform: process.platform,
|
||||||
|
architecture: process.arch,
|
||||||
|
node: process.version,
|
||||||
|
os: os.release(),
|
||||||
|
lock: hash(await readFile(path.join(root, 'pnpm-lock.yaml'))),
|
||||||
|
},
|
||||||
|
harness: Object.fromEntries(
|
||||||
|
await Promise.all(
|
||||||
|
(await readdir(frozenHarness)).map(async (file) => [
|
||||||
|
file,
|
||||||
|
hash(await readFile(path.join(frozenHarness, file))),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
installedLock: hash(
|
||||||
|
await readFile(path.join(dependencies, '.pnpm/lock.yaml')),
|
||||||
|
),
|
||||||
|
sources: {},
|
||||||
|
runs: [],
|
||||||
|
}
|
||||||
|
let browser
|
||||||
|
try {
|
||||||
|
// Playwright intentionally fails here if its explicitly installed browser is missing.
|
||||||
|
browser = await chromium.launch({ headless: true })
|
||||||
|
manifest.environment.browser = browser.version()
|
||||||
|
for (const [variant, ref] of Object.entries({
|
||||||
|
base: values.base,
|
||||||
|
head: values.head,
|
||||||
|
})) {
|
||||||
|
const tree = git('rev-parse', '--verify', `${ref}^{tree}`).toString().trim()
|
||||||
|
const source = path.join(output, variant)
|
||||||
|
await mkdir(source)
|
||||||
|
const archive = git('archive', tree, 'src')
|
||||||
|
const extracted = spawnSync('tar', ['-x', '-C', source], { input: archive })
|
||||||
|
if (extracted.status !== 0) throw new Error(extracted.stderr.toString())
|
||||||
|
await cp(frozenHarness, path.join(source, 'fixture'), { recursive: true })
|
||||||
|
await symlink(dependencies, path.join(source, 'node_modules'), 'dir')
|
||||||
|
manifest.sources[variant] = {
|
||||||
|
ref,
|
||||||
|
tree,
|
||||||
|
files: Object.fromEntries(
|
||||||
|
await Promise.all(
|
||||||
|
files.map(async (file) => [
|
||||||
|
file,
|
||||||
|
hash(await readFile(path.join(source, file))),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const mode of ['development', 'strict', 'production']) {
|
||||||
|
const servers = {}
|
||||||
|
try {
|
||||||
|
for (const variant of ['base', 'head']) {
|
||||||
|
const source = path.join(output, variant)
|
||||||
|
const fixture = path.join(source, 'fixture')
|
||||||
|
const boundary = path.join(fixture, 'boundaries.tsx')
|
||||||
|
const aliases = [
|
||||||
|
'@/hooks/use-clash',
|
||||||
|
'@/hooks/use-verge',
|
||||||
|
'@/hooks/use-profiles',
|
||||||
|
'@/hooks/use-system-state',
|
||||||
|
'@/hooks/use-system-proxy-state',
|
||||||
|
'@/services/states',
|
||||||
|
'@/services/cmds',
|
||||||
|
'@/services/mutate',
|
||||||
|
'@/services/notice-service',
|
||||||
|
'@/components/base',
|
||||||
|
'@/components/shared/proxy-control-switches',
|
||||||
|
'react-i18next',
|
||||||
|
].map((find) => ({ find, replacement: boundary }))
|
||||||
|
const config = {
|
||||||
|
configFile: false,
|
||||||
|
root: fixture,
|
||||||
|
cacheDir: path.join(output, 'cache', variant, mode),
|
||||||
|
plugins: [react()],
|
||||||
|
resolve: {
|
||||||
|
alias: [
|
||||||
|
...aliases,
|
||||||
|
{
|
||||||
|
find: '@/services/delay',
|
||||||
|
replacement: path.join(fixture, 'delay.ts'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: /^@mui\/material$/,
|
||||||
|
replacement: path.join(fixture, 'material.tsx'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: 'fixture-material',
|
||||||
|
replacement: path.join(dependencies, '@mui/material/index.mjs'),
|
||||||
|
},
|
||||||
|
{ find: 'js-yaml', replacement: path.join(fixture, 'yaml.ts') },
|
||||||
|
{
|
||||||
|
find: 'fixture-yaml',
|
||||||
|
replacement: path.join(
|
||||||
|
dependencies,
|
||||||
|
'js-yaml/dist/js-yaml.mjs',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ find: '@', replacement: path.join(source, 'src') },
|
||||||
|
{
|
||||||
|
find: /^react(?=\/|$)/,
|
||||||
|
replacement: path.join(dependencies, 'react'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: /^react-dom(?=\/|$)/,
|
||||||
|
replacement: path.join(dependencies, 'react-dom'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dedupe: ['react', 'react-dom'],
|
||||||
|
},
|
||||||
|
define: { OS_PLATFORM: JSON.stringify(process.platform) },
|
||||||
|
server: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 0,
|
||||||
|
hmr: false,
|
||||||
|
fs: {
|
||||||
|
allow: [
|
||||||
|
output,
|
||||||
|
await realpath(output),
|
||||||
|
await realpath(dependencies),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: path.join(output, 'dist', variant, mode),
|
||||||
|
emptyOutDir: true,
|
||||||
|
},
|
||||||
|
preview: { host: '127.0.0.1', port: 0 },
|
||||||
|
}
|
||||||
|
if (mode === 'production') {
|
||||||
|
await build(config)
|
||||||
|
servers[variant] = await preview(config)
|
||||||
|
} else {
|
||||||
|
servers[variant] = await createServer(config)
|
||||||
|
await servers[variant].listen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const [pair, order] of [
|
||||||
|
['base', 'head'],
|
||||||
|
['head', 'base'],
|
||||||
|
['base', 'head'],
|
||||||
|
].entries()) {
|
||||||
|
for (const variant of order) {
|
||||||
|
const label = `${mode}-${pair + 1}-${variant}`
|
||||||
|
const context = await browser.newContext()
|
||||||
|
const errors = []
|
||||||
|
const address = servers[variant].httpServer.address()
|
||||||
|
const origin = `http://127.0.0.1:${address.port}`
|
||||||
|
await context.route('**/*', (route) => {
|
||||||
|
if (new URL(route.request().url()).origin === origin)
|
||||||
|
return route.continue()
|
||||||
|
errors.push(`Unexpected network: ${route.request().url()}`)
|
||||||
|
return route.abort()
|
||||||
|
})
|
||||||
|
const page = await context.newPage()
|
||||||
|
page.on('pageerror', (error) => errors.push(String(error)))
|
||||||
|
const result = { label, variant, mode, pair: pair + 1, errors }
|
||||||
|
try {
|
||||||
|
await page.goto(`${origin}/${mode === 'strict' ? '?strict' : ''}`)
|
||||||
|
await page.waitForSelector('#delay', { timeout: 60000 })
|
||||||
|
await page.waitForFunction(
|
||||||
|
() => window.__REACT_AB__.read().listeners.length === 1,
|
||||||
|
)
|
||||||
|
result.tabs = await tabs(page)
|
||||||
|
if (variant === 'head' && assertions.has('tabs')) {
|
||||||
|
assert.equal(
|
||||||
|
result.tabs.unrelated,
|
||||||
|
0,
|
||||||
|
'Unrelated parent updates must not rerender the memoized tabs',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
result.dns = await dns(page)
|
||||||
|
if (variant === 'head' && assertions.has('dns')) {
|
||||||
|
for (const edit of result.dns.edits) {
|
||||||
|
assert.equal(
|
||||||
|
edit.serialized.at(-1),
|
||||||
|
edit.value,
|
||||||
|
'Latest DNS serialization must match the edited field',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.delay = await delay(page)
|
||||||
|
if (variant === 'head' && assertions.has('delay')) {
|
||||||
|
for (const [index, observation] of result.delay.entries()) {
|
||||||
|
assert.equal(
|
||||||
|
observation.sameReference,
|
||||||
|
index === 1,
|
||||||
|
'Preserve the reference only when all three delay fields match',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
assert.equal(
|
||||||
|
result.delay[1].childRenders,
|
||||||
|
result.delay[0].childRenders,
|
||||||
|
'Equal delay state must not rerender the memoized consumer',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
result.profile = await page.evaluate(() => {
|
||||||
|
const before = window.__CVR_REACT_PROFILER__.read()
|
||||||
|
window.__CVR_REACT_PROFILER__.clear()
|
||||||
|
return { before, after: window.__CVR_REACT_PROFILER__.read() }
|
||||||
|
})
|
||||||
|
assert.equal(result.profile.after.length, 0)
|
||||||
|
result.collector = await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.checkCollector(),
|
||||||
|
)
|
||||||
|
assert.deepEqual(result.collector, {
|
||||||
|
length: 1000,
|
||||||
|
first: '5',
|
||||||
|
last: '1004',
|
||||||
|
copied: true,
|
||||||
|
cleared: true,
|
||||||
|
})
|
||||||
|
if (mode !== 'production')
|
||||||
|
assert(
|
||||||
|
result.profile.before.length > 0 &&
|
||||||
|
result.profile.before.length <= 1000,
|
||||||
|
)
|
||||||
|
assert.deepEqual(errors, [])
|
||||||
|
assert.deepEqual(
|
||||||
|
await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.fixture.notices.filter(
|
||||||
|
(notice) => notice.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
result.ok = true
|
||||||
|
} catch (error) {
|
||||||
|
result.snapshot = await page
|
||||||
|
.evaluate(() => window.__REACT_AB__?.read())
|
||||||
|
.catch(() => null)
|
||||||
|
result.ok = false
|
||||||
|
result.error = String(error)
|
||||||
|
throw error
|
||||||
|
} finally {
|
||||||
|
manifest.runs.push(result)
|
||||||
|
await writeFile(
|
||||||
|
path.join(output, `${label}.json`),
|
||||||
|
JSON.stringify(result, null, 2),
|
||||||
|
)
|
||||||
|
await context.close()
|
||||||
|
console.log(`${label}: ${result.ok ? 'pass' : 'FAIL'}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
for (const server of Object.values(servers)) {
|
||||||
|
if (server.close) await server.close()
|
||||||
|
else
|
||||||
|
await new Promise((resolve, reject) =>
|
||||||
|
server.httpServer.close((error) =>
|
||||||
|
error ? reject(error) : resolve(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await browser?.close()
|
||||||
|
await writeFile(
|
||||||
|
path.join(output, 'report.json'),
|
||||||
|
JSON.stringify(manifest, null, 2),
|
||||||
|
)
|
||||||
|
console.log(`Evidence: ${output}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function settle(page) {
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
}
|
||||||
|
async function tabs(page) {
|
||||||
|
const buttons = page.locator('#tabs .MuiPaper-root')
|
||||||
|
const readTabs = () =>
|
||||||
|
page.evaluate(() =>
|
||||||
|
Object.fromEntries(
|
||||||
|
window.__REACT_AB__.fixture.tabRenders.map((tab) => [
|
||||||
|
tab.label.split('.').at(-1),
|
||||||
|
tab,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(await buttons.count(), 2)
|
||||||
|
assert.equal((await readTabs()).systemProxy.active, true)
|
||||||
|
assert.equal((await readTabs()).tunMode.active, false)
|
||||||
|
const before = await page.evaluate(
|
||||||
|
() => window.__REACT_AB__.fixture.tabRenders.length,
|
||||||
|
)
|
||||||
|
for (let index = 0; index < 5; index++) {
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update())
|
||||||
|
await settle(page)
|
||||||
|
}
|
||||||
|
const unrelated =
|
||||||
|
(await page.evaluate(() => window.__REACT_AB__.fixture.tabRenders.length)) -
|
||||||
|
before
|
||||||
|
await buttons.nth(1).click()
|
||||||
|
await settle(page)
|
||||||
|
assert.equal((await readTabs()).systemProxy.active, false)
|
||||||
|
assert.equal((await readTabs()).tunMode.active, true)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() =>
|
||||||
|
localStorage.getItem('clash-verge-proxy-active-tab'),
|
||||||
|
),
|
||||||
|
'tun',
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
(await page.locator('#fixture-controls').textContent()).endsWith(
|
||||||
|
'toggles.tunMode',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ mounted: false }))
|
||||||
|
await settle(page)
|
||||||
|
assert(
|
||||||
|
(await page.locator('#fixture-controls').textContent()).endsWith(
|
||||||
|
'toggles.tunMode',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ mounted: true }))
|
||||||
|
await settle(page)
|
||||||
|
assert.equal((await readTabs()).tunMode.active, true)
|
||||||
|
assert.equal((await readTabs()).systemProxy.active, false)
|
||||||
|
await buttons.nth(0).click()
|
||||||
|
await settle(page)
|
||||||
|
assert.equal((await readTabs()).systemProxy.active, true)
|
||||||
|
assert.equal((await readTabs()).tunMode.active, false)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() =>
|
||||||
|
localStorage.getItem('clash-verge-proxy-active-tab'),
|
||||||
|
),
|
||||||
|
'system',
|
||||||
|
)
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.__REACT_AB__.fixture.indicator = true
|
||||||
|
window.__REACT_AB__.fixture.verge.enable_tun_mode = true
|
||||||
|
window.__REACT_AB__.update()
|
||||||
|
})
|
||||||
|
await settle(page)
|
||||||
|
assert(Object.values(await readTabs()).every((tab) => tab.indicator))
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.__REACT_AB__.fixture.language = 'zh'
|
||||||
|
window.__REACT_AB__.update()
|
||||||
|
})
|
||||||
|
await settle(page)
|
||||||
|
const updated = Object.values(await readTabs())
|
||||||
|
assert(updated.every((tab) => tab.label.startsWith('zh:')))
|
||||||
|
assert(
|
||||||
|
(await page.locator('#tabs').textContent()).includes(
|
||||||
|
'zh:home.components.proxyTun.status.systemProxyEnabled',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
const beforeColor = await buttons
|
||||||
|
.nth(0)
|
||||||
|
.evaluate((element) => getComputedStyle(element).backgroundColor)
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.__REACT_AB__.fixture.theme = 'dark'
|
||||||
|
window.__REACT_AB__.update()
|
||||||
|
})
|
||||||
|
await settle(page)
|
||||||
|
const color = await buttons
|
||||||
|
.nth(0)
|
||||||
|
.evaluate((element) => getComputedStyle(element).backgroundColor)
|
||||||
|
assert.notEqual(color, beforeColor)
|
||||||
|
return { unrelated, updated, beforeColor, color }
|
||||||
|
}
|
||||||
|
async function dns(page) {
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.open())
|
||||||
|
const listen = page.locator('#dns input[placeholder=":53"]')
|
||||||
|
await page.waitForFunction(
|
||||||
|
() =>
|
||||||
|
document.querySelector('#dns input[placeholder=":53"]')?.value ===
|
||||||
|
':5353',
|
||||||
|
)
|
||||||
|
const edits = []
|
||||||
|
for (const value of [':54', ':55', ':56']) {
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.__REACT_AB__.fixture.serialized.length = 0
|
||||||
|
})
|
||||||
|
await listen.fill(value)
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(await listen.inputValue(), value)
|
||||||
|
edits.push({
|
||||||
|
value,
|
||||||
|
serialized: await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.fixture.serialized.map(
|
||||||
|
(config) => config.dns.listen,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.__REACT_AB__.fixture.serialized.length = 0
|
||||||
|
})
|
||||||
|
await listen.fill(':')
|
||||||
|
await listen.pressSequentially('567', { delay: 0 })
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(await listen.inputValue(), ':567')
|
||||||
|
edits.push({
|
||||||
|
value: ':567',
|
||||||
|
rapid: true,
|
||||||
|
serialized: await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.fixture.serialized.map((config) => config.dns.listen),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
await page.locator('#save-dns').click()
|
||||||
|
await page.waitForFunction(
|
||||||
|
() => window.__REACT_AB__.fixture.saved.length === 1,
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.fixture.saved[0].dns.listen),
|
||||||
|
':567',
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.open())
|
||||||
|
await page.waitForSelector('#dns')
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: /shared.actions.resetToDefault$/ })
|
||||||
|
.click()
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(await listen.inputValue(), ':53')
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: /shared.editorModes.advanced$/ })
|
||||||
|
.click()
|
||||||
|
await settle(page)
|
||||||
|
const editor = page.locator('#fixture-monaco')
|
||||||
|
assert.match(await editor.inputValue(), /listen: ["']?:53/)
|
||||||
|
await editor.fill(
|
||||||
|
'dns:\n enable: true\n listen: ":8053"\nhosts:\n example.test: 127.0.0.1\n',
|
||||||
|
)
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: /shared.editorModes.visualization$/ })
|
||||||
|
.click()
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(await listen.inputValue(), ':8053')
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: /shared.editorModes.advanced$/ })
|
||||||
|
.click()
|
||||||
|
await settle(page)
|
||||||
|
await page.locator('#save-dns').click()
|
||||||
|
await page.waitForFunction(
|
||||||
|
() => window.__REACT_AB__.fixture.saved.length === 2,
|
||||||
|
)
|
||||||
|
const saved = await page.evaluate(() => window.__REACT_AB__.fixture.saved)
|
||||||
|
assert.equal(saved[1].dns.listen, ':8053')
|
||||||
|
assert.equal(saved[1].hosts['example.test'], '127.0.0.1')
|
||||||
|
return { edits, saved }
|
||||||
|
}
|
||||||
|
async function delay(page) {
|
||||||
|
const updates = [
|
||||||
|
{ delay: 10, elapsed: 12, updatedAt: 100 },
|
||||||
|
{ delay: 10, elapsed: 12, updatedAt: 100 },
|
||||||
|
{ delay: 11, elapsed: 12, updatedAt: 100 },
|
||||||
|
{ delay: 11, elapsed: 13, updatedAt: 100 },
|
||||||
|
{ delay: 11, elapsed: 13, updatedAt: 101 },
|
||||||
|
{ delay: 11, updatedAt: 101 },
|
||||||
|
{ delay: -1, updatedAt: 102 },
|
||||||
|
{ delay: 0, updatedAt: 103 },
|
||||||
|
{ delay: 1000000, elapsed: 20, updatedAt: 104 },
|
||||||
|
]
|
||||||
|
const observations = []
|
||||||
|
for (const update of updates) {
|
||||||
|
await page.evaluate((value) => {
|
||||||
|
window.__REACT_AB__.remember()
|
||||||
|
window.__REACT_AB__.delay.emit('Node 1', 'Group 1', value)
|
||||||
|
}, update)
|
||||||
|
await settle(page)
|
||||||
|
const result = await page.evaluate(() => window.__REACT_AB__.read())
|
||||||
|
assert.deepEqual(result.delay, update)
|
||||||
|
observations.push({
|
||||||
|
update,
|
||||||
|
sameReference: result.sameReference,
|
||||||
|
childRenders: result.childRenders,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.request())
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().delay.delay),
|
||||||
|
-2,
|
||||||
|
)
|
||||||
|
await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.delay.finish({ delay: 0, updatedAt: 200 }),
|
||||||
|
)
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().delay.delay),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.request())
|
||||||
|
await settle(page)
|
||||||
|
assert.equal(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().delay.delay),
|
||||||
|
-2,
|
||||||
|
)
|
||||||
|
await page.evaluate(() =>
|
||||||
|
window.__REACT_AB__.delay.finish({
|
||||||
|
delay: 1000000,
|
||||||
|
elapsed: 20,
|
||||||
|
updatedAt: 201,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
await settle(page)
|
||||||
|
assert.deepEqual(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().delay),
|
||||||
|
{ delay: 1000000, elapsed: 20, updatedAt: 201 },
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ name: 'Node 2' }))
|
||||||
|
await settle(page)
|
||||||
|
let state = await page.evaluate(() => window.__REACT_AB__.read())
|
||||||
|
assert.deepEqual(state.listeners, ['Group 1:Node 2'])
|
||||||
|
assert.deepEqual(state.delay, { delay: -1, updatedAt: 0 })
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ group: 'Group 2' }))
|
||||||
|
await settle(page)
|
||||||
|
state = await page.evaluate(() => window.__REACT_AB__.read())
|
||||||
|
assert.deepEqual(state.listeners, ['Group 2:Node 2'])
|
||||||
|
for (const name of ['DIRECT', 'Unknown']) {
|
||||||
|
await page.evaluate((name) => window.__REACT_AB__.update({ name }), name)
|
||||||
|
await settle(page)
|
||||||
|
const preset = await page.evaluate(() => window.__REACT_AB__.read())
|
||||||
|
assert.deepEqual(preset.listeners, [])
|
||||||
|
assert.deepEqual(preset.delay, { delay: -1, updatedAt: 0 })
|
||||||
|
}
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ name: 'Node 2' }))
|
||||||
|
await settle(page)
|
||||||
|
assert.deepEqual(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().listeners),
|
||||||
|
['Group 2:Node 2'],
|
||||||
|
)
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.update({ mounted: false }))
|
||||||
|
await settle(page)
|
||||||
|
assert.deepEqual(
|
||||||
|
await page.evaluate(() => window.__REACT_AB__.read().listeners),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
return observations
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { Switch as MuiSwitch } from '@mui/material'
|
||||||
|
|
||||||
|
import { fixture } from './state'
|
||||||
|
|
||||||
|
const translations = {
|
||||||
|
en: (key: string) => `en:${key}`,
|
||||||
|
zh: (key: string) => `zh:${key}`,
|
||||||
|
}
|
||||||
|
export const useTranslation = () => ({
|
||||||
|
t: translations[fixture.language as 'en' | 'zh'],
|
||||||
|
})
|
||||||
|
export const useVerge = () => ({ verge: fixture.verge })
|
||||||
|
export const useProfiles = () => ({ current: { uid: 'fixture' } })
|
||||||
|
export const useClash = () => ({
|
||||||
|
mutateClash: () => {
|
||||||
|
throw new Error('Unexpected mutateClash')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export const useSystemState = () => ({ isTunModeAvailable: fixture.available })
|
||||||
|
export const useSystemProxyState = () => ({ indicator: fixture.indicator })
|
||||||
|
export const useThemeMode = () => fixture.theme
|
||||||
|
export const getDnsConfigContent = async () => {
|
||||||
|
fixture.commands.push('getDnsConfigContent')
|
||||||
|
return fixture.initialDns
|
||||||
|
}
|
||||||
|
export const saveDnsConfig = async (config: any) => {
|
||||||
|
fixture.commands.push('saveDnsConfig')
|
||||||
|
fixture.saved.push(structuredClone(config))
|
||||||
|
}
|
||||||
|
export const validateDnsConfig = async () => {
|
||||||
|
fixture.commands.push('validateDnsConfig')
|
||||||
|
return { status: 'valid' }
|
||||||
|
}
|
||||||
|
export const applyDnsConfig = () => {
|
||||||
|
throw new Error('Unexpected applyDnsConfig')
|
||||||
|
}
|
||||||
|
export const mutate = (fn: () => unknown) => fn()
|
||||||
|
export const showNotice = {
|
||||||
|
error: (...args: any[]) => fixture.notices.push({ error: args }),
|
||||||
|
success: (...args: any[]) => fixture.notices.push({ success: args }),
|
||||||
|
}
|
||||||
|
export const Switch = MuiSwitch
|
||||||
|
export function BaseDialog({ open, title, children, onClose, onOk }: any) {
|
||||||
|
return open ? (
|
||||||
|
<section id="dns">
|
||||||
|
{title}
|
||||||
|
<button id="close-dns" onClick={onClose}>
|
||||||
|
close
|
||||||
|
</button>
|
||||||
|
<button id="save-dns" onClick={onOk}>
|
||||||
|
save
|
||||||
|
</button>
|
||||||
|
{children}
|
||||||
|
</section>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
export function MonacoEditor({ value, onChange }: any) {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
id="fixture-monaco"
|
||||||
|
value={value}
|
||||||
|
onChange={(event) => onChange(event.target.value)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default function ProxyControlSwitches({ label }: any) {
|
||||||
|
return <output id="fixture-controls">{label}</output>
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
type Update = { delay: number; elapsed?: number; updatedAt: number }
|
||||||
|
const listeners = new Map<string, (update: Update) => void>()
|
||||||
|
const cache = new Map<string, Update>()
|
||||||
|
let finish: ((update: Update) => void) | undefined
|
||||||
|
const key = (name: string, group: string) => `${group}:${name}`
|
||||||
|
export const delayFixture = {
|
||||||
|
listeners,
|
||||||
|
emit(name: string, group: string, update: Update) {
|
||||||
|
cache.set(key(name, group), update)
|
||||||
|
listeners.get(key(name, group))?.(update)
|
||||||
|
},
|
||||||
|
finish(update: Update) {
|
||||||
|
if (!finish) throw new Error('No pending delay request')
|
||||||
|
finish(update)
|
||||||
|
finish = undefined
|
||||||
|
},
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
setListener(name: string, group: string, listener: (update: Update) => void) {
|
||||||
|
listeners.set(key(name, group), listener)
|
||||||
|
},
|
||||||
|
removeListener(name: string, group: string) {
|
||||||
|
listeners.delete(key(name, group))
|
||||||
|
},
|
||||||
|
getDelayUpdate(name: string, group: string) {
|
||||||
|
return cache.get(key(name, group))
|
||||||
|
},
|
||||||
|
getDelayFix() {
|
||||||
|
return -1
|
||||||
|
},
|
||||||
|
checkDelay() {
|
||||||
|
return new Promise<Update>((resolve) => {
|
||||||
|
finish = resolve
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { spawnSync } from 'node:child_process'
|
||||||
|
import { statSync } from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { parseArgs } from 'node:util'
|
||||||
|
|
||||||
|
import { globSync } from 'glob'
|
||||||
|
|
||||||
|
const { values, positionals } = parseArgs({
|
||||||
|
options: { json: { type: 'boolean' } },
|
||||||
|
allowPositionals: true,
|
||||||
|
})
|
||||||
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
|
||||||
|
const files = positionals.length
|
||||||
|
? positionals
|
||||||
|
: globSync('src/**/*.{js,jsx,ts,tsx,mjs,cjs,mts,cts,html}', {
|
||||||
|
cwd: root,
|
||||||
|
nodir: true,
|
||||||
|
}).sort()
|
||||||
|
if (files.length === 0) throw new Error('No source files found')
|
||||||
|
for (const file of files) {
|
||||||
|
if (
|
||||||
|
!/\.(?:[jt]sx?|[cm][jt]s|html)$/.test(file) ||
|
||||||
|
!statSync(path.resolve(root, file)).isFile()
|
||||||
|
)
|
||||||
|
throw new Error(`Expected a source file: ${file}`)
|
||||||
|
}
|
||||||
|
const executable = fileURLToPath(
|
||||||
|
new URL('../bin/react-doctor.js', import.meta.resolve('react-doctor')),
|
||||||
|
)
|
||||||
|
const result = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
executable,
|
||||||
|
...files,
|
||||||
|
'--json',
|
||||||
|
'--no-telemetry',
|
||||||
|
'--no-supply-chain',
|
||||||
|
'--blocking',
|
||||||
|
'none',
|
||||||
|
'--yes',
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cwd: root,
|
||||||
|
encoding: 'utf8',
|
||||||
|
stdio: ['ignore', 'pipe', 'inherit'],
|
||||||
|
maxBuffer: 64 * 1024 * 1024,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (result.error) throw result.error
|
||||||
|
if (result.signal)
|
||||||
|
throw new Error(`React Doctor terminated by ${result.signal}`)
|
||||||
|
const report = JSON.parse(result.stdout)
|
||||||
|
if (values.json) {
|
||||||
|
process.stdout.write(result.stdout)
|
||||||
|
} else {
|
||||||
|
for (const diagnostic of report.diagnostics) {
|
||||||
|
console.log(
|
||||||
|
`${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column} ${diagnostic.severity} ${diagnostic.plugin}/${diagnostic.rule}\n ${diagnostic.message}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
`${report.summary.totalDiagnosticCount} advisory diagnostics across ${report.projects.reduce((count, project) => count + project.analyzedFileCount, 0)} analyzed files`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// In 0.9.21, --blocking none also masks linter execution failures.
|
||||||
|
const incomplete = report.projects.filter((project) => !project.complete)
|
||||||
|
if (report.error) console.error(report.error.message)
|
||||||
|
for (const project of incomplete) {
|
||||||
|
console.error(
|
||||||
|
'Incomplete React Doctor scan:',
|
||||||
|
project.directory,
|
||||||
|
project.skippedCheckReasons,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
process.exitCode =
|
||||||
|
result.status || (!report.ok || incomplete.length > 0 ? 1 : 0)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head><meta charset="UTF-8" /><title>React component A/B</title></head>
|
||||||
|
<body><div id="root"></div><script type="module" src="./scene.tsx"></script></body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { Paper as MuiPaper } from 'fixture-material'
|
||||||
|
export * from 'fixture-material'
|
||||||
|
|
||||||
|
import { fixture } from './state'
|
||||||
|
|
||||||
|
export function Paper(props: any) {
|
||||||
|
const { onClick, elevation, children, sx } = props
|
||||||
|
if (onClick && sx?.maxWidth === 160) {
|
||||||
|
fixture.tabRenders.push({
|
||||||
|
active: elevation === 2,
|
||||||
|
indicator: Boolean(children[2]),
|
||||||
|
label: children[1].props.children,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return <MuiPaper {...props} />
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import type { ProfilerOnRenderCallback } from 'react'
|
||||||
|
|
||||||
|
export type ProfileRecord = Parameters<ProfilerOnRenderCallback>
|
||||||
|
|
||||||
|
const records: ProfileRecord[] = []
|
||||||
|
|
||||||
|
export const recordRender: ProfilerOnRenderCallback = (...record) => {
|
||||||
|
if (records.length === 1000) records.shift()
|
||||||
|
records.push(record)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const profiler = {
|
||||||
|
read: () => records.map((record) => [...record]),
|
||||||
|
clear: () => {
|
||||||
|
records.length = 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(window, { __CVR_REACT_PROFILER__: profiler })
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { ThemeProvider, createTheme } from '@mui/material'
|
||||||
|
import {
|
||||||
|
Profiler,
|
||||||
|
StrictMode,
|
||||||
|
memo,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
|
||||||
|
import { ProxyTunCard } from '@/components/home/proxy-tun-card'
|
||||||
|
import { DnsViewer } from '@/components/setting/mods/dns-viewer'
|
||||||
|
import { useProxyDelayState } from '@/hooks/use-proxy-delay-state'
|
||||||
|
|
||||||
|
import { delayFixture } from './delay'
|
||||||
|
import { profiler, recordRender } from './profiler'
|
||||||
|
import { fixture } from './state'
|
||||||
|
|
||||||
|
const member = (name: string): any =>
|
||||||
|
name === 'Unknown'
|
||||||
|
? {
|
||||||
|
kind: 'unresolved',
|
||||||
|
ref: { kind: 'unresolved', name, reason: 'missing' },
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
kind: 'node',
|
||||||
|
ref: { kind: 'node', recordId: name, name },
|
||||||
|
node: { name, history: [], source: { kind: 'core', proxyName: name } },
|
||||||
|
}
|
||||||
|
let update: (patch?: any) => void
|
||||||
|
let open: () => void
|
||||||
|
let delay: ReturnType<typeof useProxyDelayState>
|
||||||
|
let previous: unknown
|
||||||
|
let childRenders = 0
|
||||||
|
const DelayValue = memo(({ state }: any) => {
|
||||||
|
childRenders++
|
||||||
|
return <output id="delay">{JSON.stringify(state)}</output>
|
||||||
|
})
|
||||||
|
function DelayProbe({ name, group }: any) {
|
||||||
|
const resolved = useMemo(() => member(name), [name])
|
||||||
|
const current = useProxyDelayState(resolved, group)
|
||||||
|
useEffect(() => {
|
||||||
|
delay = current
|
||||||
|
})
|
||||||
|
return <DelayValue state={current.delayState} />
|
||||||
|
}
|
||||||
|
function Scene() {
|
||||||
|
const [state, setState] = useState({
|
||||||
|
revision: 0,
|
||||||
|
name: 'Node 1',
|
||||||
|
group: 'Group 1',
|
||||||
|
mounted: true,
|
||||||
|
})
|
||||||
|
const ref = useRef<any>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
update = (patch = {}) =>
|
||||||
|
setState((old) => ({ ...old, ...patch, revision: old.revision + 1 }))
|
||||||
|
open = () => ref.current.open()
|
||||||
|
}, [])
|
||||||
|
const mode = fixture.theme
|
||||||
|
const theme = useMemo(() => createTheme({ palette: { mode } }), [mode])
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
<main data-revision={state.revision}>
|
||||||
|
<section id="tabs" key={state.mounted ? 'mounted' : 'reset'}>
|
||||||
|
<ProxyTunCard />
|
||||||
|
</section>
|
||||||
|
<DnsViewer ref={ref} />
|
||||||
|
{state.mounted && <DelayProbe name={state.name} group={state.group} />}
|
||||||
|
</main>
|
||||||
|
</ThemeProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const strict = new URLSearchParams(location.search).has('strict')
|
||||||
|
const app = (
|
||||||
|
<Profiler id="fixtures" onRender={recordRender}>
|
||||||
|
<Scene />
|
||||||
|
</Profiler>
|
||||||
|
)
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
strict ? <StrictMode>{app}</StrictMode> : app,
|
||||||
|
)
|
||||||
|
Object.assign(window, {
|
||||||
|
__REACT_AB__: {
|
||||||
|
update: (patch?: any) => update(patch),
|
||||||
|
open: () => open(),
|
||||||
|
fixture,
|
||||||
|
delay: delayFixture,
|
||||||
|
request: () => {
|
||||||
|
void delay.onDelay()
|
||||||
|
},
|
||||||
|
remember: () => {
|
||||||
|
previous = delay.delayState
|
||||||
|
},
|
||||||
|
checkCollector: () => {
|
||||||
|
profiler.clear()
|
||||||
|
for (let index = 0; index < 1005; index++)
|
||||||
|
recordRender(String(index), 'update', 1, 2, 3, 4)
|
||||||
|
const records = profiler.read()
|
||||||
|
records[0][0] = 'changed copy'
|
||||||
|
const preserved = profiler.read()
|
||||||
|
const result = {
|
||||||
|
length: preserved.length,
|
||||||
|
first: preserved[0][0],
|
||||||
|
last: preserved.at(-1)![0],
|
||||||
|
copied: preserved[0][0] === '5',
|
||||||
|
cleared: false,
|
||||||
|
}
|
||||||
|
profiler.clear()
|
||||||
|
result.cleared = profiler.read().length === 0
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
read: () => ({
|
||||||
|
fixture,
|
||||||
|
profile: profiler.read(),
|
||||||
|
childRenders,
|
||||||
|
sameReference: previous === delay.delayState,
|
||||||
|
delay: delay.delayState,
|
||||||
|
listeners: [...delayFixture.listeners.keys()],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
export const fixture = {
|
||||||
|
language: 'en',
|
||||||
|
theme: 'light' as 'light' | 'dark',
|
||||||
|
verge: { enable_tun_mode: false },
|
||||||
|
indicator: false,
|
||||||
|
available: true,
|
||||||
|
initialDns: 'dns:\n enable: true\n listen: ":5353"\n',
|
||||||
|
saved: [] as any[],
|
||||||
|
serialized: [] as any[],
|
||||||
|
tabRenders: [] as any[],
|
||||||
|
notices: [] as any[],
|
||||||
|
commands: [] as string[],
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["../../src/*"],
|
||||||
|
"@root/*": ["../../*"],
|
||||||
|
"fixture-material": ["../../node_modules/@mui/material"],
|
||||||
|
"fixture-yaml": ["../../node_modules/js-yaml"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["./*.ts", "./*.tsx", "../../src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["./*.mjs", "./*.mts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
|
import { normalizePath, type Plugin } from 'vite'
|
||||||
|
|
||||||
|
export function reactDiagnostics(mode: string | undefined): Plugin[] {
|
||||||
|
if (!mode) return []
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'react-diagnostics',
|
||||||
|
enforce: 'pre',
|
||||||
|
apply: 'serve',
|
||||||
|
config() {
|
||||||
|
if (mode !== 'profiler' && mode !== 'wdyr')
|
||||||
|
throw new Error(`Unknown CVR_REACT_DIAGNOSTICS mode: ${mode}`)
|
||||||
|
return {
|
||||||
|
cacheDir: path.resolve('node_modules/.vite', mode),
|
||||||
|
...(mode === 'wdyr'
|
||||||
|
? {
|
||||||
|
oxc: {
|
||||||
|
jsx: {
|
||||||
|
importSource: '@welldone-software/why-did-you-render',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
include: [
|
||||||
|
'@welldone-software/why-did-you-render',
|
||||||
|
'@welldone-software/why-did-you-render/jsx-dev-runtime',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transformIndexHtml(html) {
|
||||||
|
if (mode !== 'wdyr') return html
|
||||||
|
const entry = 'src="./main.tsx"'
|
||||||
|
if (!html.includes(entry))
|
||||||
|
throw new Error('WDYR entry no longer matches index.html')
|
||||||
|
return html.replace(
|
||||||
|
entry,
|
||||||
|
`src="/@fs/${normalizePath(path.resolve('scripts/react/wdyr.ts'))}"`,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
transform(code, id) {
|
||||||
|
if (mode !== 'profiler') return
|
||||||
|
if (id !== normalizePath(path.resolve('src/main.tsx'))) return
|
||||||
|
const open = '<React.StrictMode>'
|
||||||
|
const close = '</React.StrictMode>'
|
||||||
|
if (!code.includes(open) || !code.includes(close)) {
|
||||||
|
throw new Error('React profiling entry no longer matches main.tsx')
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: `import { Profiler } from 'react'\nimport { recordRender } from '../scripts/react/profiler'\n${code}`
|
||||||
|
.replace(open, `<Profiler id="app" onRender={recordRender}>${open}`)
|
||||||
|
.replace(close, `${close}</Profiler>`),
|
||||||
|
map: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import whyDidYouRender from '@welldone-software/why-did-you-render'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
whyDidYouRender(React, {
|
||||||
|
include: [/^(ProxyItem|ProxyItemMini|ProxyTunCard)$/],
|
||||||
|
trackAllPureComponents: false,
|
||||||
|
trackHooks: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await import('../../src/main')
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import * as yaml from 'fixture-yaml'
|
||||||
|
export * from 'fixture-yaml'
|
||||||
|
|
||||||
|
import { fixture } from './state'
|
||||||
|
|
||||||
|
export function dump(value: any, options: any) {
|
||||||
|
fixture.serialized.push(structuredClone(value))
|
||||||
|
return yaml.dump(value, options)
|
||||||
|
}
|
||||||
+15
-15
@@ -29,7 +29,7 @@ perf-harness = ["dep:tauri-plugin-wdio-webdriver"]
|
|||||||
identifier = "io.github.clash-verge-rev.clash-verge-rev"
|
identifier = "io.github.clash-verge-rev.clash-verge-rev"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.7.4", features = [] }
|
tauri-build = { version = "2.7.3", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clash-verge-draft = { workspace = true }
|
clash-verge-draft = { workspace = true }
|
||||||
@@ -58,8 +58,8 @@ smartstring = { workspace = true, features = ["serde"] }
|
|||||||
bitflags = { workspace = true }
|
bitflags = { workspace = true }
|
||||||
socket2 = { workspace = true }
|
socket2 = { workspace = true }
|
||||||
warp = { version = "0.4.3", features = ["server"] }
|
warp = { version = "0.4.3", features = ["server"] }
|
||||||
open = "5.4.5"
|
open = "5.4.4"
|
||||||
rfd = { version = "0.17.2", default-features = false, features = ["common-controls-v6"] }
|
rfd = { version = "0.16.0", default-features = false, features = ["common-controls-v6"] }
|
||||||
dirs = "7.0.0"
|
dirs = "7.0.0"
|
||||||
dunce = "1.0.5"
|
dunce = "1.0.5"
|
||||||
nanoid = "0.5"
|
nanoid = "0.5"
|
||||||
@@ -72,14 +72,14 @@ sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs.git", branch
|
|||||||
"guard",
|
"guard",
|
||||||
] }
|
] }
|
||||||
network-interface = { version = "2.0.5", features = ["serde"] }
|
network-interface = { version = "2.0.5", features = ["serde"] }
|
||||||
tauri-plugin-shell = "2.6.0"
|
tauri-plugin-shell = "2.5.0"
|
||||||
tauri-plugin-opener = "2.7.2"
|
tauri-plugin-opener = "2.7.2"
|
||||||
tauri-plugin-dialog = "2.8.4"
|
tauri-plugin-dialog = "2.8.3"
|
||||||
tauri-plugin-fs = "2.7.1"
|
tauri-plugin-fs = "2.7.1"
|
||||||
tauri-plugin-process = "2.4.0"
|
tauri-plugin-process = "2.4.0"
|
||||||
tauri-plugin-deep-link = "2.6.3"
|
tauri-plugin-deep-link = "2.6.2"
|
||||||
tauri-plugin-window-state = "2.5.0"
|
tauri-plugin-window-state = "2.5.0"
|
||||||
zip = "9.2.2"
|
zip = "9.1.3"
|
||||||
flate2 = "1.1.10"
|
flate2 = "1.1.10"
|
||||||
reqwest_dav = "0.3.3"
|
reqwest_dav = "0.3.3"
|
||||||
aes-gcm = { version = "0.11.1" }
|
aes-gcm = { version = "0.11.1" }
|
||||||
@@ -89,27 +89,27 @@ getrandom = "0.4.3"
|
|||||||
futures = "0.3.34"
|
futures = "0.3.34"
|
||||||
gethostname = "1.1.0"
|
gethostname = "1.1.0"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
tauri-plugin-notification = "2.8.0"
|
tauri-plugin-notification = "2.7.0"
|
||||||
tokio-stream = "0.1.19"
|
tokio-stream = "0.1.19"
|
||||||
backon = { version = "1.6.0", features = ["tokio-sleep"] }
|
backon = { version = "1.6.0", features = ["tokio-sleep"] }
|
||||||
tauri-plugin-http = "2.8.3"
|
tauri-plugin-http = "2.8.3"
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tauri-plugin-devtools = { version = "2.2.3", optional = true }
|
tauri-plugin-devtools = { version = "2.2.2", optional = true }
|
||||||
tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", rev = "7a03d16f4d39b1bb885b7babe66b9e153e34b615" }
|
tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", rev = "7a03d16f4d39b1bb885b7babe66b9e153e34b615" }
|
||||||
async-trait = "0.1.92"
|
async-trait = "0.1.92"
|
||||||
clash_verge_service_ipc = { git = "https://github.com/clash-verge-rev/clash-verge-service-ipc.git", tag = "v2.7.7", version = "2.7.7", features = [
|
clash_verge_service_ipc = { git = "https://github.com/clash-verge-rev/clash-verge-service-ipc.git", tag = "v2.7.7", version = "2.7.7", features = [
|
||||||
"client",
|
"client",
|
||||||
] }
|
] }
|
||||||
arc-swap = "1.9.3"
|
arc-swap = "1.9.2"
|
||||||
tokio-rustls = "0.26.6"
|
tokio-rustls = "0.26.6"
|
||||||
rustls = { version = "0.23.46", features = ["ring"] }
|
rustls = { version = "0.23.46", features = ["ring"] }
|
||||||
webpki-roots = "1.0.11"
|
webpki-roots = "1.0.9"
|
||||||
dark-light = "3.0.0"
|
dark-light = "3.0.0"
|
||||||
bytes = "1.12.1"
|
bytes = "1.12.1"
|
||||||
tokio-util = { version = "0.7.20", features = ["time"] }
|
tokio-util = { version = "0.7.20", features = ["time"] }
|
||||||
specta = { version = "=2.0.0-rc.26", features = ["derive", "function", "serde_json"] }
|
specta = { version = "=2.0.0-rc.25", features = ["derive", "function", "serde_json"] }
|
||||||
tauri-specta = { version = "=2.0.0-rc.26", features = ["derive", "typescript"] }
|
tauri-specta = { version = "=2.0.0-rc.25", features = ["derive", "typescript"] }
|
||||||
specta-typescript = "=0.0.13"
|
specta-typescript = "=0.0.12"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2.191"
|
libc = "0.2.191"
|
||||||
@@ -119,7 +119,7 @@ libc = "0.2.191"
|
|||||||
clash-verge-signal = { workspace = true }
|
clash-verge-signal = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
tauri-plugin-wdio-webdriver = { version = "=1.5.1", optional = true }
|
tauri-plugin-wdio-webdriver = { version = "=1.5.0", optional = true }
|
||||||
objc2 = "0.6.5"
|
objc2 = "0.6.5"
|
||||||
objc2-foundation = { version = "0.3.2", features = [
|
objc2-foundation = { version = "0.3.2", features = [
|
||||||
"NSString",
|
"NSString",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
Fade,
|
Fade,
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import { useState, useMemo, useCallback, memo, FC } from 'react'
|
import { useState, useMemo, memo, FC } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import ProxyControlSwitches from '@/components/shared/proxy-control-switches'
|
import ProxyControlSwitches from '@/components/shared/proxy-control-switches'
|
||||||
@@ -152,15 +152,10 @@ export const ProxyTunCard: FC = () => {
|
|||||||
showNotice.error(err)
|
showNotice.error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSystemTabClick = useCallback(() => {
|
const handleTabChange = (tab: string) => {
|
||||||
setActiveTab('system')
|
setActiveTab(tab)
|
||||||
localStorage.setItem(LOCAL_STORAGE_TAB_KEY, 'system')
|
localStorage.setItem(LOCAL_STORAGE_TAB_KEY, tab)
|
||||||
}, [])
|
}
|
||||||
|
|
||||||
const handleTunTabClick = useCallback(() => {
|
|
||||||
setActiveTab('tun')
|
|
||||||
localStorage.setItem(LOCAL_STORAGE_TAB_KEY, 'tun')
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const tabDescription = useMemo(() => {
|
const tabDescription = useMemo(() => {
|
||||||
if (activeTab === 'system') {
|
if (activeTab === 'system') {
|
||||||
@@ -196,14 +191,14 @@ export const ProxyTunCard: FC = () => {
|
|||||||
>
|
>
|
||||||
<TabButton
|
<TabButton
|
||||||
isActive={activeTab === 'system'}
|
isActive={activeTab === 'system'}
|
||||||
onClick={handleSystemTabClick}
|
onClick={() => handleTabChange('system')}
|
||||||
icon={ComputerRounded}
|
icon={ComputerRounded}
|
||||||
label={t('settings.sections.system.toggles.systemProxy')}
|
label={t('settings.sections.system.toggles.systemProxy')}
|
||||||
hasIndicator={systemProxyIndicator}
|
hasIndicator={systemProxyIndicator}
|
||||||
/>
|
/>
|
||||||
<TabButton
|
<TabButton
|
||||||
isActive={activeTab === 'tun'}
|
isActive={activeTab === 'tun'}
|
||||||
onClick={handleTunTabClick}
|
onClick={() => handleTabChange('tun')}
|
||||||
icon={TroubleshootRounded}
|
icon={TroubleshootRounded}
|
||||||
label={t('settings.sections.system.toggles.tunMode')}
|
label={t('settings.sections.system.toggles.tunMode')}
|
||||||
hasIndicator={enable_tun_mode! && isTunModeAvailable}
|
hasIndicator={enable_tun_mode! && isTunModeAvailable}
|
||||||
|
|||||||
@@ -183,7 +183,6 @@ function useProxyRenderState(
|
|||||||
renderList,
|
renderList,
|
||||||
onProxies,
|
onProxies,
|
||||||
onHeadState,
|
onHeadState,
|
||||||
setHeadState: setListHeadState,
|
|
||||||
handleCheckAll,
|
handleCheckAll,
|
||||||
saveScrollPosition,
|
saveScrollPosition,
|
||||||
getScrollPosition,
|
getScrollPosition,
|
||||||
@@ -378,17 +377,12 @@ function NormalProxyGroups(props: { mode: string }) {
|
|||||||
renderList,
|
renderList,
|
||||||
onProxies,
|
onProxies,
|
||||||
onHeadState,
|
onHeadState,
|
||||||
setHeadState,
|
|
||||||
handleCheckAll,
|
handleCheckAll,
|
||||||
getScrollPosition,
|
getScrollPosition,
|
||||||
saveScrollPosition,
|
saveScrollPosition,
|
||||||
} = useProxyRenderState(mode, false, null)
|
} = useProxyRenderState(mode, false, null)
|
||||||
const emptyList = useEmptyRenderList()
|
const emptyList = useEmptyRenderList()
|
||||||
const { onDragEnd: onHeaderDragEnd } = useProxyGroupHeaderLayout()
|
const { onDragEnd: onHeaderDragEnd } = useProxyGroupHeaderLayout()
|
||||||
const { proxyView } = useProxiesData()
|
|
||||||
const globalGroupName = proxyView?.global?.name
|
|
||||||
// The revealed group sits below GLOBAL's rows, so a click must bring it into view.
|
|
||||||
const pendingRevealRef = useRef<string | null>(null)
|
|
||||||
const renderFirstRef = useRef(true)
|
const renderFirstRef = useRef(true)
|
||||||
// Do not persist intermediate positions produced while restoring virtual scroll.
|
// Do not persist intermediate positions produced while restoring virtual scroll.
|
||||||
const isRestoringRef = useRef(false)
|
const isRestoringRef = useRef(false)
|
||||||
@@ -483,17 +477,9 @@ function NormalProxyGroups(props: { mode: string }) {
|
|||||||
if (!['Selector', 'URLTest', 'Fallback'].includes(group.type)) return
|
if (!['Selector', 'URLTest', 'Fallback'].includes(group.type)) return
|
||||||
if (!isInteractableMember(member)) return
|
if (!isInteractableMember(member)) return
|
||||||
|
|
||||||
if (group.name === globalGroupName) {
|
|
||||||
pendingRevealRef.current =
|
|
||||||
member.kind === 'group' ? member.ref.name : null
|
|
||||||
// The selection refetches the view, so skip onHeadState's refetch.
|
|
||||||
if (member.kind === 'group') {
|
|
||||||
setHeadState(member.ref.name, { open: true })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
select(group.name, member.ref.name, group.now!, group.fixed!)
|
select(group.name, member.ref.name, group.now!, group.fixed!)
|
||||||
},
|
},
|
||||||
[globalGroupName, select, setHeadState],
|
[select],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleLocation = useStableCallback((group: ProxyGroupView) => {
|
const handleLocation = useStableCallback((group: ProxyGroupView) => {
|
||||||
@@ -539,17 +525,6 @@ function NormalProxyGroups(props: { mode: string }) {
|
|||||||
return Array.from(new Set(names))
|
return Array.from(new Set(names))
|
||||||
}, [renderList])
|
}, [renderList])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (mode !== 'global') {
|
|
||||||
pendingRevealRef.current = null
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const groupName = pendingRevealRef.current
|
|
||||||
if (!groupName || !proxyGroupNames.includes(groupName)) return
|
|
||||||
pendingRevealRef.current = null
|
|
||||||
handleGroupLocationByName(groupName)
|
|
||||||
}, [handleGroupLocationByName, mode, proxyGroupNames])
|
|
||||||
|
|
||||||
const handleGroupToggle = useCallback(
|
const handleGroupToggle = useCallback(
|
||||||
async (group: ProxyGroupView) => {
|
async (group: ProxyGroupView) => {
|
||||||
const index = renderList.findIndex(
|
const index = renderList.findIndex(
|
||||||
@@ -633,7 +608,7 @@ function NormalProxyGroups(props: { mode: string }) {
|
|||||||
/>
|
/>
|
||||||
</DragDropProvider>
|
</DragDropProvider>
|
||||||
|
|
||||||
{mode === 'rule' && (
|
{(mode === 'rule' || mode === 'global') && (
|
||||||
<ProxyGroupNavigator
|
<ProxyGroupNavigator
|
||||||
proxyGroupNames={proxyGroupNames}
|
proxyGroupNames={proxyGroupNames}
|
||||||
onGroupLocation={handleGroupLocationByName}
|
onGroupLocation={handleGroupLocationByName}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { useVerge } from '@/hooks/use-verge'
|
|||||||
import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
|
import { useAppRefreshers, useProxiesData } from '@/providers/app-data-context'
|
||||||
import delayManager, { type DelaySnapshot } from '@/services/delay'
|
import delayManager, { type DelaySnapshot } from '@/services/delay'
|
||||||
import {
|
import {
|
||||||
findCurrentGroupMember,
|
|
||||||
isInteractableMember,
|
isInteractableMember,
|
||||||
resolveMember,
|
resolveMember,
|
||||||
selectGlobalChainNodes,
|
selectGlobalChainNodes,
|
||||||
@@ -79,18 +78,6 @@ const resolveOccurrences = (view: ProxyViewV1, group: ProxyGroupView) =>
|
|||||||
member: resolveMember(view, member),
|
member: resolveMember(view, member),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// mihomo selects DIRECT in GLOBAL by default, so the selected built-in stays visible.
|
|
||||||
const HIDDEN_GLOBAL_BUILTINS = new Set(['DIRECT', 'REJECT'])
|
|
||||||
|
|
||||||
const isHiddenGlobalBuiltin = (
|
|
||||||
group: ProxyGroupView,
|
|
||||||
{ member }: ResolvedMemberOccurrence,
|
|
||||||
) =>
|
|
||||||
member.kind === 'node' &&
|
|
||||||
member.node.source.kind === 'core' &&
|
|
||||||
HIDDEN_GLOBAL_BUILTINS.has(member.node.source.proxyName) &&
|
|
||||||
member.ref.name !== group.now
|
|
||||||
|
|
||||||
const memberKey = (
|
const memberKey = (
|
||||||
group: ProxyGroupView,
|
group: ProxyGroupView,
|
||||||
occurrence: ResolvedMemberOccurrence,
|
occurrence: ResolvedMemberOccurrence,
|
||||||
@@ -222,10 +209,8 @@ export const useRenderList = (
|
|||||||
const renderGroups = useMemo(() => {
|
const renderGroups = useMemo(() => {
|
||||||
if (!proxyView) return []
|
if (!proxyView) return []
|
||||||
if (mode === 'rule') return proxyView.groups
|
if (mode === 'rule') return proxyView.groups
|
||||||
const { global } = proxyView
|
const global = proxyView.global ? [proxyView.global] : []
|
||||||
if (!global) return []
|
return mode === 'global' ? [...global, ...proxyView.groups] : global
|
||||||
const current = findCurrentGroupMember(proxyView, global)?.member
|
|
||||||
return current?.kind === 'group' ? [global, current.group] : [global]
|
|
||||||
}, [mode, proxyView])
|
}, [mode, proxyView])
|
||||||
|
|
||||||
// Every group this list draws, so a test settling in any of them re-sorts that group.
|
// Every group this list draws, so a test settling in any of them re-sorts that group.
|
||||||
@@ -275,10 +260,10 @@ export const useRenderList = (
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useRule = mode === 'rule' || mode === 'global'
|
||||||
const cache = groupCacheRef.current
|
const cache = groupCacheRef.current
|
||||||
|
|
||||||
const retList = renderGroups.flatMap((group) => {
|
const retList = renderGroups.flatMap((group) => {
|
||||||
const isFlat = group === proxyView.global
|
|
||||||
const headState = headStates[group.name] || DEFAULT_STATE
|
const headState = headStates[group.name] || DEFAULT_STATE
|
||||||
const cached = cache.get(group.name)
|
const cached = cache.get(group.name)
|
||||||
if (
|
if (
|
||||||
@@ -294,24 +279,19 @@ export const useRenderList = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ret: IRenderItem[] = [
|
const ret: IRenderItem[] = [
|
||||||
isFlat
|
{
|
||||||
? { type: 1, key: `head-${group.name}`, group, headState }
|
type: 0,
|
||||||
: {
|
key: group.name,
|
||||||
type: 0,
|
group,
|
||||||
key: group.name,
|
headState,
|
||||||
group,
|
icon: group.icon!,
|
||||||
headState,
|
testUrl: group.testUrl!,
|
||||||
icon: group.icon!,
|
},
|
||||||
testUrl: group.testUrl!,
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if (headState.open || isFlat) {
|
if (headState.open || !useRule) {
|
||||||
const resolved = resolveOccurrences(proxyView, group)
|
|
||||||
const occurrences = filterSort(
|
const occurrences = filterSort(
|
||||||
isFlat
|
resolveOccurrences(proxyView, group),
|
||||||
? resolved.filter((item) => !isHiddenGlobalBuiltin(group, item))
|
|
||||||
: resolved,
|
|
||||||
group.name,
|
group.name,
|
||||||
headState.filterText,
|
headState.filterText,
|
||||||
headState.sortType,
|
headState.sortType,
|
||||||
@@ -322,6 +302,9 @@ export const useRenderList = (
|
|||||||
useRegularExpression: headState.filterUseRegularExpression,
|
useRegularExpression: headState.filterUseRegularExpression,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
if (!useRule) {
|
||||||
|
ret.push({ type: 1, key: `head-${group.name}`, group, headState })
|
||||||
|
}
|
||||||
if (occurrences.length === 0) {
|
if (occurrences.length === 0) {
|
||||||
ret.push({ type: 3, key: `empty-${group.name}`, group, headState })
|
ret.push({ type: 3, key: `empty-${group.name}`, group, headState })
|
||||||
} else if (col > 1) {
|
} else if (col > 1) {
|
||||||
@@ -360,8 +343,9 @@ export const useRenderList = (
|
|||||||
return ret
|
return ret
|
||||||
})
|
})
|
||||||
|
|
||||||
const filtered =
|
const filtered = !useRule
|
||||||
mode === 'rule' ? retList.filter((item) => !item.group.hidden) : retList
|
? retList.slice(1)
|
||||||
|
: retList.filter((item) => !item.group.hidden)
|
||||||
if (
|
if (
|
||||||
prevListRef.current.length === filtered.length &&
|
prevListRef.current.length === filtered.length &&
|
||||||
filtered.every((item, index) => item === prevListRef.current[index])
|
filtered.every((item, index) => item === prevListRef.current[index])
|
||||||
|
|||||||
@@ -586,10 +586,20 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
|||||||
? event.target.checked
|
? event.target.checked
|
||||||
: event.target.value
|
: event.target.value
|
||||||
|
|
||||||
setValues((prev) => ({
|
setValues((prev) => {
|
||||||
...prev,
|
const newValues = {
|
||||||
[field]: value,
|
...prev,
|
||||||
}))
|
[field]: value,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visualization) {
|
||||||
|
setTimeout(() => {
|
||||||
|
updateYamlFromValues()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValues
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ import { useTranslation } from 'react-i18next'
|
|||||||
|
|
||||||
import { BaseDialog } from '@/components/base'
|
import { BaseDialog } from '@/components/base'
|
||||||
import { useVerge } from '@/hooks/use-verge'
|
import { useVerge } from '@/hooks/use-verge'
|
||||||
import type {
|
|
||||||
IVergeTestItem_Deserialize,
|
|
||||||
IVergeTestItem_Serialize,
|
|
||||||
} from '@/services/bindings'
|
|
||||||
import { showNotice } from '@/services/notice-service'
|
import { showNotice } from '@/services/notice-service'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -31,7 +27,7 @@ export const TestViewer = forwardRef<TestViewerRef, Props>(
|
|||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const { verge, patchVerge } = useVerge()
|
const { verge, patchVerge } = useVerge()
|
||||||
const testList = verge?.test_list ?? []
|
const testList = verge?.test_list ?? []
|
||||||
const { control, ...formIns } = useForm<IVergeTestItem_Deserialize>({
|
const { control, ...formIns } = useForm<IVergeTestItem>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: '',
|
name: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
@@ -41,16 +37,11 @@ export const TestViewer = forwardRef<TestViewerRef, Props>(
|
|||||||
|
|
||||||
const patchTestList = async (
|
const patchTestList = async (
|
||||||
uid: string,
|
uid: string,
|
||||||
patch: Partial<IVergeTestItem_Deserialize>,
|
patch: Partial<IVergeTestItem>,
|
||||||
) => {
|
) => {
|
||||||
const newList = testList.map((x) => {
|
const newList = testList.map((x) => {
|
||||||
if (x.uid === uid) {
|
if (x.uid === uid) {
|
||||||
return {
|
return { ...x, ...patch }
|
||||||
uid: x.uid,
|
|
||||||
name: patch.name === undefined ? x.name : patch.name,
|
|
||||||
icon: patch.icon === undefined ? x.icon : patch.icon,
|
|
||||||
url: patch.url === undefined ? x.url : patch.url,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
})
|
})
|
||||||
@@ -86,12 +77,7 @@ export const TestViewer = forwardRef<TestViewerRef, Props>(
|
|||||||
|
|
||||||
if (openType === 'new') {
|
if (openType === 'new') {
|
||||||
const uid = nanoid()
|
const uid = nanoid()
|
||||||
const item: IVergeTestItem_Serialize = {
|
const item = { ...form, uid }
|
||||||
uid,
|
|
||||||
name: form.name ?? null,
|
|
||||||
icon: form.icon ?? null,
|
|
||||||
url: form.url ?? null,
|
|
||||||
}
|
|
||||||
const newList = [...testList, item]
|
const newList = [...testList, item]
|
||||||
await patchVerge({ test_list: newList })
|
await patchVerge({ test_list: newList })
|
||||||
onChange(uid)
|
onChange(uid)
|
||||||
|
|||||||
@@ -17,12 +17,7 @@ const PRESET_PROXY_NAMES = [
|
|||||||
'COMPATIBLE',
|
'COMPATIBLE',
|
||||||
]
|
]
|
||||||
|
|
||||||
const identity = (previous: DelayUpdate, next: DelayUpdate): DelayUpdate =>
|
const identity = (_: DelayUpdate, next: DelayUpdate): DelayUpdate => next
|
||||||
previous.delay === next.delay &&
|
|
||||||
previous.elapsed === next.elapsed &&
|
|
||||||
previous.updatedAt === next.updatedAt
|
|
||||||
? previous
|
|
||||||
: next
|
|
||||||
|
|
||||||
const INITIAL_DELAY: DelayUpdate = { delay: -1, updatedAt: 0 }
|
const INITIAL_DELAY: DelayUpdate = { delay: -1, updatedAt: 0 }
|
||||||
|
|
||||||
|
|||||||
+149
-255
@@ -23,10 +23,7 @@ export const commands = {
|
|||||||
__TAURI_INVOKE<string[]>('get_network_interfaces'),
|
__TAURI_INVOKE<string[]>('get_network_interfaces'),
|
||||||
getSystemHostname: () => __TAURI_INVOKE<string>('get_system_hostname'),
|
getSystemHostname: () => __TAURI_INVOKE<string>('get_system_hostname'),
|
||||||
restartApp: () => __TAURI_INVOKE<null>('restart_app'),
|
restartApp: () => __TAURI_INVOKE<null>('restart_app'),
|
||||||
installUpdate: (
|
installUpdate: (version: string, onEvent: Channel<DownloadEvent>) =>
|
||||||
version: string,
|
|
||||||
onEvent: Channel<DownloadEvent_Deserialize>,
|
|
||||||
) =>
|
|
||||||
__TAURI_INVOKE<InstallUpdateOutcome>('install_update', {
|
__TAURI_INVOKE<InstallUpdateOutcome>('install_update', {
|
||||||
version,
|
version,
|
||||||
onEvent,
|
onEvent,
|
||||||
@@ -37,12 +34,11 @@ export const commands = {
|
|||||||
upgradeClashCore: (force: boolean) =>
|
upgradeClashCore: (force: boolean) =>
|
||||||
__TAURI_INVOKE<CoreUpgradeReport>('upgrade_clash_core', { force }),
|
__TAURI_INVOKE<CoreUpgradeReport>('upgrade_clash_core', { force }),
|
||||||
/** Returns one coherent core/service snapshot instead of independently refreshed state. */
|
/** Returns one coherent core/service snapshot instead of independently refreshed state. */
|
||||||
getRuntimeState: () =>
|
getRuntimeState: () => __TAURI_INVOKE<RunStateView>('get_runtime_state'),
|
||||||
__TAURI_INVOKE<RunStateView_Serialize>('get_runtime_state'),
|
|
||||||
getPendingFailures: () =>
|
getPendingFailures: () =>
|
||||||
__TAURI_INVOKE<PendingFailure[]>('get_pending_failures'),
|
__TAURI_INVOKE<PendingFailure[]>('get_pending_failures'),
|
||||||
getSidecarFailure: () =>
|
getSidecarFailure: () =>
|
||||||
__TAURI_INVOKE<SidecarFailureSnapshot_Serialize>('get_sidecar_failure'),
|
__TAURI_INVOKE<SidecarFailureSnapshot>('get_sidecar_failure'),
|
||||||
entryLightweightMode: () => __TAURI_INVOKE<null>('entry_lightweight_mode'),
|
entryLightweightMode: () => __TAURI_INVOKE<null>('entry_lightweight_mode'),
|
||||||
installService: () =>
|
installService: () =>
|
||||||
__TAURI_INVOKE<ServiceInstallOutcome>('install_service'),
|
__TAURI_INVOKE<ServiceInstallOutcome>('install_service'),
|
||||||
@@ -52,7 +48,7 @@ export const commands = {
|
|||||||
repairService: () => __TAURI_INVOKE<ServiceInstallOutcome>('repair_service'),
|
repairService: () => __TAURI_INVOKE<ServiceInstallOutcome>('repair_service'),
|
||||||
continueWithSidecar: () => __TAURI_INVOKE<null>('continue_with_sidecar'),
|
continueWithSidecar: () => __TAURI_INVOKE<null>('continue_with_sidecar'),
|
||||||
syncRuntimeProviders: () => __TAURI_INVOKE<void>('sync_runtime_providers'),
|
syncRuntimeProviders: () => __TAURI_INVOKE<void>('sync_runtime_providers'),
|
||||||
getClashInfo: () => __TAURI_INVOKE<ClashInfo_Serialize>('get_clash_info'),
|
getClashInfo: () => __TAURI_INVOKE<ClashInfo>('get_clash_info'),
|
||||||
patchClashConfig: (payload: YamlMapping) =>
|
patchClashConfig: (payload: YamlMapping) =>
|
||||||
__TAURI_INVOKE<null>('patch_clash_config', { payload }),
|
__TAURI_INVOKE<null>('patch_clash_config', { payload }),
|
||||||
patchClashMode: (payload: string) =>
|
patchClashMode: (payload: string) =>
|
||||||
@@ -60,11 +56,16 @@ export const commands = {
|
|||||||
/** Reads the saved mode without depending on strict mihomo `/configs` deserialization. */
|
/** Reads the saved mode without depending on strict mihomo `/configs` deserialization. */
|
||||||
getClashMode: () => __TAURI_INVOKE<string | null>('get_clash_mode'),
|
getClashMode: () => __TAURI_INVOKE<string | null>('get_clash_mode'),
|
||||||
changeClashCore: (clashCore: string) =>
|
changeClashCore: (clashCore: string) =>
|
||||||
__TAURI_INVOKE<CommandFailure_Serialize | null>('change_clash_core', {
|
__TAURI_INVOKE<{
|
||||||
clashCore,
|
/** Stable frontend identifier, when classified. */
|
||||||
}),
|
code?: string | null
|
||||||
|
/** Human-readable diagnostic detail. */
|
||||||
|
detail: string
|
||||||
|
/** Requested operation when known by the command. */
|
||||||
|
operation?: FailedOperation | null
|
||||||
|
} | null>('change_clash_core', { clashCore }),
|
||||||
getRuntimeConfig: () =>
|
getRuntimeConfig: () =>
|
||||||
__TAURI_INVOKE<YamlMapping | null>('get_runtime_config'),
|
__TAURI_INVOKE<{ [key in string]: JsonValue } | null>('get_runtime_config'),
|
||||||
getProxyView: () => __TAURI_INVOKE<ProxyViewV1_Serialize>('get_proxy_view'),
|
getProxyView: () => __TAURI_INVOKE<ProxyViewV1_Serialize>('get_proxy_view'),
|
||||||
getRuntimeYaml: () => __TAURI_INVOKE<string>('get_runtime_yaml'),
|
getRuntimeYaml: () => __TAURI_INVOKE<string>('get_runtime_yaml'),
|
||||||
getRuntimeLogs: () => __TAURI_INVOKE<RuntimeLogs>('get_runtime_logs'),
|
getRuntimeLogs: () => __TAURI_INVOKE<RuntimeLogs>('get_runtime_logs'),
|
||||||
@@ -72,7 +73,7 @@ export const commands = {
|
|||||||
__TAURI_INVOKE<string>('get_runtime_proxy_chain_config', {
|
__TAURI_INVOKE<string>('get_runtime_proxy_chain_config', {
|
||||||
proxyChainExitNode,
|
proxyChainExitNode,
|
||||||
}),
|
}),
|
||||||
updateProxyChainConfigInRuntime: (proxyChainConfig: YamlValue | null) =>
|
updateProxyChainConfigInRuntime: (proxyChainConfig: JsonValue | null) =>
|
||||||
__TAURI_INVOKE<ValidationOutcome>('update_proxy_chain_config_in_runtime', {
|
__TAURI_INVOKE<ValidationOutcome>('update_proxy_chain_config_in_runtime', {
|
||||||
proxyChainConfig,
|
proxyChainConfig,
|
||||||
}),
|
}),
|
||||||
@@ -102,11 +103,18 @@ export const commands = {
|
|||||||
takeDnsOverrideNotice: () =>
|
takeDnsOverrideNotice: () =>
|
||||||
__TAURI_INVOKE<boolean>('take_dns_override_notice'),
|
__TAURI_INVOKE<boolean>('take_dns_override_notice'),
|
||||||
takeServiceFallbackNotice: () =>
|
takeServiceFallbackNotice: () =>
|
||||||
__TAURI_INVOKE<ServiceFallbackNotice | null>(
|
__TAURI_INVOKE<
|
||||||
'take_service_fallback_notice',
|
| { kind: 'unavailable' }
|
||||||
),
|
| { kind: 'coreRejected'; reason: string }
|
||||||
|
| { kind: 'notAutoStarted' }
|
||||||
|
| null
|
||||||
|
>('take_service_fallback_notice'),
|
||||||
getCoreStartupError: () =>
|
getCoreStartupError: () =>
|
||||||
__TAURI_INVOKE<CoreFailure | null>('get_core_startup_error'),
|
__TAURI_INVOKE<
|
||||||
|
| { kind: 'startFailed'; detail: string }
|
||||||
|
| { kind: 'serviceCoreStopped'; detail: string }
|
||||||
|
| null
|
||||||
|
>('get_core_startup_error'),
|
||||||
takeServiceRepairNotice: () =>
|
takeServiceRepairNotice: () =>
|
||||||
__TAURI_INVOKE<boolean>('take_service_repair_notice'),
|
__TAURI_INVOKE<boolean>('take_service_repair_notice'),
|
||||||
takeServiceOwnerNotice: () =>
|
takeServiceOwnerNotice: () =>
|
||||||
@@ -132,12 +140,10 @@ export const commands = {
|
|||||||
openDevtools: () => __TAURI_INVOKE<void>('open_devtools'),
|
openDevtools: () => __TAURI_INVOKE<void>('open_devtools'),
|
||||||
exitApp: () => __TAURI_INVOKE<void>('exit_app'),
|
exitApp: () => __TAURI_INVOKE<void>('exit_app'),
|
||||||
getNetworkInterfacesInfo: () =>
|
getNetworkInterfacesInfo: () =>
|
||||||
__TAURI_INVOKE<NetworkInterfaceView_Serialize[]>(
|
__TAURI_INVOKE<NetworkInterfaceView[]>('get_network_interfaces_info'),
|
||||||
'get_network_interfaces_info',
|
|
||||||
),
|
|
||||||
getProfiles: () => __TAURI_INVOKE<IProfiles_Serialize>('get_profiles'),
|
getProfiles: () => __TAURI_INVOKE<IProfiles_Serialize>('get_profiles'),
|
||||||
enhanceProfiles: () => __TAURI_INVOKE<ValidationOutcome>('enhance_profiles'),
|
enhanceProfiles: () => __TAURI_INVOKE<ValidationOutcome>('enhance_profiles'),
|
||||||
patchProfilesConfig: (profiles: ProfileSelection_Deserialize) =>
|
patchProfilesConfig: (profiles: ProfileSelection) =>
|
||||||
__TAURI_INVOKE<ValidationOutcome>('patch_profiles_config', { profiles }),
|
__TAURI_INVOKE<ValidationOutcome>('patch_profiles_config', { profiles }),
|
||||||
viewProfile: (index: string) =>
|
viewProfile: (index: string) =>
|
||||||
__TAURI_INVOKE<null>('view_profile', { index }),
|
__TAURI_INVOKE<null>('view_profile', { index }),
|
||||||
@@ -145,12 +151,52 @@ export const commands = {
|
|||||||
__TAURI_INVOKE<null>('patch_profile', { index, profile }),
|
__TAURI_INVOKE<null>('patch_profile', { index, profile }),
|
||||||
createProfile: (item: ProfileCreate_Deserialize, fileData: string | null) =>
|
createProfile: (item: ProfileCreate_Deserialize, fileData: string | null) =>
|
||||||
__TAURI_INVOKE<null>('create_profile', { item, fileData }),
|
__TAURI_INVOKE<null>('create_profile', { item, fileData }),
|
||||||
importProfile: (url: string, option: PrfOption_Deserialize | null) =>
|
importProfile: (
|
||||||
__TAURI_INVOKE<null>('import_profile', { url, option }),
|
url: string,
|
||||||
|
option: {
|
||||||
|
user_agent?: string | null
|
||||||
|
with_proxy?: boolean | null
|
||||||
|
self_proxy?: boolean | null
|
||||||
|
update_interval?: number | null
|
||||||
|
/**
|
||||||
|
* HTTP request timeout in seconds
|
||||||
|
* default is 60 seconds
|
||||||
|
*/
|
||||||
|
timeout_seconds?: number | null
|
||||||
|
/** default is `false` */
|
||||||
|
danger_accept_invalid_certs?: boolean | null
|
||||||
|
allow_auto_update?: boolean | null
|
||||||
|
merge?: string | null
|
||||||
|
script?: string | null
|
||||||
|
rules?: string | null
|
||||||
|
proxies?: string | null
|
||||||
|
groups?: string | null
|
||||||
|
} | null,
|
||||||
|
) => __TAURI_INVOKE<null>('import_profile', { url, option }),
|
||||||
reorderProfile: (activeId: string, overId: string) =>
|
reorderProfile: (activeId: string, overId: string) =>
|
||||||
__TAURI_INVOKE<null>('reorder_profile', { activeId, overId }),
|
__TAURI_INVOKE<null>('reorder_profile', { activeId, overId }),
|
||||||
updateProfile: (index: string, option: PrfOption_Deserialize | null) =>
|
updateProfile: (
|
||||||
__TAURI_INVOKE<null>('update_profile', { index, option }),
|
index: string,
|
||||||
|
option: {
|
||||||
|
user_agent?: string | null
|
||||||
|
with_proxy?: boolean | null
|
||||||
|
self_proxy?: boolean | null
|
||||||
|
update_interval?: number | null
|
||||||
|
/**
|
||||||
|
* HTTP request timeout in seconds
|
||||||
|
* default is 60 seconds
|
||||||
|
*/
|
||||||
|
timeout_seconds?: number | null
|
||||||
|
/** default is `false` */
|
||||||
|
danger_accept_invalid_certs?: boolean | null
|
||||||
|
allow_auto_update?: boolean | null
|
||||||
|
merge?: string | null
|
||||||
|
script?: string | null
|
||||||
|
rules?: string | null
|
||||||
|
proxies?: string | null
|
||||||
|
groups?: string | null
|
||||||
|
} | null,
|
||||||
|
) => __TAURI_INVOKE<null>('update_profile', { index, option }),
|
||||||
deleteProfile: (index: string) =>
|
deleteProfile: (index: string) =>
|
||||||
__TAURI_INVOKE<null>('delete_profile', { index }),
|
__TAURI_INVOKE<null>('delete_profile', { index }),
|
||||||
readProfileFile: (index: string) =>
|
readProfileFile: (index: string) =>
|
||||||
@@ -178,14 +224,11 @@ export const commands = {
|
|||||||
__TAURI_INVOKE<null>('delete_webdav_backup', { filename }),
|
__TAURI_INVOKE<null>('delete_webdav_backup', { filename }),
|
||||||
restoreWebdavBackup: (filename: string) =>
|
restoreWebdavBackup: (filename: string) =>
|
||||||
__TAURI_INVOKE<null>('restore_webdav_backup', { filename }),
|
__TAURI_INVOKE<null>('restore_webdav_backup', { filename }),
|
||||||
getUnlockItems: () =>
|
getUnlockItems: () => __TAURI_INVOKE<UnlockItem[]>('get_unlock_items'),
|
||||||
__TAURI_INVOKE<UnlockItem_Serialize[]>('get_unlock_items'),
|
checkMediaUnlock: (onComplete: Channel<UnlockItem>) =>
|
||||||
checkMediaUnlock: (onComplete: Channel<UnlockItem_Deserialize>) =>
|
__TAURI_INVOKE<UnlockItem[]>('check_media_unlock', { onComplete }),
|
||||||
__TAURI_INVOKE<UnlockItem_Serialize[]>('check_media_unlock', {
|
|
||||||
onComplete,
|
|
||||||
}),
|
|
||||||
checkMediaUnlockItem: (name: string) =>
|
checkMediaUnlockItem: (name: string) =>
|
||||||
__TAURI_INVOKE<UnlockItem_Serialize>('check_media_unlock_item', { name }),
|
__TAURI_INVOKE<UnlockItem>('check_media_unlock_item', { name }),
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
@@ -194,20 +237,7 @@ export type AutoProxy = {
|
|||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ClashInfo = ClashInfo_Serialize | ClashInfo_Deserialize
|
export type ClashInfo = {
|
||||||
|
|
||||||
export type ClashInfo_Deserialize = {
|
|
||||||
/** clash core port */
|
|
||||||
mixed_port: number
|
|
||||||
socks_port: number
|
|
||||||
port: number
|
|
||||||
/** same as `external-controller` */
|
|
||||||
server: string
|
|
||||||
/** clash secret */
|
|
||||||
secret?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ClashInfo_Serialize = {
|
|
||||||
/** clash core port */
|
/** clash core port */
|
||||||
mixed_port: number
|
mixed_port: number
|
||||||
socks_port: number
|
socks_port: number
|
||||||
@@ -226,21 +256,21 @@ export type CommandFailure =
|
|||||||
/** Structured command failure returned to the frontend. */
|
/** Structured command failure returned to the frontend. */
|
||||||
export type CommandFailure_Deserialize = {
|
export type CommandFailure_Deserialize = {
|
||||||
/** Stable frontend identifier, when classified. */
|
/** Stable frontend identifier, when classified. */
|
||||||
code?: string | null
|
code: string | null
|
||||||
/** Human-readable diagnostic detail. */
|
/** Human-readable diagnostic detail. */
|
||||||
detail: string
|
detail: string
|
||||||
/** Requested operation when known by the command. */
|
/** Requested operation when known by the command. */
|
||||||
operation?: FailedOperation | null
|
operation: FailedOperation | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Structured command failure returned to the frontend. */
|
/** Structured command failure returned to the frontend. */
|
||||||
export type CommandFailure_Serialize = {
|
export type CommandFailure_Serialize = {
|
||||||
/** Stable frontend identifier, when classified. */
|
/** Stable frontend identifier, when classified. */
|
||||||
code?: string
|
code?: string | null
|
||||||
/** Human-readable diagnostic detail. */
|
/** Human-readable diagnostic detail. */
|
||||||
detail: string
|
detail: string
|
||||||
/** Requested operation when known by the command. */
|
/** Requested operation when known by the command. */
|
||||||
operation?: FailedOperation
|
operation?: FailedOperation | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Why the Core is not running, kept until a Core starts again. */
|
/** Why the Core is not running, kept until a Core starts again. */
|
||||||
@@ -263,26 +293,7 @@ export type DnsOverrideOutcome =
|
|||||||
| { status: 'confirmation_required'; source: string }
|
| { status: 'confirmation_required'; source: string }
|
||||||
|
|
||||||
/** Same wire shape as the updater plugin's JS `DownloadEvent`. */
|
/** Same wire shape as the updater plugin's JS `DownloadEvent`. */
|
||||||
export type DownloadEvent = DownloadEvent_Serialize | DownloadEvent_Deserialize
|
export type DownloadEvent =
|
||||||
|
|
||||||
/** Same wire shape as the updater plugin's JS `DownloadEvent`. */
|
|
||||||
export type DownloadEvent_Deserialize =
|
|
||||||
| {
|
|
||||||
event: 'Started'
|
|
||||||
data: {
|
|
||||||
contentLength?: number | null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
event: 'Progress'
|
|
||||||
data: {
|
|
||||||
chunkLength: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| { event: 'Finished' }
|
|
||||||
|
|
||||||
/** Same wire shape as the updater plugin's JS `DownloadEvent`. */
|
|
||||||
export type DownloadEvent_Serialize =
|
|
||||||
| {
|
| {
|
||||||
event: 'Started'
|
event: 'Started'
|
||||||
data: {
|
data: {
|
||||||
@@ -322,27 +333,14 @@ export type IProfiles_Serialize = {
|
|||||||
/** ### `verge.yaml` schema */
|
/** ### `verge.yaml` schema */
|
||||||
export type IVerge = IVerge_Serialize | IVerge_Deserialize
|
export type IVerge = IVerge_Serialize | IVerge_Deserialize
|
||||||
|
|
||||||
export type IVergeTestItem =
|
export type IVergeTestItem = {
|
||||||
| IVergeTestItem_Serialize
|
|
||||||
| IVergeTestItem_Deserialize
|
|
||||||
|
|
||||||
export type IVergeTestItem_Deserialize = {
|
|
||||||
uid?: string | null
|
uid?: string | null
|
||||||
name?: string | null
|
name?: string | null
|
||||||
icon?: string | null
|
icon?: string | null
|
||||||
url?: string | null
|
url?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IVergeTestItem_Serialize = {
|
export type IVergeTheme = {
|
||||||
uid: string | null
|
|
||||||
name: string | null
|
|
||||||
icon: string | null
|
|
||||||
url: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IVergeTheme = IVergeTheme_Serialize | IVergeTheme_Deserialize
|
|
||||||
|
|
||||||
export type IVergeTheme_Deserialize = {
|
|
||||||
primary_color?: string | null
|
primary_color?: string | null
|
||||||
secondary_color?: string | null
|
secondary_color?: string | null
|
||||||
primary_text?: string | null
|
primary_text?: string | null
|
||||||
@@ -355,19 +353,6 @@ export type IVergeTheme_Deserialize = {
|
|||||||
css_injection?: string | null
|
css_injection?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IVergeTheme_Serialize = {
|
|
||||||
primary_color: string | null
|
|
||||||
secondary_color: string | null
|
|
||||||
primary_text: string | null
|
|
||||||
secondary_text: string | null
|
|
||||||
info_color: string | null
|
|
||||||
error_color: string | null
|
|
||||||
warning_color: string | null
|
|
||||||
success_color: string | null
|
|
||||||
font_family: string | null
|
|
||||||
css_injection: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ### `verge.yaml` schema */
|
/** ### `verge.yaml` schema */
|
||||||
export type IVerge_Deserialize = {
|
export type IVerge_Deserialize = {
|
||||||
/** silent | error | warn | info | debug | trace */
|
/** silent | error | warn | info | debug | trace */
|
||||||
@@ -410,7 +395,7 @@ export type IVerge_Deserialize = {
|
|||||||
proxy_auto_config?: boolean | null
|
proxy_auto_config?: boolean | null
|
||||||
pac_file_content?: string | null
|
pac_file_content?: string | null
|
||||||
proxy_host?: string | null
|
proxy_host?: string | null
|
||||||
theme_setting?: IVergeTheme_Deserialize | null
|
theme_setting?: IVergeTheme | null
|
||||||
web_ui_list?: string[] | null
|
web_ui_list?: string[] | null
|
||||||
clash_core?: string | null
|
clash_core?: string | null
|
||||||
/** format: {func},{key} */
|
/** format: {func},{key} */
|
||||||
@@ -426,7 +411,7 @@ export type IVerge_Deserialize = {
|
|||||||
auto_delay_detection_interval_minutes?: number | null
|
auto_delay_detection_interval_minutes?: number | null
|
||||||
enable_builtin_enhanced?: boolean | null
|
enable_builtin_enhanced?: boolean | null
|
||||||
proxy_layout_column?: number | null
|
proxy_layout_column?: number | null
|
||||||
test_list?: IVergeTestItem_Deserialize[] | null
|
test_list?: IVergeTestItem[] | null
|
||||||
/** 0: 不清理; 1: 1天;2: 7天; 3: 30天; 4: 90天 */
|
/** 0: 不清理; 1: 1天;2: 7天; 3: 30天; 4: 90天 */
|
||||||
auto_log_clean?: number | null
|
auto_log_clean?: number | null
|
||||||
enable_auto_backup_schedule?: boolean | null
|
enable_auto_backup_schedule?: boolean | null
|
||||||
@@ -475,13 +460,13 @@ export type IVerge_Serialize = {
|
|||||||
traffic_graph: boolean | null
|
traffic_graph: boolean | null
|
||||||
/** show memory info (only for Mihomo) */
|
/** show memory info (only for Mihomo) */
|
||||||
enable_memory_usage: boolean | null
|
enable_memory_usage: boolean | null
|
||||||
enable_group_icon?: boolean
|
enable_group_icon?: boolean | null
|
||||||
pause_render_traffic_stats_on_blur: boolean | null
|
pause_render_traffic_stats_on_blur: boolean | null
|
||||||
common_tray_icon?: boolean
|
common_tray_icon?: boolean | null
|
||||||
menu_icon?: string
|
menu_icon?: string | null
|
||||||
menu_order?: string[]
|
menu_order?: string[] | null
|
||||||
proxy_group_tools_position?: string
|
proxy_group_tools_position?: string | null
|
||||||
notice_position?: string
|
notice_position?: string | null
|
||||||
collapse_navbar: boolean | null
|
collapse_navbar: boolean | null
|
||||||
sysproxy_tray_icon: boolean | null
|
sysproxy_tray_icon: boolean | null
|
||||||
tun_tray_icon: boolean | null
|
tun_tray_icon: boolean | null
|
||||||
@@ -500,11 +485,11 @@ export type IVerge_Serialize = {
|
|||||||
proxy_auto_config: boolean | null
|
proxy_auto_config: boolean | null
|
||||||
pac_file_content: string | null
|
pac_file_content: string | null
|
||||||
proxy_host: string | null
|
proxy_host: string | null
|
||||||
theme_setting: IVergeTheme_Serialize | null
|
theme_setting: IVergeTheme | null
|
||||||
web_ui_list: string[] | null
|
web_ui_list: string[] | null
|
||||||
clash_core?: string
|
clash_core?: string | null
|
||||||
/** format: {func},{key} */
|
/** format: {func},{key} */
|
||||||
hotkeys?: string[]
|
hotkeys?: string[] | null
|
||||||
enable_global_hotkey: boolean | null
|
enable_global_hotkey: boolean | null
|
||||||
home_cards: JsonValue | null
|
home_cards: JsonValue | null
|
||||||
auto_close_connection: boolean | null
|
auto_close_connection: boolean | null
|
||||||
@@ -516,7 +501,7 @@ export type IVerge_Serialize = {
|
|||||||
auto_delay_detection_interval_minutes: number | null
|
auto_delay_detection_interval_minutes: number | null
|
||||||
enable_builtin_enhanced: boolean | null
|
enable_builtin_enhanced: boolean | null
|
||||||
proxy_layout_column: number | null
|
proxy_layout_column: number | null
|
||||||
test_list: IVergeTestItem_Serialize[] | null
|
test_list: IVergeTestItem[] | null
|
||||||
/** 0: 不清理; 1: 1天;2: 7天; 3: 30天; 4: 90天 */
|
/** 0: 不清理; 1: 1天;2: 7天; 3: 30天; 4: 90天 */
|
||||||
auto_log_clean: number | null
|
auto_log_clean: number | null
|
||||||
enable_auto_backup_schedule: boolean | null
|
enable_auto_backup_schedule: boolean | null
|
||||||
@@ -528,10 +513,10 @@ export type IVerge_Serialize = {
|
|||||||
verge_socks_enabled: boolean | null
|
verge_socks_enabled: boolean | null
|
||||||
verge_port: number | null
|
verge_port: number | null
|
||||||
verge_http_enabled: boolean | null
|
verge_http_enabled: boolean | null
|
||||||
webdav_url?: string
|
webdav_url?: string | null
|
||||||
webdav_username?: string
|
webdav_username?: string | null
|
||||||
webdav_password?: string
|
webdav_password?: string | null
|
||||||
tray_proxy_groups_display_mode?: string
|
tray_proxy_groups_display_mode?: string | null
|
||||||
tray_inline_outbound_modes: boolean | null
|
tray_inline_outbound_modes: boolean | null
|
||||||
enable_auto_light_weight_mode: boolean | null
|
enable_auto_light_weight_mode: boolean | null
|
||||||
/** 自动进入轻量模式的延迟(分钟) */
|
/** 自动进入轻量模式的延迟(分钟) */
|
||||||
@@ -593,17 +578,7 @@ export type LocalBackupFile = {
|
|||||||
content_length: number
|
content_length: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NetworkInterfaceView =
|
export type NetworkInterfaceView = {
|
||||||
| NetworkInterfaceView_Serialize
|
|
||||||
| NetworkInterfaceView_Deserialize
|
|
||||||
|
|
||||||
export type NetworkInterfaceView_Deserialize = {
|
|
||||||
name: string
|
|
||||||
addr: InterfaceAddress[]
|
|
||||||
mac_addr?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type NetworkInterfaceView_Serialize = {
|
|
||||||
name: string
|
name: string
|
||||||
addr: InterfaceAddress[]
|
addr: InterfaceAddress[]
|
||||||
mac_addr: string | null
|
mac_addr: string | null
|
||||||
@@ -662,20 +637,7 @@ export type PendingFailure = {
|
|||||||
sequence: number
|
sequence: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlatformVergeFields =
|
export type PlatformVergeFields = {
|
||||||
| PlatformVergeFields_Serialize
|
|
||||||
| PlatformVergeFields_Deserialize
|
|
||||||
|
|
||||||
export type PlatformVergeFields_Deserialize = {
|
|
||||||
tray_icon?: string | null
|
|
||||||
verge_redir_port?: number | null
|
|
||||||
verge_redir_enabled?: boolean | null
|
|
||||||
verge_tproxy_port?: number | null
|
|
||||||
verge_tproxy_enabled?: boolean | null
|
|
||||||
enable_tray_speed?: boolean | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PlatformVergeFields_Serialize = {
|
|
||||||
tray_icon?: string | null
|
tray_icon?: string | null
|
||||||
verge_redir_port?: number | null
|
verge_redir_port?: number | null
|
||||||
verge_redir_enabled?: boolean | null
|
verge_redir_enabled?: boolean | null
|
||||||
@@ -701,7 +663,7 @@ export type PrfItem_Deserialize = {
|
|||||||
file?: string | null
|
file?: string | null
|
||||||
desc?: string | null
|
desc?: string | null
|
||||||
url?: string | null
|
url?: string | null
|
||||||
selected?: PrfSelected_Deserialize[] | null
|
selected?: PrfSelected[] | null
|
||||||
extra?: PrfExtra | null
|
extra?: PrfExtra | null
|
||||||
updated?: number | null
|
updated?: number | null
|
||||||
option?: PrfOption_Deserialize | null
|
option?: PrfOption_Deserialize | null
|
||||||
@@ -714,13 +676,13 @@ export type PrfItem_Serialize = {
|
|||||||
type: string | null
|
type: string | null
|
||||||
name: string | null
|
name: string | null
|
||||||
file: string | null
|
file: string | null
|
||||||
desc?: string
|
desc?: string | null
|
||||||
url?: string
|
url?: string | null
|
||||||
selected?: PrfSelected_Serialize[]
|
selected?: PrfSelected[] | null
|
||||||
extra?: PrfExtra
|
extra?: PrfExtra | null
|
||||||
updated: number | null
|
updated: number | null
|
||||||
option?: PrfOption_Serialize
|
option?: PrfOption_Serialize | null
|
||||||
home?: string
|
home?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PrfOption = PrfOption_Serialize | PrfOption_Deserialize
|
export type PrfOption = PrfOption_Serialize | PrfOption_Deserialize
|
||||||
@@ -746,18 +708,18 @@ export type PrfOption_Deserialize = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PrfOption_Serialize = {
|
export type PrfOption_Serialize = {
|
||||||
user_agent?: string
|
user_agent?: string | null
|
||||||
with_proxy?: boolean
|
with_proxy?: boolean | null
|
||||||
self_proxy?: boolean
|
self_proxy?: boolean | null
|
||||||
update_interval?: number
|
update_interval?: number | null
|
||||||
/**
|
/**
|
||||||
* HTTP request timeout in seconds
|
* HTTP request timeout in seconds
|
||||||
* default is 60 seconds
|
* default is 60 seconds
|
||||||
*/
|
*/
|
||||||
timeout_seconds?: number
|
timeout_seconds?: number | null
|
||||||
/** default is `false` */
|
/** default is `false` */
|
||||||
danger_accept_invalid_certs?: boolean
|
danger_accept_invalid_certs?: boolean | null
|
||||||
allow_auto_update?: boolean
|
allow_auto_update?: boolean | null
|
||||||
merge: string | null
|
merge: string | null
|
||||||
script: string | null
|
script: string | null
|
||||||
rules: string | null
|
rules: string | null
|
||||||
@@ -765,18 +727,11 @@ export type PrfOption_Serialize = {
|
|||||||
groups: string | null
|
groups: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PrfSelected = PrfSelected_Serialize | PrfSelected_Deserialize
|
export type PrfSelected = {
|
||||||
|
|
||||||
export type PrfSelected_Deserialize = {
|
|
||||||
name?: string | null
|
name?: string | null
|
||||||
now?: string | null
|
now?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PrfSelected_Serialize = {
|
|
||||||
name: string | null
|
|
||||||
now: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ProfileCreate = ProfileCreate_Serialize | ProfileCreate_Deserialize
|
export type ProfileCreate = ProfileCreate_Serialize | ProfileCreate_Deserialize
|
||||||
|
|
||||||
export type ProfileCreate_Deserialize = {
|
export type ProfileCreate_Deserialize = {
|
||||||
@@ -806,7 +761,7 @@ export type ProfileDnsSettings_Deserialize = {
|
|||||||
|
|
||||||
export type ProfileDnsSettings_Serialize = {
|
export type ProfileDnsSettings_Serialize = {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
confirmation?: string
|
confirmation?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfilePatch = ProfilePatch_Serialize | ProfilePatch_Deserialize
|
export type ProfilePatch = ProfilePatch_Serialize | ProfilePatch_Deserialize
|
||||||
@@ -817,7 +772,7 @@ export type ProfilePatch_Deserialize = {
|
|||||||
desc?: string | null
|
desc?: string | null
|
||||||
file?: string | null
|
file?: string | null
|
||||||
url?: string | null
|
url?: string | null
|
||||||
selected?: PrfSelected_Deserialize[] | null
|
selected?: PrfSelected[] | null
|
||||||
extra?: PrfExtra | null
|
extra?: PrfExtra | null
|
||||||
updated?: number | null
|
updated?: number | null
|
||||||
option?: PrfOption_Deserialize | null
|
option?: PrfOption_Deserialize | null
|
||||||
@@ -829,24 +784,16 @@ export type ProfilePatch_Serialize = {
|
|||||||
desc: string | null
|
desc: string | null
|
||||||
file: string | null
|
file: string | null
|
||||||
url: string | null
|
url: string | null
|
||||||
selected: PrfSelected_Serialize[] | null
|
selected: PrfSelected[] | null
|
||||||
extra: PrfExtra | null
|
extra: PrfExtra | null
|
||||||
updated: number | null
|
updated: number | null
|
||||||
option: PrfOption_Serialize | null
|
option: PrfOption_Serialize | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileSelection =
|
export type ProfileSelection = {
|
||||||
| ProfileSelection_Serialize
|
|
||||||
| ProfileSelection_Deserialize
|
|
||||||
|
|
||||||
export type ProfileSelection_Deserialize = {
|
|
||||||
current?: string | null
|
current?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileSelection_Serialize = {
|
|
||||||
current: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ProfileUpdatePayload = {
|
export type ProfileUpdatePayload = {
|
||||||
uid: string
|
uid: string
|
||||||
}
|
}
|
||||||
@@ -866,11 +813,11 @@ export type ProxyGroupView =
|
|||||||
export type ProxyGroupView_Deserialize = {
|
export type ProxyGroupView_Deserialize = {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
now?: string | null
|
now: string | null
|
||||||
fixed?: string | null
|
fixed: string | null
|
||||||
hidden?: boolean | null
|
hidden: boolean | null
|
||||||
icon?: string | null
|
icon: string | null
|
||||||
testUrl?: string | null
|
testUrl: string | null
|
||||||
history: DelayHistory[]
|
history: DelayHistory[]
|
||||||
members: ProxyMemberRef[]
|
members: ProxyMemberRef[]
|
||||||
} & ProxyCapabilities
|
} & ProxyCapabilities
|
||||||
@@ -878,11 +825,11 @@ export type ProxyGroupView_Deserialize = {
|
|||||||
export type ProxyGroupView_Serialize = {
|
export type ProxyGroupView_Serialize = {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
now?: string
|
now?: string | null
|
||||||
fixed?: string
|
fixed?: string | null
|
||||||
hidden?: boolean
|
hidden?: boolean | null
|
||||||
icon?: string
|
icon?: string | null
|
||||||
testUrl?: string
|
testUrl?: string | null
|
||||||
history: DelayHistory[]
|
history: DelayHistory[]
|
||||||
members: ProxyMemberRef[]
|
members: ProxyMemberRef[]
|
||||||
} & ProxyCapabilities
|
} & ProxyCapabilities
|
||||||
@@ -908,10 +855,10 @@ export type ProxyNodeView_Deserialize = {
|
|||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
history: DelayHistory[]
|
history: DelayHistory[]
|
||||||
id?: string | null
|
id: string | null
|
||||||
hidden?: boolean | null
|
hidden: boolean | null
|
||||||
icon?: string | null
|
icon: string | null
|
||||||
testUrl?: string | null
|
testUrl: string | null
|
||||||
source: ProxyNodeSource
|
source: ProxyNodeSource
|
||||||
} & ProxyCapabilities
|
} & ProxyCapabilities
|
||||||
|
|
||||||
@@ -920,10 +867,10 @@ export type ProxyNodeView_Serialize = {
|
|||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
history: DelayHistory[]
|
history: DelayHistory[]
|
||||||
id?: string
|
id?: string | null
|
||||||
hidden?: boolean
|
hidden?: boolean | null
|
||||||
icon?: string
|
icon?: string | null
|
||||||
testUrl?: string
|
testUrl?: string | null
|
||||||
source: ProxyNodeSource
|
source: ProxyNodeSource
|
||||||
} & ProxyCapabilities
|
} & ProxyCapabilities
|
||||||
|
|
||||||
@@ -944,16 +891,16 @@ export type ProxyProviderView =
|
|||||||
export type ProxyProviderView_Deserialize = {
|
export type ProxyProviderView_Deserialize = {
|
||||||
name: string
|
name: string
|
||||||
vehicleType: ProxyProviderVehicleType
|
vehicleType: ProxyProviderVehicleType
|
||||||
updatedAt?: string | null
|
updatedAt: string | null
|
||||||
subscriptionInfo?: ProxySubscriptionInfo | null
|
subscriptionInfo: ProxySubscriptionInfo | null
|
||||||
proxyRecordIds: string[]
|
proxyRecordIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProxyProviderView_Serialize = {
|
export type ProxyProviderView_Serialize = {
|
||||||
name: string
|
name: string
|
||||||
vehicleType: ProxyProviderVehicleType
|
vehicleType: ProxyProviderVehicleType
|
||||||
updatedAt?: string
|
updatedAt?: string | null
|
||||||
subscriptionInfo?: ProxySubscriptionInfo
|
subscriptionInfo?: ProxySubscriptionInfo | null
|
||||||
proxyRecordIds: string[]
|
proxyRecordIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -974,8 +921,8 @@ export type ProxyViewV1_Deserialize = {
|
|||||||
schemaVersion: number
|
schemaVersion: number
|
||||||
orderSource: ProxyViewOrderSource
|
orderSource: ProxyViewOrderSource
|
||||||
providerState: ProxyViewProviderState
|
providerState: ProxyViewProviderState
|
||||||
global?: ProxyGroupView_Deserialize | null
|
global: ProxyGroupView_Deserialize | null
|
||||||
direct?: string | null
|
direct: string | null
|
||||||
groups: ProxyGroupView_Deserialize[]
|
groups: ProxyGroupView_Deserialize[]
|
||||||
records: { [key in string]: ProxyNodeView_Deserialize }
|
records: { [key in string]: ProxyNodeView_Deserialize }
|
||||||
standalone: string[]
|
standalone: string[]
|
||||||
@@ -994,22 +941,7 @@ export type ProxyViewV1_Serialize = {
|
|||||||
providers: ProxyProviderView_Serialize[]
|
providers: ProxyProviderView_Serialize[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RunStateView = RunStateView_Serialize | RunStateView_Deserialize
|
export type RunStateView = {
|
||||||
|
|
||||||
export type RunStateView_Deserialize = {
|
|
||||||
mode: RunningMode
|
|
||||||
service: ServiceHealthKind
|
|
||||||
serviceUnavailableReason?: string | null
|
|
||||||
pendingAction?: PendingAction | null
|
|
||||||
sidecarAllowed: boolean
|
|
||||||
isAdmin: boolean
|
|
||||||
opInFlight: boolean
|
|
||||||
serviceUsable: boolean
|
|
||||||
tunCapable: boolean
|
|
||||||
serviceNeedsAttention: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RunStateView_Serialize = {
|
|
||||||
mode: RunningMode
|
mode: RunningMode
|
||||||
service: ServiceHealthKind
|
service: ServiceHealthKind
|
||||||
serviceUnavailableReason: string | null
|
serviceUnavailableReason: string | null
|
||||||
@@ -1048,18 +980,7 @@ export type ServiceInstallOutcome =
|
|||||||
| { status: 'sidecar'; reason: string }
|
| { status: 'sidecar'; reason: string }
|
||||||
|
|
||||||
/** A removal has a revision too, so a delayed read cannot restore a resolved failure. */
|
/** A removal has a revision too, so a delayed read cannot restore a resolved failure. */
|
||||||
export type SidecarFailureSnapshot =
|
export type SidecarFailureSnapshot = {
|
||||||
| SidecarFailureSnapshot_Serialize
|
|
||||||
| SidecarFailureSnapshot_Deserialize
|
|
||||||
|
|
||||||
/** A removal has a revision too, so a delayed read cannot restore a resolved failure. */
|
|
||||||
export type SidecarFailureSnapshot_Deserialize = {
|
|
||||||
revision: number
|
|
||||||
detail?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A removal has a revision too, so a delayed read cannot restore a resolved failure. */
|
|
||||||
export type SidecarFailureSnapshot_Serialize = {
|
|
||||||
revision: number
|
revision: number
|
||||||
detail: string | null
|
detail: string | null
|
||||||
}
|
}
|
||||||
@@ -1080,16 +1001,7 @@ export type ToggleableProxyPort = {
|
|||||||
port: number
|
port: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UnlockItem = UnlockItem_Serialize | UnlockItem_Deserialize
|
export type UnlockItem = {
|
||||||
|
|
||||||
export type UnlockItem_Deserialize = {
|
|
||||||
name: string
|
|
||||||
status: string
|
|
||||||
region?: string | null
|
|
||||||
check_time?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UnlockItem_Serialize = {
|
|
||||||
name: string
|
name: string
|
||||||
status: string
|
status: string
|
||||||
region: string | null
|
region: string | null
|
||||||
@@ -1115,11 +1027,7 @@ export type ValidationOutcome =
|
|||||||
|
|
||||||
export type ValidationSkipReason = 'exiting' | 'debounced'
|
export type ValidationSkipReason = 'exiting' | 'debounced'
|
||||||
|
|
||||||
export type VergeEventPayloads =
|
export type VergeEventPayloads = {
|
||||||
| VergeEventPayloads_Serialize
|
|
||||||
| VergeEventPayloads_Deserialize
|
|
||||||
|
|
||||||
export type VergeEventPayloads_Deserialize = {
|
|
||||||
'verge://refresh-clash-config': null
|
'verge://refresh-clash-config': null
|
||||||
'verge://refresh-verge-config': null
|
'verge://refresh-verge-config': null
|
||||||
'verge://refresh-profiles': null
|
'verge://refresh-profiles': null
|
||||||
@@ -1129,21 +1037,7 @@ export type VergeEventPayloads_Deserialize = {
|
|||||||
'verge://timer-updated': string
|
'verge://timer-updated': string
|
||||||
'profile-update-started': ProfileUpdatePayload
|
'profile-update-started': ProfileUpdatePayload
|
||||||
'profile-update-completed': ProfileUpdatePayload
|
'profile-update-completed': ProfileUpdatePayload
|
||||||
'verge://run-state-changed': RunStateView_Deserialize
|
'verge://run-state-changed': RunStateView
|
||||||
'verge://pending-failures-changed': null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type VergeEventPayloads_Serialize = {
|
|
||||||
'verge://refresh-clash-config': null
|
|
||||||
'verge://refresh-verge-config': null
|
|
||||||
'verge://refresh-profiles': null
|
|
||||||
'verge://refresh-proxy-config': null
|
|
||||||
'verge://notice-message': [NoticeStatus, string]
|
|
||||||
'profile-changed': string
|
|
||||||
'verge://timer-updated': string
|
|
||||||
'profile-update-started': ProfileUpdatePayload
|
|
||||||
'profile-update-completed': ProfileUpdatePayload
|
|
||||||
'verge://run-state-changed': RunStateView_Serialize
|
|
||||||
'verge://pending-failures-changed': null
|
'verge://pending-failures-changed': null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import type {
|
|||||||
|
|
||||||
export type {
|
export type {
|
||||||
RunningMode,
|
RunningMode,
|
||||||
RunStateView_Serialize as RunState,
|
RunStateView as RunState,
|
||||||
FailedOperation,
|
FailedOperation,
|
||||||
PendingFailure,
|
PendingFailure,
|
||||||
SidecarFailureSnapshot,
|
SidecarFailureSnapshot,
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
export type {
|
export type { NoticeStatus, VergeEventPayloads } from './bindings'
|
||||||
NoticeStatus,
|
|
||||||
VergeEventPayloads_Serialize as VergeEventPayloads,
|
|
||||||
} from './bindings'
|
|
||||||
|
|||||||
@@ -5,12 +5,16 @@ import react from '@vitejs/plugin-react'
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import svgr from 'vite-plugin-svgr'
|
import svgr from 'vite-plugin-svgr'
|
||||||
|
|
||||||
|
import { reactDiagnostics } from './scripts/react/vite.mts'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: 'src',
|
root: 'src',
|
||||||
|
cacheDir: path.resolve('node_modules/.vite/default'),
|
||||||
server: { port: 3000 },
|
server: { port: 3000 },
|
||||||
plugins: [
|
plugins: [
|
||||||
svgr(),
|
svgr(),
|
||||||
react(),
|
react(),
|
||||||
|
...reactDiagnostics(process.env.CVR_REACT_DIAGNOSTICS),
|
||||||
legacy({
|
legacy({
|
||||||
modernTargets: ['edge>=109', 'safari>=14'],
|
modernTargets: ['edge>=109', 'safari>=14'],
|
||||||
renderLegacyChunks: false,
|
renderLegacyChunks: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user