From 47c8ccb0e54fa0c792600389d5b2cea3d20e84ff Mon Sep 17 00:00:00 2001 From: GyDi Date: Sun, 11 Sep 2022 20:58:55 +0800 Subject: [PATCH] refactor: optimize --- src-tauri/Cargo.lock | 260 +++++++++++++----- src-tauri/Cargo.toml | 4 +- src-tauri/src/cmds.rs | 217 +++++++-------- src-tauri/src/config/mod.rs | 4 +- src-tauri/src/core/handle.rs | 101 +++++++ src-tauri/src/core/mod.rs | 328 +++++++++-------------- src-tauri/src/core/notice.rs | 37 --- src-tauri/src/core/service.rs | 162 +++++------ src-tauri/src/core/sysopt.rs | 197 ++++++++------ src-tauri/src/core/timer.rs | 27 +- src-tauri/src/{core => data}/clash.rs | 1 + src-tauri/src/data/mod.rs | 32 +++ src-tauri/src/{core => data}/prfitem.rs | 0 src-tauri/src/{core => data}/profiles.rs | 0 src-tauri/src/{core => data}/verge.rs | 2 +- src-tauri/src/main.rs | 36 +-- src-tauri/src/utils/help.rs | 10 +- src-tauri/src/utils/mod.rs | 1 - src-tauri/src/utils/resolve.rs | 21 +- src-tauri/src/utils/tmpl.rs | 3 +- 20 files changed, 812 insertions(+), 631 deletions(-) create mode 100644 src-tauri/src/core/handle.rs delete mode 100644 src-tauri/src/core/notice.rs rename src-tauri/src/{core => data}/clash.rs (99%) create mode 100644 src-tauri/src/data/mod.rs rename src-tauri/src/{core => data}/prfitem.rs (100%) rename src-tauri/src/{core => data}/profiles.rs (100%) rename src-tauri/src/{core => data}/verge.rs (98%) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 62b7561..5accace 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -34,6 +34,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +dependencies = [ + "memchr", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -124,7 +133,7 @@ dependencies = [ "concurrent-queue", "futures-lite", "libc", - "log", + "log 0.4.17", "once_cell", "parking", "polling", @@ -226,7 +235,7 @@ checksum = "262c3f7f5d61249d8c00e5546e2685cd15ebeeb1bc0f3cc5449350a1cb07319e" dependencies = [ "flate2", "http", - "log", + "log 0.4.17", "native-tls", "openssl", "serde", @@ -238,12 +247,12 @@ dependencies = [ [[package]] name = "auto-launch" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642d13324da4df30a472026356a7fd24845d4a8038e5c47ed99c62074b526fa5" +checksum = "5904a4d734f0235edf29aab320a14899f3e090446e594ff96508a6215f76f89c" dependencies = [ - "anyhow", "dirs 4.0.0", + "thiserror", "winreg", ] @@ -500,9 +509,10 @@ dependencies = [ "delay_timer", "dirs 4.0.0", "dunce", - "log", + "log 0.4.17", "log4rs", "nanoid", + "once_cell", "open 2.1.3", "parking_lot 0.12.1", "port_scanner", @@ -513,6 +523,7 @@ dependencies = [ "serde_json", "serde_yaml", "sysinfo", + "sysproxy", "tauri", "tauri-build", "tokio", @@ -764,7 +775,7 @@ version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" dependencies = [ - "nix", + "nix 0.25.0", "winapi", ] @@ -825,7 +836,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7397f8c48906dd9b5afc75001368c979418e5dff5575998a831eb2319b424e" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", "pathsearch", "rand 0.8.5", "shared_library", @@ -866,7 +877,7 @@ dependencies = [ "dashmap", "event-listener", "futures", - "log", + "log 0.4.17", "lru", "once_cell", "rs-snowflake", @@ -1333,7 +1344,7 @@ checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" dependencies = [ "cc", "libc", - "log", + "log 0.4.17", "rustversion", "winapi", ] @@ -1463,11 +1474,11 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "bstr", "fnv", - "log", - "regex", + "log 0.4.17", + "regex 1.6.0", ] [[package]] @@ -1555,6 +1566,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "handlebars" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc" +dependencies = [ + "lazy_static 0.2.11", + "log 0.3.9", + "pest 0.3.3", + "quick-error", + "regex 0.2.11", + "serde", + "serde_json", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -1631,7 +1657,7 @@ version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ - "log", + "log 0.4.17", "mac", "markup5ever", "proc-macro2", @@ -1757,12 +1783,12 @@ checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" dependencies = [ "crossbeam-utils", "globset", - "lazy_static", - "log", + "lazy_static 1.4.0", + "log 0.4.17", "memchr", - "regex", + "regex 1.6.0", "same-file", - "thread_local", + "thread_local 1.1.4", "walkdir", "winapi-util", ] @@ -1818,6 +1844,22 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "interfaces" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec8f50a973916cac3da5057c986db05cd3346f38c78e9bc24f64cc9f6a3978f" +dependencies = [ + "bitflags", + "cc", + "handlebars", + "lazy_static 1.4.0", + "libc", + "nix 0.23.1", + "serde", + "serde_derive", +] + [[package]] name = "ipnet" version = "2.5.0" @@ -1868,7 +1910,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log", + "log 0.4.17", "thiserror", "walkdir", ] @@ -1882,7 +1924,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log", + "log 0.4.17", "thiserror", "walkdir", ] @@ -1925,6 +1967,12 @@ dependencies = [ "selectors", ] +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" + [[package]] name = "lazy_static" version = "1.4.0" @@ -1941,7 +1989,7 @@ dependencies = [ "gtk", "gtk-sys", "libappindicator-sys", - "log", + "log 0.4.17", ] [[package]] @@ -1996,6 +2044,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.17", +] + [[package]] name = "log" version = "0.4.17" @@ -2025,7 +2082,7 @@ dependencies = [ "fnv", "humantime", "libc", - "log", + "log 0.4.17", "log-mdc", "parking_lot 0.12.1", "serde", @@ -2083,7 +2140,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" dependencies = [ - "log", + "log 0.4.17", "phf 0.8.0", "phf_codegen", "string_cache", @@ -2171,7 +2228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", - "log", + "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -2184,7 +2241,7 @@ checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" dependencies = [ "buf_redux", "httparse", - "log", + "log 0.4.17", "mime", "mime_guess", "quick-error", @@ -2209,9 +2266,9 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", "libc", - "log", + "log 0.4.17", "openssl", "openssl-probe", "openssl-sys", @@ -2255,6 +2312,19 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset", +] + [[package]] name = "nix" version = "0.25.0" @@ -2444,9 +2514,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "opaque-debug" @@ -2645,6 +2715,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" + [[package]] name = "pest" version = "2.1.3" @@ -2836,7 +2912,7 @@ checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ "cfg-if 1.0.0", "libc", - "log", + "log 0.4.17", "wepoll-ffi", "winapi", ] @@ -3057,15 +3133,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +dependencies = [ + "aho-corasick 0.6.10", + "memchr", + "regex-syntax 0.5.6", + "thread_local 0.3.6", + "utf8-ranges", +] + [[package]] name = "regex" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "memchr", - "regex-syntax", + "regex-syntax 0.6.27", ] [[package]] @@ -3074,7 +3163,16 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.27", +] + +[[package]] +name = "regex-syntax" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +dependencies = [ + "ucd-util", ] [[package]] @@ -3110,8 +3208,8 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", - "log", + "lazy_static 1.4.0", + "log 0.4.17", "mime", "native-tls", "percent-encoding", @@ -3142,8 +3240,8 @@ dependencies = [ "gobject-sys", "gtk-sys", "js-sys", - "lazy_static", - "log", + "lazy_static 1.4.0", + "log 0.4.17", "objc", "objc-foundation", "objc_id", @@ -3263,7 +3361,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", "windows-sys", ] @@ -3312,7 +3410,7 @@ dependencies = [ "cssparser", "derive_more", "fxhash", - "log", + "log 0.4.17", "matches", "phf 0.8.0", "phf_codegen", @@ -3361,7 +3459,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" dependencies = [ - "pest", + "pest 2.1.3", ] [[package]] @@ -3548,7 +3646,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", ] [[package]] @@ -3567,7 +3665,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", "libc", ] @@ -3747,6 +3845,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "sysproxy" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fd97e02a884d8009c43ef592ddea3d01bca955fe25f44ac7e63f169350a372" +dependencies = [ + "interfaces", + "thiserror", + "winreg", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -3799,10 +3908,10 @@ dependencies = [ "image", "instant", "jni 0.19.0", - "lazy_static", + "lazy_static 1.4.0", "libappindicator", "libc", - "log", + "log 0.4.17", "ndk", "ndk-context", "ndk-sys", @@ -3861,7 +3970,7 @@ dependencies = [ "percent-encoding", "rand 0.8.5", "raw-window-handle", - "regex", + "regex 1.6.0", "rfd", "semver 1.0.12", "serde", @@ -3917,7 +4026,7 @@ dependencies = [ "png 0.17.5", "proc-macro2", "quote", - "regex", + "regex 1.6.0", "semver 1.0.12", "serde", "serde_json", @@ -4069,14 +4178,14 @@ dependencies = [ "cfg-if 1.0.0", "filedescriptor", "hex", - "lazy_static", + "lazy_static 1.4.0", "libc", - "log", + "log 0.4.17", "memmem", "num-derive", "num-traits", "ordered-float", - "regex", + "regex 1.6.0", "semver 0.11.0", "sha2 0.9.9", "signal-hook 0.1.17", @@ -4126,6 +4235,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +dependencies = [ + "lazy_static 1.4.0", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -4232,7 +4350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" dependencies = [ "futures-util", - "log", + "log 0.4.17", "pin-project", "tokio", "tungstenite", @@ -4247,7 +4365,7 @@ dependencies = [ "bytes", "futures-core", "futures-sink", - "log", + "log 0.4.17", "pin-project-lite", "tokio", ] @@ -4288,7 +4406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", - "log", + "log 0.4.17", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4321,8 +4439,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ - "lazy_static", - "log", + "lazy_static 1.4.0", + "log 0.4.17", "tracing-core", ] @@ -4335,10 +4453,10 @@ dependencies = [ "ansi_term", "matchers", "once_cell", - "regex", + "regex 1.6.0", "sharded-slab", "smallvec", - "thread_local", + "thread_local 1.1.4", "tracing", "tracing-core", "tracing-log", @@ -4376,7 +4494,7 @@ dependencies = [ "bytes", "http", "httparse", - "log", + "log 0.4.17", "rand 0.8.5", "sha-1 0.9.8", "thiserror", @@ -4414,6 +4532,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +[[package]] +name = "ucd-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bfcbf611b122f2c10eb1bb6172fbc4c2e25df9970330e4d75ce2b5201c9bfc" + [[package]] name = "unicase" version = "2.6.0" @@ -4478,6 +4602,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-ranges" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" + [[package]] name = "utf8parse" version = "0.2.0" @@ -4584,7 +4714,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log", + "log 0.4.17", "try-lock", ] @@ -4600,7 +4730,7 @@ dependencies = [ "headers", "http", "hyper", - "log", + "log 0.4.17", "mime", "mime_guess", "multipart", @@ -4653,8 +4783,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", - "lazy_static", - "log", + "lazy_static 1.4.0", + "log 0.4.17", "proc-macro2", "quote", "syn", @@ -4788,7 +4918,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0258c53ee9adc0a4f8ba1c8c317588f7a58c7048a55b621d469ba75ab3709ca1" dependencies = [ - "regex", + "regex 1.6.0", "serde", "serde_json", "thiserror", @@ -4822,7 +4952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" dependencies = [ "either", - "lazy_static", + "lazy_static 1.4.0", "libc", ] @@ -5040,7 +5170,7 @@ dependencies = [ "http", "jni 0.18.0", "libc", - "log", + "log 0.4.17", "objc", "objc_id", "once_cell", @@ -5072,7 +5202,7 @@ version = "2.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" dependencies = [ - "lazy_static", + "lazy_static 1.4.0", "libc", "pkg-config", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b369b32..852daef 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -25,9 +25,11 @@ log4rs = "1.0.0" nanoid = "0.4.0" chrono = "0.4.19" sysinfo = "0.26.2" +sysproxy = "0.1" serde_json = "1.0" serde_yaml = "0.8" -auto-launch = "0.3" +auto-launch = "0.4" +once_cell = "1.14.0" port_scanner = "0.1.5" delay_timer = "0.11.1" parking_lot = "0.12.0" diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index e7a3d2b..16d8192 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -1,39 +1,39 @@ use crate::{ - core::{ClashInfo, Core, PrfItem, PrfOption, Profiles, Verge}, - utils::{dirs, help, sysopt::SysProxyConfig}, + core::Core, + data::{ClashInfo, Data, PrfItem, PrfOption, Profiles, Verge}, + utils::{dirs, help}, }; use crate::{log_if_err, ret_err, wrap_err}; use anyhow::Result; use serde_yaml::Mapping; use std::collections::{HashMap, VecDeque}; -use tauri::{api, State}; +use sysproxy::Sysproxy; type CmdResult = Result; /// get all profiles from `profiles.yaml` #[tauri::command] -pub fn get_profiles(core: State<'_, Core>) -> CmdResult { - let profiles = core.profiles.lock(); +pub fn get_profiles() -> CmdResult { + let global = Data::global(); + let profiles = global.profiles.lock(); Ok(profiles.clone()) } /// manually exec enhanced profile #[tauri::command] -pub fn enhance_profiles(core: State<'_, Core>) -> CmdResult { +pub fn enhance_profiles() -> CmdResult { + let core = Core::global(); wrap_err!(core.activate()) } /// import the profile from url /// and save to `profiles.yaml` #[tauri::command] -pub async fn import_profile( - url: String, - option: Option, - core: State<'_, Core>, -) -> CmdResult { +pub async fn import_profile(url: String, option: Option) -> CmdResult { let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?; - let mut profiles = core.profiles.lock(); + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.append_item(item)) } @@ -41,60 +41,66 @@ pub async fn import_profile( /// append a temp profile item file to the `profiles` dir /// view the temp profile file by using vscode or other editor #[tauri::command] -pub async fn create_profile( - item: PrfItem, // partial - file_data: Option, - core: State<'_, Core>, -) -> CmdResult { +pub async fn create_profile(item: PrfItem, file_data: Option) -> CmdResult { let item = wrap_err!(PrfItem::from(item, file_data).await)?; - let mut profiles = core.profiles.lock(); + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.append_item(item)) } /// Update the profile #[tauri::command] -pub async fn update_profile( - index: String, - option: Option, - core: State<'_, Core>, -) -> CmdResult { +pub async fn update_profile(index: String, option: Option) -> CmdResult { + let core = Core::global(); wrap_err!(core.update_profile_item(index, option).await) } /// change the current profile #[tauri::command] -pub fn select_profile(index: String, core: State<'_, Core>) -> CmdResult { - let mut profiles = core.profiles.lock(); +pub fn select_profile(index: String) -> CmdResult { + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.put_current(index))?; drop(profiles); + + let core = Core::global(); wrap_err!(core.activate()) } /// change the profile chain #[tauri::command] -pub fn change_profile_chain(chain: Option>, core: State<'_, Core>) -> CmdResult { - let mut profiles = core.profiles.lock(); +pub fn change_profile_chain(chain: Option>) -> CmdResult { + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.put_chain(chain))?; drop(profiles); + + let core = Core::global(); wrap_err!(core.activate()) } /// change the profile valid fields #[tauri::command] -pub fn change_profile_valid(valid: Option>, core: State) -> CmdResult { - let mut profiles = core.profiles.lock(); +pub fn change_profile_valid(valid: Option>) -> CmdResult { + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.put_valid(valid))?; drop(profiles); + + let core = Core::global(); wrap_err!(core.activate()) } /// delete profile item #[tauri::command] -pub fn delete_profile(index: String, core: State<'_, Core>) -> CmdResult { - let mut profiles = core.profiles.lock(); +pub fn delete_profile(index: String) -> CmdResult { + let global = Data::global(); + let mut profiles = global.profiles.lock(); if wrap_err!(profiles.delete_item(index))? { drop(profiles); + + let core = Core::global(); log_if_err!(core.activate()); } Ok(()) @@ -102,30 +108,33 @@ pub fn delete_profile(index: String, core: State<'_, Core>) -> CmdResult { /// patch the profile config #[tauri::command] -pub fn patch_profile(index: String, profile: PrfItem, core: State<'_, Core>) -> CmdResult { - let mut profiles = core.profiles.lock(); +pub fn patch_profile(index: String, profile: PrfItem) -> CmdResult { + let global = Data::global(); + let mut profiles = global.profiles.lock(); wrap_err!(profiles.patch_item(index, profile))?; drop(profiles); // update cron task + let core = Core::global(); let mut timer = core.timer.lock(); wrap_err!(timer.refresh()) } /// run vscode command to edit the profile #[tauri::command] -pub fn view_profile(index: String, core: State<'_, Core>) -> CmdResult { - let profiles = core.profiles.lock(); +pub fn view_profile(index: String) -> CmdResult { + let global = Data::global(); + let profiles = global.profiles.lock(); let item = wrap_err!(profiles.get_item(&index))?; let file = item.file.clone(); if file.is_none() { - ret_err!("the file is null"); + ret_err!("file is null"); } let path = dirs::app_profiles_dir().join(file.unwrap()); if !path.exists() { - ret_err!("the file not found"); + ret_err!("file not found"); } wrap_err!(help::open_file(path)) @@ -133,8 +142,9 @@ pub fn view_profile(index: String, core: State<'_, Core>) -> CmdResult { /// read the profile item file data #[tauri::command] -pub fn read_profile_file(index: String, core: State<'_, Core>) -> CmdResult { - let profiles = core.profiles.lock(); +pub fn read_profile_file(index: String) -> CmdResult { + let global = Data::global(); + let profiles = global.profiles.lock(); let item = wrap_err!(profiles.get_item(&index))?; let data = wrap_err!(item.read_file())?; Ok(data) @@ -142,16 +152,13 @@ pub fn read_profile_file(index: String, core: State<'_, Core>) -> CmdResult, - core: State<'_, Core>, -) -> CmdResult { +pub fn save_profile_file(index: String, file_data: Option) -> CmdResult { if file_data.is_none() { return Ok(()); } - let profiles = core.profiles.lock(); + let global = Data::global(); + let profiles = global.profiles.lock(); let item = wrap_err!(profiles.get_item(&index))?; wrap_err!(item.save_file(file_data.unwrap())) } @@ -159,37 +166,40 @@ pub fn save_profile_file( /// get the clash core info from the state /// the caller can also get the infomation by clash's api #[tauri::command] -pub fn get_clash_info(core: State<'_, Core>) -> CmdResult { - let clash = core.clash.lock(); +pub fn get_clash_info() -> CmdResult { + let global = Data::global(); + let clash = global.clash.lock(); Ok(clash.info.clone()) } /// get the runtime clash config mapping #[tauri::command] -pub fn get_runtime_config(core: State<'_, Core>) -> CmdResult> { +pub fn get_runtime_config() -> CmdResult> { + let core = Core::global(); let rt = core.runtime.lock(); Ok(rt.config.clone()) } /// get the runtime clash config yaml string #[tauri::command] -pub fn get_runtime_yaml(core: State<'_, Core>) -> CmdResult> { +pub fn get_runtime_yaml() -> CmdResult> { + let core = Core::global(); let rt = core.runtime.lock(); Ok(rt.config_yaml.clone()) } /// get the runtime config exists keys #[tauri::command] -pub fn get_runtime_exists(core: State<'_, Core>) -> CmdResult> { +pub fn get_runtime_exists() -> CmdResult> { + let core = Core::global(); let rt = core.runtime.lock(); Ok(rt.exists_keys.clone()) } /// get the runtime enhanced chain log #[tauri::command] -pub fn get_runtime_logs( - core: State<'_, Core>, -) -> CmdResult>> { +pub fn get_runtime_logs() -> CmdResult>> { + let core = Core::global(); let rt = core.runtime.lock(); Ok(rt.chain_logs.clone()) } @@ -198,87 +208,87 @@ pub fn get_runtime_logs( /// after putting the change to the clash core /// then we should save the latest config #[tauri::command] -pub fn patch_clash_config( - payload: Mapping, - app_handle: tauri::AppHandle, - core: State<'_, Core>, -) -> CmdResult { - wrap_err!(core.patch_clash(payload, &app_handle)) +pub fn patch_clash_config(payload: Mapping) -> CmdResult { + let core = Core::global(); + wrap_err!(core.patch_clash(payload)) } /// get the verge config #[tauri::command] -pub fn get_verge_config(core: State<'_, Core>) -> CmdResult { - let verge = core.verge.lock(); +pub fn get_verge_config() -> CmdResult { + let global = Data::global(); + let verge = global.verge.lock(); Ok(verge.clone()) } /// patch the verge config /// this command only save the config and not responsible for other things #[tauri::command] -pub fn patch_verge_config( - payload: Verge, - app_handle: tauri::AppHandle, - core: State<'_, Core>, -) -> CmdResult { - wrap_err!(core.patch_verge(payload, &app_handle)) +pub fn patch_verge_config(payload: Verge) -> CmdResult { + let core = Core::global(); + wrap_err!(core.patch_verge(payload)) } /// change clash core #[tauri::command] -pub fn change_clash_core(core: State<'_, Core>, clash_core: Option) -> CmdResult { +pub fn change_clash_core(clash_core: Option) -> CmdResult { + let core = Core::global(); wrap_err!(core.change_core(clash_core)) } /// restart the sidecar #[tauri::command] -pub fn restart_sidecar(core: State<'_, Core>) -> CmdResult { +pub fn restart_sidecar() -> CmdResult { + let core = Core::global(); wrap_err!(core.restart_clash()) } /// kill all sidecars when update app #[tauri::command] pub fn kill_sidecar() { - api::process::kill_children(); + tauri::api::process::kill_children(); } /// get the system proxy #[tauri::command] -pub fn get_sys_proxy() -> Result { - wrap_err!(SysProxyConfig::get_sys()) -} +pub fn get_sys_proxy() -> CmdResult { + let current = wrap_err!(Sysproxy::get_system_proxy())?; -/// get the current proxy config -/// which may not the same as system proxy -#[tauri::command] -pub fn get_cur_proxy(core: State<'_, Core>) -> CmdResult> { - let sysopt = core.sysopt.lock(); - wrap_err!(sysopt.get_sysproxy()) + let mut map = Mapping::new(); + map.insert("enable".into(), current.enable.into()); + map.insert( + "server".into(), + format!("{}:{}", current.host, current.port).into(), + ); + map.insert("bypass".into(), current.bypass.into()); + + Ok(map) } #[tauri::command] -pub fn get_clash_logs(core: State<'_, Core>) -> CmdResult> { +pub fn get_clash_logs() -> CmdResult> { + let core = Core::global(); let service = core.service.lock(); Ok(service.get_logs()) } /// open app config dir #[tauri::command] -pub fn open_app_dir() -> Result<(), String> { +pub fn open_app_dir() -> CmdResult<()> { let app_dir = dirs::app_home_dir(); wrap_err!(open::that(app_dir)) } /// open logs dir #[tauri::command] -pub fn open_logs_dir() -> Result<(), String> { +pub fn open_logs_dir() -> CmdResult<()> { let log_dir = dirs::app_logs_dir(); wrap_err!(open::that(log_dir)) } /// open url #[tauri::command] -pub fn open_web_url(url: String) -> Result<(), String> { +pub fn open_web_url(url: String) -> CmdResult<()> { wrap_err!(open::that(url)) } @@ -289,17 +299,17 @@ pub mod service { use crate::core::win_service::JsonResponse; #[tauri::command] - pub async fn start_service() -> Result<(), String> { + pub async fn start_service() -> CmdResult<()> { wrap_err!(crate::core::Service::start_service().await) } #[tauri::command] - pub async fn stop_service() -> Result<(), String> { + pub async fn stop_service() -> CmdResult<()> { wrap_err!(crate::core::Service::stop_service().await) } #[tauri::command] - pub async fn check_service() -> Result { + pub async fn check_service() -> CmdResult { // no log match crate::core::Service::check_service().await { Ok(res) => Ok(res), @@ -308,12 +318,12 @@ pub mod service { } #[tauri::command] - pub async fn install_service() -> Result<(), String> { + pub async fn install_service() -> CmdResult<()> { wrap_err!(crate::core::Service::install_service().await) } #[tauri::command] - pub async fn uninstall_service() -> Result<(), String> { + pub async fn uninstall_service() -> CmdResult<()> { wrap_err!(crate::core::Service::uninstall_service().await) } } @@ -323,26 +333,23 @@ pub mod service { use super::*; #[tauri::command] - pub async fn start_service() -> Result<(), String> { - Ok(()) - } - - #[tauri::command] - pub async fn stop_service() -> Result<(), String> { - Ok(()) - } - - #[tauri::command] - pub async fn check_service() -> Result<(), String> { - Ok(()) - } - - #[tauri::command] - pub async fn install_service() -> Result<(), String> { + pub async fn start_service() -> CmdResult<()> { Ok(()) } #[tauri::command] - pub async fn uninstall_service() -> Result<(), String> { + pub async fn stop_service() -> CmdResult<()> { + Ok(()) + } + #[tauri::command] + pub async fn check_service() -> CmdResult<()> { + Ok(()) + } + #[tauri::command] + pub async fn install_service() -> CmdResult<()> { + Ok(()) + } + #[tauri::command] + pub async fn uninstall_service() -> CmdResult<()> { Ok(()) } } diff --git a/src-tauri/src/config/mod.rs b/src-tauri/src/config/mod.rs index d4ae508..5bfca85 100644 --- a/src-tauri/src/config/mod.rs +++ b/src-tauri/src/config/mod.rs @@ -7,8 +7,8 @@ pub(self) use self::field::*; use self::merge::*; use self::script::*; use self::tun::*; -use crate::core::ChainItem; -use crate::core::ChainType; +use crate::data::ChainItem; +use crate::data::ChainType; use serde_yaml::Mapping; use std::collections::HashMap; use std::collections::HashSet; diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs new file mode 100644 index 0000000..bba93d0 --- /dev/null +++ b/src-tauri/src/core/handle.rs @@ -0,0 +1,101 @@ +use crate::data::*; +use crate::log_if_err; +use anyhow::{bail, Result}; +use serde_yaml::Value; +use tauri::{AppHandle, Manager, Window}; + +#[derive(Debug, Default, Clone)] +pub struct Handle { + pub app_handle: Option, +} + +impl Handle { + pub fn from(app_handle: Option) -> Handle { + Handle { app_handle } + } + + pub fn get_window(&self) -> Option { + self + .app_handle + .as_ref() + .map_or(None, |a| a.get_window("main")) + } + + pub fn refresh_clash(&self) { + if let Some(window) = self.get_window() { + log_if_err!(window.emit("verge://refresh-clash-config", "yes")); + } + } + + pub fn refresh_verge(&self) { + if let Some(window) = self.get_window() { + log_if_err!(window.emit("verge://refresh-verge-config", "yes")); + } + } + + #[allow(unused)] + pub fn refresh_profiles(&self) { + if let Some(window) = self.get_window() { + log_if_err!(window.emit("verge://refresh-profiles-config", "yes")); + } + } + + // update system tray state (clash config) + pub fn update_systray_clash(&self) -> Result<()> { + if self.app_handle.is_none() { + bail!("unhandle error"); + } + + let app_handle = self.app_handle.as_ref().unwrap(); + + let global = Data::global(); + let clash = global.clash.lock(); + let mode = clash + .config + .get(&Value::from("mode")) + .map(|val| val.as_str().unwrap_or("rule")) + .unwrap_or("rule"); + + let tray = app_handle.tray_handle(); + + tray.get_item("rule_mode").set_selected(mode == "rule")?; + tray + .get_item("global_mode") + .set_selected(mode == "global")?; + tray + .get_item("direct_mode") + .set_selected(mode == "direct")?; + tray + .get_item("script_mode") + .set_selected(mode == "script")?; + + Ok(()) + } + + /// update the system tray state (verge config) + pub fn update_systray(&self) -> Result<()> { + if self.app_handle.is_none() { + bail!("unhandle error"); + } + + let app_handle = self.app_handle.as_ref().unwrap(); + let tray = app_handle.tray_handle(); + + let global = Data::global(); + let verge = global.verge.lock(); + let system_proxy = verge.enable_system_proxy.as_ref(); + let tun_mode = verge.enable_tun_mode.as_ref(); + + tray + .get_item("system_proxy") + .set_selected(*system_proxy.unwrap_or(&false))?; + tray + .get_item("tun_mode") + .set_selected(*tun_mode.unwrap_or(&false))?; + + // update verge config + self.refresh_verge(); + + Ok(()) + } +} diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index f3bd3f9..df7d6d2 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -1,108 +1,71 @@ -use self::notice::Notice; +use self::handle::Handle; use self::sysopt::Sysopt; use self::timer::Timer; use crate::config::enhance_config; +use crate::data::*; use crate::log_if_err; use anyhow::{bail, Result}; +use once_cell::sync::Lazy; use parking_lot::Mutex; -use serde_yaml::Mapping; -use serde_yaml::Value; +use serde_yaml::{Mapping, Value}; use std::sync::Arc; -use tauri::{AppHandle, Manager, Window}; -mod clash; -mod notice; -mod prfitem; -mod profiles; +mod handle; mod service; mod sysopt; mod timer; -mod verge; -pub use self::clash::*; -pub use self::prfitem::*; -pub use self::profiles::*; pub use self::service::*; -pub use self::verge::*; + +static CORE: Lazy = Lazy::new(|| Core { + service: Arc::new(Mutex::new(Service::new())), + sysopt: Arc::new(Mutex::new(Sysopt::new())), + timer: Arc::new(Mutex::new(Timer::new())), + runtime: Arc::new(Mutex::new(RuntimeResult::default())), + handle: Handle::default(), +}); #[derive(Clone)] pub struct Core { - pub clash: Arc>, - pub verge: Arc>, - pub profiles: Arc>, pub service: Arc>, pub sysopt: Arc>, pub timer: Arc>, pub runtime: Arc>, - pub window: Arc>>, + pub handle: Handle, } impl Core { - pub fn new() -> Core { - Core { - clash: Arc::new(Mutex::new(Clash::new())), - verge: Arc::new(Mutex::new(Verge::new())), - profiles: Arc::new(Mutex::new(Profiles::new())), - service: Arc::new(Mutex::new(Service::new())), - sysopt: Arc::new(Mutex::new(Sysopt::new())), - timer: Arc::new(Mutex::new(Timer::new())), - runtime: Arc::new(Mutex::new(RuntimeResult::default())), - window: Arc::new(Mutex::new(None)), - } + pub fn global() -> Core { + CORE.clone() } /// initialize the core state - pub fn init(&self, app_handle: tauri::AppHandle) { + pub fn init(&mut self, app_handle: tauri::AppHandle) { // kill old clash process Service::kill_old_clash(); + self.handle = Handle::from(Some(app_handle)); - let verge = self.verge.lock(); - let clash_core = verge.clash_core.clone(); - - let mut service = self.service.lock(); - service.set_core(clash_core); - - #[cfg(windows)] { - let enable = verge.enable_service_mode.clone(); - service.set_mode(enable.unwrap_or(false)); + let mut service = self.service.lock(); + log_if_err!(service.start()); } - log_if_err!(service.start()); - drop(verge); - drop(service); - log_if_err!(self.activate()); - let clash = self.clash.lock(); - let verge = self.verge.lock(); + { + let mut sysopt = self.sysopt.lock(); + log_if_err!(sysopt.init_launch()); + log_if_err!(sysopt.init_sysproxy()); + } - // let silent_start = verge.enable_silent_start.clone(); - let auto_launch = verge.enable_auto_launch.clone(); - let mut sysopt = self.sysopt.lock(); - - sysopt.init_sysproxy(clash.info.port.clone(), &verge); - - drop(clash); - drop(verge); - - log_if_err!(sysopt.init_launch(auto_launch)); - - log_if_err!(self.update_systray(&app_handle)); - log_if_err!(self.update_systray_clash(&app_handle)); + log_if_err!(self.handle.update_systray()); + log_if_err!(self.handle.update_systray_clash()); // timer initialize let mut timer = self.timer.lock(); - timer.set_core(self.clone()); log_if_err!(timer.restore()); } - /// save the window instance - pub fn set_win(&self, win: Option) { - let mut window = self.window.lock(); - *window = win; - } - /// restart the clash sidecar pub fn restart_clash(&self) -> Result<()> { let mut service = self.service.lock(); @@ -119,7 +82,8 @@ impl Core { bail!("invalid clash core name \"{clash_core}\""); } - let mut verge = self.verge.lock(); + let global = Data::global(); + let mut verge = global.verge.lock(); verge.patch_config(Verge { clash_core: Some(clash_core.clone()), ..Verge::default() @@ -127,10 +91,8 @@ impl Core { drop(verge); let mut service = self.service.lock(); - service.stop()?; - service.set_core(Some(clash_core)); service.clear_logs(); - service.start()?; + service.restart()?; drop(service); self.activate() @@ -138,12 +100,13 @@ impl Core { /// Patch Clash /// handle the clash config changed - pub fn patch_clash(&self, patch: Mapping, app_handle: &AppHandle) -> Result<()> { + pub fn patch_clash(&self, patch: Mapping) -> Result<()> { let has_port = patch.contains_key(&Value::from("mixed-port")); let has_mode = patch.contains_key(&Value::from("mode")); let port = { - let mut clash = self.clash.lock(); + let global = Data::global(); + let mut clash = global.clash.lock(); clash.patch_config(patch)?; clash.info.port.clone() }; @@ -157,175 +120,121 @@ impl Core { self.activate()?; let mut sysopt = self.sysopt.lock(); - let verge = self.verge.lock(); - sysopt.init_sysproxy(port, &verge); + sysopt.init_sysproxy()?; } if has_mode { - self.update_systray_clash(app_handle)?; + self.handle.update_systray_clash()?; } Ok(()) } /// Patch Verge - pub fn patch_verge(&self, patch: Verge, app_handle: &AppHandle) -> Result<()> { - let tun_mode = patch.enable_tun_mode.clone(); - let auto_launch = patch.enable_auto_launch.clone(); - let system_proxy = patch.enable_system_proxy.clone(); - let proxy_bypass = patch.system_proxy_bypass.clone(); - let proxy_guard = patch.enable_proxy_guard.clone(); + pub fn patch_verge(&self, patch: Verge) -> Result<()> { + // save the patch + let global = Data::global(); + let mut verge = global.verge.lock(); + verge.patch_config(patch.clone())?; + drop(verge); - #[cfg(windows)] + let tun_mode = patch.enable_tun_mode; + let auto_launch = patch.enable_auto_launch; + let system_proxy = patch.enable_system_proxy; + let proxy_bypass = patch.system_proxy_bypass; + let proxy_guard = patch.enable_proxy_guard; + + #[cfg(target_os = "windows")] { - let service_mode = patch.enable_service_mode.clone(); + let service_mode = patch.enable_service_mode; + // 重启服务 if service_mode.is_some() { - let service_mode = service_mode.unwrap(); - let mut service = self.service.lock(); - service.stop()?; - service.set_mode(service_mode); - service.start()?; + service.restart()?; drop(service); + } - // self.activate_enhanced(false)?; + if tun_mode.is_some() && *tun_mode.as_ref().unwrap_or(&false) { + let wintun_dll = crate::utils::dirs::app_home_dir().join("wintun.dll"); + if !wintun_dll.exists() { + bail!("failed to enable TUN for missing `wintun.dll`"); + } + } + + if service_mode.is_some() || tun_mode.is_some() { self.activate()?; } } - if auto_launch.is_some() { - let mut sysopt = self.sysopt.lock(); - sysopt.update_launch(auto_launch)?; - } - - if system_proxy.is_some() || proxy_bypass.is_some() { - let mut sysopt = self.sysopt.lock(); - sysopt.update_sysproxy(system_proxy.clone(), proxy_bypass)?; - sysopt.guard_proxy(); - } - - if proxy_guard.unwrap_or(false) { - let sysopt = self.sysopt.lock(); - sysopt.guard_proxy(); - } - - #[cfg(target_os = "windows")] - if tun_mode.is_some() && *tun_mode.as_ref().unwrap_or(&false) { - let wintun_dll = crate::utils::dirs::app_home_dir().join("wintun.dll"); - if !wintun_dll.exists() { - bail!("failed to enable TUN for missing `wintun.dll`"); - } - } - - // save the patch - let mut verge = self.verge.lock(); - verge.patch_config(patch)?; - drop(verge); - - if system_proxy.is_some() || tun_mode.is_some() { - self.update_systray(app_handle)?; - } - + #[cfg(not(target_os = "windows"))] if tun_mode.is_some() { self.activate()?; } - Ok(()) - } + let mut sysopt = self.sysopt.lock(); - // update system tray state (clash config) - pub fn update_systray_clash(&self, app_handle: &AppHandle) -> Result<()> { - let clash = self.clash.lock(); - let mode = clash - .config - .get(&Value::from("mode")) - .map(|val| val.as_str().unwrap_or("rule")) - .unwrap_or("rule"); + if auto_launch.is_some() { + sysopt.update_launch()?; + } + if system_proxy.is_some() || proxy_bypass.is_some() { + sysopt.update_sysproxy()?; + sysopt.guard_proxy(); + } + if proxy_guard.unwrap_or(false) { + sysopt.guard_proxy(); + } - let tray = app_handle.tray_handle(); - - tray.get_item("rule_mode").set_selected(mode == "rule")?; - tray - .get_item("global_mode") - .set_selected(mode == "global")?; - tray - .get_item("direct_mode") - .set_selected(mode == "direct")?; - tray - .get_item("script_mode") - .set_selected(mode == "script")?; - - Ok(()) - } - - /// update the system tray state (verge config) - pub fn update_systray(&self, app_handle: &AppHandle) -> Result<()> { - let verge = self.verge.lock(); - let tray = app_handle.tray_handle(); - - let system_proxy = verge.enable_system_proxy.as_ref(); - let tun_mode = verge.enable_tun_mode.as_ref(); - - tray - .get_item("system_proxy") - .set_selected(*system_proxy.unwrap_or(&false))?; - tray - .get_item("tun_mode") - .set_selected(*tun_mode.unwrap_or(&false))?; - - // update verge config - let window = app_handle.get_window("main"); - let notice = Notice::from(window); - notice.refresh_verge(); + if system_proxy.is_some() || tun_mode.is_some() { + self.handle.update_systray()?; + } Ok(()) } // update rule/global/direct/script mode - pub fn update_mode(&self, app_handle: &AppHandle, mode: &str) -> Result<()> { + pub fn update_mode(&self, mode: &str) -> Result<()> { // save config to file - let mut clash = self.clash.lock(); - clash.config.insert(Value::from("mode"), Value::from(mode)); - clash.save_config()?; - - let info = clash.info.clone(); - drop(clash); - - let notice = { - let window = self.window.lock(); - Notice::from(window.clone()) + let info = { + let global = Data::global(); + let mut clash = global.clash.lock(); + clash.config.insert(Value::from("mode"), Value::from(mode)); + clash.save_config()?; + clash.info.clone() }; let mut mapping = Mapping::new(); mapping.insert(Value::from("mode"), Value::from(mode)); - let service = self.service.lock(); - service.patch_config(info, mapping, notice)?; + tauri::async_runtime::spawn(async move { + log_if_err!(Service::patch_config(info, mapping.to_owned()).await); + }); // update tray - self.update_systray_clash(app_handle)?; + self.handle.update_systray_clash()?; Ok(()) } /// activate the profile /// auto activate enhanced profile + /// 触发clash配置更新 pub fn activate(&self) -> Result<()> { - let profile_activate = { - let profiles = self.profiles.lock(); - profiles.gen_activate()? - }; + let global = Data::global(); - let (clash_config, clash_info) = { - let clash = self.clash.lock(); - (clash.config.clone(), clash.info.clone()) - }; + let verge = global.verge.lock(); + let clash = global.clash.lock(); + let profiles = global.profiles.lock(); - let tun_mode = { - let verge = self.verge.lock(); - verge.enable_tun_mode.unwrap_or(false) - }; + let tun_mode = verge.enable_tun_mode.clone().unwrap_or(false); + let profile_activate = profiles.gen_activate()?; + + let clash_config = clash.config.clone(); + let clash_info = clash.info.clone(); + + drop(clash); + drop(verge); + drop(profiles); let (config, exists_keys, logs) = enhance_config( clash_config, @@ -336,25 +245,36 @@ impl Core { ); let mut runtime = self.runtime.lock(); - runtime.config = Some(config.clone()); - runtime.config_yaml = Some(serde_yaml::to_string(&config).unwrap_or("".into())); - runtime.exists_keys = exists_keys; - runtime.chain_logs = logs; - - let notice = { - let window = self.window.lock(); - Notice::from(window.clone()) + *runtime = RuntimeResult { + config: Some(config.clone()), + config_yaml: Some(serde_yaml::to_string(&config).unwrap_or("".into())), + exists_keys, + chain_logs: logs, }; + drop(runtime); - let service = self.service.lock(); - service.set_config(clash_info, config, notice) + let mut service = self.service.lock(); + service.check_start()?; + drop(service); + + let handle = self.handle.clone(); + tauri::async_runtime::spawn(async move { + match Service::set_config(clash_info, config).await { + Ok(_) => handle.refresh_clash(), + Err(err) => log::error!(target: "app", "{err}"), + } + }); + + Ok(()) } /// Static function /// update profile item pub async fn update_profile_item(&self, uid: String, option: Option) -> Result<()> { + let global = Data::global(); + let (url, opt) = { - let profiles = self.profiles.lock(); + let profiles = global.profiles.lock(); let item = profiles.get_item(&uid)?; if let Some(typ) = item.itype.as_ref() { @@ -363,7 +283,7 @@ impl Core { // reactivate the config if Some(uid) == profiles.get_current() { drop(profiles); - return self.activate(); + self.activate()?; } return Ok(()); } @@ -377,7 +297,7 @@ impl Core { let merged_opt = PrfOption::merge(opt, option); let item = PrfItem::from_url(&url, None, None, merged_opt).await?; - let mut profiles = self.profiles.lock(); + let mut profiles = global.profiles.lock(); profiles.update_item(uid.clone(), item)?; // reactivate the profile diff --git a/src-tauri/src/core/notice.rs b/src-tauri/src/core/notice.rs deleted file mode 100644 index 52e3dd6..0000000 --- a/src-tauri/src/core/notice.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::log_if_err; -use tauri::Window; - -#[derive(Debug, Default, Clone)] -pub struct Notice { - win: Option, -} - -impl Notice { - pub fn from(win: Option) -> Notice { - Notice { win } - } - - #[allow(unused)] - pub fn set_win(&mut self, win: Option) { - self.win = win; - } - - pub fn refresh_clash(&self) { - if let Some(window) = self.win.as_ref() { - log_if_err!(window.emit("verge://refresh-clash-config", "yes")); - } - } - - pub fn refresh_verge(&self) { - if let Some(window) = self.win.as_ref() { - log_if_err!(window.emit("verge://refresh-verge-config", "yes")); - } - } - - #[allow(unused)] - pub fn refresh_profiles(&self) { - if let Some(window) = self.win.as_ref() { - log_if_err!(window.emit("verge://refresh-profiles-config", "yes")); - } - } -} diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 7c29e6f..b6f053d 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -1,4 +1,4 @@ -use super::{notice::Notice, ClashInfo}; +use crate::data::{ClashInfo, Data}; use crate::log_if_err; use crate::utils::{config, dirs}; use anyhow::{bail, Result}; @@ -15,7 +15,6 @@ use std::{ use tauri::api::process::{Command, CommandChild, CommandEvent}; use tokio::time::sleep; -static mut CLASH_CORE: &str = "clash"; const LOGS_QUEUE_LEN: usize = 100; #[derive(Debug)] @@ -23,39 +22,31 @@ pub struct Service { sidecar: Option, logs: Arc>>, - - #[allow(unused)] - service_mode: bool, } impl Service { pub fn new() -> Service { let queue = VecDeque::with_capacity(LOGS_QUEUE_LEN + 10); + Service { sidecar: None, logs: Arc::new(RwLock::new(queue)), - service_mode: false, } } - pub fn set_core(&mut self, clash_core: Option) { - unsafe { - CLASH_CORE = Box::leak(clash_core.unwrap_or("clash".into()).into_boxed_str()); - } - } - - #[allow(unused)] - pub fn set_mode(&mut self, enable: bool) { - self.service_mode = enable; - } - pub fn start(&mut self) -> Result<()> { - #[cfg(not(windows))] + #[cfg(not(target_os = "windows"))] self.start_clash_by_sidecar()?; - #[cfg(windows)] + #[cfg(target_os = "windows")] { - if !self.service_mode { + let enable = { + let data = Data::global(); + let verge = data.verge.lock(); + verge.enable_service_mode.clone().unwrap_or(false) + }; + + if !enable { return self.start_clash_by_sidecar(); } @@ -76,18 +67,24 @@ impl Service { } pub fn stop(&mut self) -> Result<()> { - #[cfg(not(windows))] + #[cfg(not(target_os = "windows"))] self.stop_clash_by_sidecar()?; - #[cfg(windows)] + #[cfg(target_os = "windows")] { - if !self.service_mode { - return self.stop_clash_by_sidecar(); - } + let _ = self.stop_clash_by_sidecar(); - tauri::async_runtime::spawn(async move { - log_if_err!(Self::stop_clash_by_service().await); - }); + let enable = { + let data = Data::global(); + let verge = data.verge.lock(); + verge.enable_service_mode.clone().unwrap_or(false) + }; + + if enable { + tauri::async_runtime::spawn(async move { + log_if_err!(Self::stop_clash_by_service().await); + }); + } } Ok(()) @@ -119,13 +116,19 @@ impl Service { /// start the clash sidecar fn start_clash_by_sidecar(&mut self) -> Result<()> { if self.sidecar.is_some() { - bail!("could not run clash sidecar twice"); + let sidecar = self.sidecar.take().unwrap(); + let _ = sidecar.kill(); } + let clash_core: String = { + let global = Data::global(); + let verge = global.verge.lock(); + verge.clash_core.clone().unwrap_or("clash".into()) + }; + let app_dir = dirs::app_home_dir(); let app_dir = app_dir.as_os_str().to_str().unwrap(); - let clash_core = unsafe { CLASH_CORE }; let cmd = Command::new_sidecar(clash_core)?; let (mut rx, cmd_child) = cmd.args(["-d", app_dir]).spawn()?; @@ -178,70 +181,70 @@ impl Service { Ok(()) } - /// update clash config - /// using PUT methods - pub fn set_config(&self, info: ClashInfo, config: Mapping, notice: Notice) -> Result<()> { - if !self.service_mode && self.sidecar.is_none() { - bail!("did not start sidecar"); + pub fn check_start(&mut self) -> Result<()> { + let global = Data::global(); + #[cfg(target_os = "windows")] + { + let verge = global.verge.lock(); + let service_mode = verge.enable_service_mode.unwrap_or(false); + + if !service_mode && self.sidecar.is_none() { + self.start()?; + } } + #[cfg(not(target_os = "windows"))] + if self.sidecar.is_none() { + self.start()?; + } + + Ok(()) + } + + /// update clash config + /// using PUT methods + pub async fn set_config(info: ClashInfo, config: Mapping) -> Result<()> { let temp_path = dirs::profiles_temp_path(); config::save_yaml(temp_path.clone(), &config, Some("# Clash Verge Temp File"))?; let (server, headers) = Self::clash_client_info(info)?; - tauri::async_runtime::spawn(async move { - let mut data = HashMap::new(); - data.insert("path", temp_path.as_os_str().to_str().unwrap()); + let mut data = HashMap::new(); + data.insert("path", temp_path.as_os_str().to_str().unwrap()); - // retry 5 times - for _ in 0..5 { - match reqwest::ClientBuilder::new().no_proxy().build() { - Ok(client) => { - let builder = client.put(&server).headers(headers.clone()).json(&data); - - match builder.send().await { - Ok(resp) => { - if resp.status() != 204 { - log::error!(target: "app", "failed to activate clash with status \"{}\"", resp.status()); - } - - notice.refresh_clash(); - - // do not retry - break; + // retry 5 times + for _ in 0..5 { + let headers = headers.clone(); + match reqwest::ClientBuilder::new().no_proxy().build() { + Ok(client) => { + let builder = client.put(&server).headers(headers).json(&data); + match builder.send().await { + Ok(resp) => match resp.status().as_u16() { + 204 => break, + // 配置有问题不重试 + 400 => bail!("failed to update clash config with status 400"), + status @ _ => { + log::error!(target: "app", "failed to activate clash with status \"{status}\""); } - Err(err) => log::error!(target: "app", "failed to activate for `{err}`"), - } + }, + Err(err) => log::error!(target: "app", "{err}"), } - Err(err) => log::error!(target: "app", "failed to activate for `{err}`"), } - sleep(Duration::from_millis(500)).await; + Err(err) => log::error!(target: "app", "{err}"), } - }); + sleep(Duration::from_millis(500)).await; + } Ok(()) } /// patch clash config - pub fn patch_config(&self, info: ClashInfo, config: Mapping, notice: Notice) -> Result<()> { - if !self.service_mode && self.sidecar.is_none() { - bail!("did not start sidecar"); - } - + pub async fn patch_config(info: ClashInfo, config: Mapping) -> Result<()> { let (server, headers) = Self::clash_client_info(info)?; - tauri::async_runtime::spawn(async move { - if let Ok(client) = reqwest::ClientBuilder::new().no_proxy().build() { - let builder = client.patch(&server).headers(headers.clone()).json(&config); - - match builder.send().await { - Ok(_) => notice.refresh_clash(), - Err(err) => log::error!(target: "app", "{err}"), - } - } - }); - + let client = reqwest::ClientBuilder::new().no_proxy().build()?; + let builder = client.patch(&server).headers(headers.clone()).json(&config); + builder.send().await?; Ok(()) } @@ -296,7 +299,7 @@ impl Drop for Service { /// ### Service Mode /// -#[cfg(windows)] +#[cfg(target_os = "windows")] pub mod win_service { use super::*; use anyhow::Context; @@ -453,7 +456,12 @@ pub mod win_service { sleep(Duration::from_secs(1)).await; } - let clash_core = unsafe { CLASH_CORE }; + let clash_core = { + let global = Data::global(); + let verge = global.verge.lock(); + verge.clash_core.clone().unwrap_or("clash".into()) + }; + let clash_bin = format!("{clash_core}.exe"); let bin_path = current_exe().unwrap().with_file_name(clash_bin); let bin_path = bin_path.as_os_str().to_str().unwrap(); diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index f52de55..b50ef97 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -1,17 +1,17 @@ -use super::{Clash, Verge}; -use crate::{log_if_err, utils::sysopt::SysProxyConfig}; +use crate::{data::*, log_if_err}; use anyhow::{bail, Result}; use auto_launch::{AutoLaunch, AutoLaunchBuilder}; use std::sync::Arc; +use sysproxy::Sysproxy; use tauri::{async_runtime::Mutex, utils::platform::current_exe}; pub struct Sysopt { /// current system proxy setting - cur_sysproxy: Option, + cur_sysproxy: Option, /// record the original system proxy /// recover it when exit - old_sysproxy: Option, + old_sysproxy: Option, /// helps to auto launch the app auto_launch: Option, @@ -20,6 +20,13 @@ pub struct Sysopt { guard_state: Arc>, } +#[cfg(target_os = "windows")] +static DEFAULT_BYPASS: &str = "localhost;127.*;192.168.*;"; +#[cfg(target_os = "linux")] +static DEFAULT_BYPASS: &str = "localhost,127.0.0.1/8,::1"; +#[cfg(target_os = "macos")] +static DEFAULT_BYPASS: &str = "127.0.0.1,localhost,"; + impl Sysopt { pub fn new() -> Sysopt { Sysopt { @@ -31,84 +38,105 @@ impl Sysopt { } /// init the sysproxy - pub fn init_sysproxy(&mut self, port: Option, verge: &Verge) { - if let Some(port) = port { - let enable = verge.enable_system_proxy.clone().unwrap_or(false); + pub fn init_sysproxy(&mut self) -> Result<()> { + let data = Data::global(); + let clash = data.clash.lock(); + let port = clash.info.port.clone(); - self.old_sysproxy = match SysProxyConfig::get_sys() { - Ok(proxy) => Some(proxy), - Err(_) => None, - }; + if port.is_none() { + bail!("clash port is none"); + } - let bypass = verge.system_proxy_bypass.clone(); - let sysproxy = SysProxyConfig::new(enable, port, bypass); + let verge = data.verge.lock(); - if enable { - if let Err(err) = sysproxy.set_sys() { - log::error!(target: "app", "failed to set system proxy for `{err}`"); - } - } + let enable = verge.enable_system_proxy.clone().unwrap_or(false); + let bypass = verge.system_proxy_bypass.clone(); + let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into()); - self.cur_sysproxy = Some(sysproxy); + let port = port.unwrap().parse::()?; + let host = String::from("127.0.0.1"); + + self.cur_sysproxy = Some(Sysproxy { + enable, + host, + port, + bypass, + }); + + if enable { + self.old_sysproxy = Sysproxy::get_system_proxy().map_or(None, |p| Some(p)); + self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?; } // launchs the system proxy guard self.guard_proxy(); + Ok(()) } /// update the system proxy - /// when the verge config is changed - pub fn update_sysproxy(&mut self, enable: Option, bypass: Option) -> Result<()> { - let sysproxy = self.cur_sysproxy.take(); - - if sysproxy.is_none() { - bail!("unhandle error for sysproxy is none"); + pub fn update_sysproxy(&mut self) -> Result<()> { + if self.cur_sysproxy.is_none() { + return self.init_sysproxy(); } - let mut sysproxy = sysproxy.unwrap(); + let data = Data::global(); + let verge = data.verge.lock(); - if let Some(enable) = enable { - sysproxy.enable = enable; - } + let enable = verge.enable_system_proxy.clone().unwrap_or(false); + let bypass = verge.system_proxy_bypass.clone(); + let bypass = bypass.unwrap_or(DEFAULT_BYPASS.into()); - if let Some(bypass) = bypass { - sysproxy.bypass = bypass; - } + let mut sysproxy = self.cur_sysproxy.take().unwrap(); + + sysproxy.enable = enable; + sysproxy.bypass = bypass; self.cur_sysproxy = Some(sysproxy); - - if self.cur_sysproxy.as_ref().unwrap().set_sys().is_err() { - bail!("failed to set system proxy"); - } + self.cur_sysproxy.as_ref().unwrap().set_system_proxy()?; Ok(()) } /// reset the sysproxy - pub fn reset_sysproxy(&mut self) { - if let Some(sysproxy) = self.old_sysproxy.take() { - // 如果原代理设置是开启的,且域名端口设置和当前的一致,就不恢复原设置 - // https://github.com/zzzgydi/clash-verge/issues/157 - if let Some(cur) = self.cur_sysproxy.as_ref() { - if sysproxy.enable && cur.server == sysproxy.server { - return; + pub fn reset_sysproxy(&mut self) -> Result<()> { + if self.cur_sysproxy.is_none() { + return Ok(()); + } + + let mut cur = self.cur_sysproxy.take().unwrap(); + + match self.old_sysproxy.take() { + Some(old) => { + // 如果原代理设置和当前的设置是一样的,需要关闭 + // 否则就恢复原代理设置 + if old.enable && old.host == cur.host && old.port == cur.port { + cur.enable = false; + cur.set_system_proxy()?; + } else { + old.set_system_proxy()?; } } - - match sysproxy.set_sys() { - Ok(_) => self.cur_sysproxy = None, - Err(_) => log::error!(target: "app", "failed to reset proxy"), + None => { + if cur.enable { + cur.enable = false; + cur.set_system_proxy()?; + } } } - } - /// get current proxy - pub fn get_sysproxy(&self) -> Result> { - Ok(self.cur_sysproxy.clone()) + Ok(()) } /// init the auto launch - pub fn init_launch(&mut self, enable: Option) -> Result<()> { + pub fn init_launch(&mut self) -> Result<()> { + let data = Data::global(); + let verge = data.verge.lock(); + let enable = verge.enable_auto_launch.clone().unwrap_or(false); + + if !enable { + return Ok(()); + } + let app_exe = current_exe().unwrap(); let app_exe = dunce::canonicalize(app_exe).unwrap(); let app_name = app_exe.file_stem().unwrap().to_str().unwrap(); @@ -125,25 +153,23 @@ impl Sysopt { .set_app_path(app_path) .build()?; - if let Some(enable) = enable { - // fix issue #26 - if enable { - auto.enable()?; - } - } - + // fix issue #26 + auto.enable()?; self.auto_launch = Some(auto); Ok(()) } /// update the startup - pub fn update_launch(&mut self, enable: Option) -> Result<()> { - if enable.is_none() { - return Ok(()); + pub fn update_launch(&mut self) -> Result<()> { + if self.auto_launch.is_none() { + return self.init_launch(); } - let enable = enable.unwrap(); + let data = Data::global(); + let verge = data.verge.lock(); + let enable = verge.enable_auto_launch.clone().unwrap_or(false); + let auto_launch = self.auto_launch.as_ref().unwrap(); match enable { @@ -176,35 +202,42 @@ impl Sysopt { loop { sleep(Duration::from_secs(wait_secs)).await; - let verge = Verge::new(); + let global = Data::global(); + let verge = global.verge.lock(); - let enable_proxy = verge.enable_system_proxy.unwrap_or(false); - let enable_guard = verge.enable_proxy_guard.unwrap_or(false); - let guard_duration = verge.proxy_guard_duration.unwrap_or(10); + let enable = verge.enable_system_proxy.clone().unwrap_or(false); + let guard = verge.enable_proxy_guard.clone().unwrap_or(false); + let guard_duration = verge.proxy_guard_duration.clone().unwrap_or(10); + let bypass = verge.system_proxy_bypass.clone(); + drop(verge); + + // stop loop + if !enable || !guard { + break; + } // update duration wait_secs = guard_duration; - // stop loop - if !enable_guard || !enable_proxy { - break; - } + let clash = global.clash.lock(); + let port = clash.info.port.clone(); + let port = port.unwrap_or("".into()).parse::(); + drop(clash); log::debug!(target: "app", "try to guard the system proxy"); - let clash = Clash::new(); + match port { + Ok(port) => { + let sysproxy = Sysproxy { + enable: true, + host: "127.0.0.1".into(), + port, + bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()), + }; - match &clash.info.port { - Some(port) => { - let bypass = verge.system_proxy_bypass.clone(); - let sysproxy = SysProxyConfig::new(true, port.clone(), bypass); - - log_if_err!(sysproxy.set_sys()); - } - None => { - let status = &clash.info.status; - log::error!(target: "app", "failed to parse clash port with status {status}") + log_if_err!(sysproxy.set_system_proxy()); } + Err(_) => log::error!(target: "app", "failed to parse clash port"), } } diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs index 181c0d5..3728b76 100644 --- a/src-tauri/src/core/timer.rs +++ b/src-tauri/src/core/timer.rs @@ -1,7 +1,7 @@ use super::Core; -use crate::log_if_err; use crate::utils::help::get_now; -use anyhow::{bail, Context, Result}; +use crate::{data::Data, log_if_err}; +use anyhow::{Context, Result}; use delay_timer::prelude::{DelayTimer, DelayTimerBuilder, TaskBuilder}; use std::collections::HashMap; @@ -16,9 +16,6 @@ pub struct Timer { /// increment id timer_count: TaskID, - - /// save the instance of the app - core: Option, } impl Timer { @@ -27,20 +24,11 @@ impl Timer { delay_timer: DelayTimerBuilder::default().build(), timer_map: HashMap::new(), timer_count: 1, - core: None, } } - pub fn set_core(&mut self, core: Core) { - self.core = Some(core); - } - /// Correctly update all cron tasks pub fn refresh(&mut self) -> Result<()> { - if self.core.is_none() { - bail!("unhandle error for core is none"); - } - let diff_map = self.gen_diff(); for (uid, diff) in diff_map.into_iter() { @@ -69,7 +57,9 @@ impl Timer { self.refresh()?; let cur_timestamp = get_now(); // seconds - let profiles = self.core.as_ref().unwrap().profiles.lock(); + + let global = Data::global(); + let profiles = global.profiles.lock(); profiles .get_items() @@ -94,7 +84,8 @@ impl Timer { /// generate a uid -> update_interval map fn gen_map(&self) -> HashMap { - let profiles = self.core.as_ref().unwrap().profiles.lock(); + let global = Data::global(); + let profiles = global.profiles.lock(); let mut new_map = HashMap::new(); @@ -148,14 +139,14 @@ impl Timer { /// add a cron task fn add_task(&self, uid: String, tid: TaskID, minutes: u64) -> Result<()> { - let core = self.core.clone().unwrap(); + let core = Core::global(); let task = TaskBuilder::default() .set_task_id(tid) .set_maximum_parallel_runnable_num(1) .set_frequency_repeated_by_minutes(minutes) // .set_frequency_repeated_by_seconds(minutes) // for test - .spawn_async_routine(move || Self::async_task(core.clone(), uid.clone())) + .spawn_async_routine(move || Self::async_task(core.to_owned(), uid.to_owned())) .context("failed to create timer task")?; self diff --git a/src-tauri/src/core/clash.rs b/src-tauri/src/data/clash.rs similarity index 99% rename from src-tauri/src/core/clash.rs rename to src-tauri/src/data/clash.rs index b3a09dc..627389a 100644 --- a/src-tauri/src/core/clash.rs +++ b/src-tauri/src/data/clash.rs @@ -106,6 +106,7 @@ impl ClashInfo { } } +#[derive(Debug)] pub struct Clash { /// maintain the clash config pub config: Mapping, diff --git a/src-tauri/src/data/mod.rs b/src-tauri/src/data/mod.rs new file mode 100644 index 0000000..b5f79cb --- /dev/null +++ b/src-tauri/src/data/mod.rs @@ -0,0 +1,32 @@ +mod clash; +mod prfitem; +mod profiles; +mod verge; + +pub use self::clash::*; +pub use self::prfitem::*; +pub use self::profiles::*; +pub use self::verge::*; + +use once_cell::sync::Lazy; +use parking_lot::Mutex; +use std::sync::Arc; + +static DATA: Lazy = Lazy::new(|| Data { + clash: Arc::new(Mutex::new(Clash::new())), + verge: Arc::new(Mutex::new(Verge::new())), + profiles: Arc::new(Mutex::new(Profiles::new())), +}); + +#[derive(Debug, Clone)] +pub struct Data { + pub clash: Arc>, + pub verge: Arc>, + pub profiles: Arc>, +} + +impl Data { + pub fn global() -> Data { + DATA.clone() + } +} diff --git a/src-tauri/src/core/prfitem.rs b/src-tauri/src/data/prfitem.rs similarity index 100% rename from src-tauri/src/core/prfitem.rs rename to src-tauri/src/data/prfitem.rs diff --git a/src-tauri/src/core/profiles.rs b/src-tauri/src/data/profiles.rs similarity index 100% rename from src-tauri/src/core/profiles.rs rename to src-tauri/src/data/profiles.rs diff --git a/src-tauri/src/core/verge.rs b/src-tauri/src/data/verge.rs similarity index 98% rename from src-tauri/src/core/verge.rs rename to src-tauri/src/data/verge.rs index d3d517a..98741db 100644 --- a/src-tauri/src/core/verge.rs +++ b/src-tauri/src/data/verge.rs @@ -12,7 +12,7 @@ pub struct Verge { // i18n pub language: Option, - /// `light` or `dark` + /// `light` or `dark` or `system` pub theme_mode: Option, /// enable blur mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index b5e53b3..e8cdb61 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -6,15 +6,16 @@ mod cmds; mod config; mod core; +mod data; mod utils; use crate::{ - core::Verge, + core::Core, + data::{Data, Verge}, utils::{resolve, server}, }; use tauri::{ api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, - WindowEvent, }; fn main() -> std::io::Result<()> { @@ -65,14 +66,15 @@ fn main() -> std::io::Result<()> { } mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => { let mode = &mode[0..mode.len() - 5]; - let core = app_handle.state::(); - crate::log_if_err!(core.update_mode(app_handle, mode)); + let core = Core::global(); + crate::log_if_err!(core.update_mode(mode)); } "system_proxy" => { - let core = app_handle.state::(); + let core = Core::global(); let new_value = { - let verge = core.verge.lock(); + let global = Data::global(); + let verge = global.verge.lock(); !verge.enable_system_proxy.clone().unwrap_or(false) }; @@ -81,13 +83,14 @@ fn main() -> std::io::Result<()> { ..Verge::default() }; - crate::log_if_err!(core.patch_verge(patch, app_handle)); + crate::log_if_err!(core.patch_verge(patch)); } "tun_mode" => { - let core = app_handle.state::(); + let core = Core::global(); let new_value = { - let verge = core.verge.lock(); + let global = Data::global(); + let verge = global.verge.lock(); !verge.enable_tun_mode.clone().unwrap_or(false) }; @@ -96,17 +99,17 @@ fn main() -> std::io::Result<()> { ..Verge::default() }; - crate::log_if_err!(core.patch_verge(patch, app_handle)); + crate::log_if_err!(core.patch_verge(patch)); } "restart_clash" => { - let core = app_handle.state::(); + let core = Core::global(); crate::log_if_err!(core.restart_clash()); } "restart_app" => { api::process::restart(&app_handle.env()); } "quit" => { - resolve::resolve_reset(app_handle); + resolve::resolve_reset(); app_handle.exit(0); } _ => {} @@ -120,7 +123,6 @@ fn main() -> std::io::Result<()> { .invoke_handler(tauri::generate_handler![ // common cmds::get_sys_proxy, - cmds::get_cur_proxy, cmds::open_app_dir, cmds::open_logs_dir, cmds::open_web_url, @@ -183,24 +185,24 @@ fn main() -> std::io::Result<()> { let app_handle = app.app_handle(); ctrlc::set_handler(move || { - resolve::resolve_reset(&app_handle); + resolve::resolve_reset(); app_handle.exit(0); }) .expect("error when exiting."); - app.run(|app_handle, e| match e { + app.run(|_, e| match e { tauri::RunEvent::ExitRequested { api, .. } => { api.prevent_exit(); } tauri::RunEvent::Exit => { - resolve::resolve_reset(app_handle); + resolve::resolve_reset(); api::process::kill_children(); } #[cfg(target_os = "macos")] tauri::RunEvent::WindowEvent { label, event, .. } => { if label == "main" { match event { - WindowEvent::CloseRequested { api, .. } => { + tauri::WindowEvent::CloseRequested { api, .. } => { api.prevent_close(); app_handle.get_window("main").map(|win| { let _ = win.hide(); diff --git a/src-tauri/src/utils/help.rs b/src-tauri/src/utils/help.rs index 3d23a76..2fbe80a 100644 --- a/src-tauri/src/utils/help.rs +++ b/src-tauri/src/utils/help.rs @@ -58,22 +58,20 @@ pub fn open_file(path: PathBuf) -> Result<()> { .arg(path) .spawn() { - bail!(format!("failed to open file by VScode for `{err}`")); + bail!("failed to open file by VScode for `{err}`"); } } #[cfg(not(target_os = "windows"))] if let Err(err) = Command::new(code).arg(path).spawn() { - bail!(format!("failed to open file by VScode for `{err}`")); + bail!("failed to open file by VScode for `{err}`"); } return Ok(()); } - match open::that(path) { - Ok(_) => Ok(()), - Err(err) => bail!(format!("failed to open file for `{err}`")), - } + open::that(path)?; + Ok(()) } #[macro_export] diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index f1af3a3..e6c37a8 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -4,6 +4,5 @@ pub mod help; pub mod init; pub mod resolve; pub mod server; -pub mod sysopt; pub mod tmpl; mod winhelp; diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index 9c5b405..6042640 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -1,4 +1,4 @@ -use crate::{core::Core, utils::init, utils::server}; +use crate::{core::Core, data::Data, utils::init, utils::server}; use tauri::{App, AppHandle, Manager}; /// handle something when start app @@ -6,32 +6,27 @@ pub fn resolve_setup(app: &App) { // init app config init::init_app(app.package_info()); - // init core - // should be initialized after init_app fix #122 - let core = Core::new(); - { - let verge = core.verge.lock(); + let global = Data::global(); + let verge = global.verge.lock(); let singleton = verge.app_singleton_port.clone(); // setup a simple http server for singleton server::embed_server(&app.handle(), singleton); } - core.set_win(app.get_window("main")); + // core should be initialized after init_app fix #122 + let mut core = Core::global(); core.init(app.app_handle()); - // fix #122 - app.manage(core); - resolve_window(app); } /// reset system proxy -pub fn resolve_reset(app_handle: &AppHandle) { - let core = app_handle.state::(); +pub fn resolve_reset() { + let core = Core::global(); let mut sysopt = core.sysopt.lock(); - sysopt.reset_sysproxy(); + crate::log_if_err!(sysopt.reset_sysproxy()); drop(sysopt); let mut service = core.service.lock(); diff --git a/src-tauri/src/utils/tmpl.rs b/src-tauri/src/utils/tmpl.rs index bf7acee..dc311f6 100644 --- a/src-tauri/src/utils/tmpl.rs +++ b/src-tauri/src/utils/tmpl.rs @@ -29,7 +29,6 @@ enable_self_startup: false enable_system_proxy: false enable_proxy_guard: false proxy_guard_duration: 10 -system_proxy_bypass: localhost;127.*;10.*;192.168.*; "; /// template for new a profile item @@ -60,7 +59,7 @@ append-proxy-groups: "; /// enhanced profile -pub const ITEM_SCRIPT: &str = "// Should define the `main` function +pub const ITEM_SCRIPT: &str = "// Define the `main` function // The argument to this function is the clash config // or the result of the previous handler // so you should return the config after processing