feat: macos system tray addition rate display

This commit is contained in:
huzibaca 2024-12-25 02:11:07 +08:00
parent 2d2521e434
commit fb41c915cc
No known key found for this signature in database
GPG Key ID: D4364EE4851DC302
13 changed files with 611 additions and 334 deletions

528
src-tauri/Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "addr2line"
version = "0.24.2"
@ -85,12 +91,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "aligned-vec"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
[[package]]
name = "alloc-no-stdlib"
version = "2.0.4"
@ -133,6 +133,15 @@ version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "arbitrary"
version = "1.4.1"
@ -150,7 +159,7 @@ checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4"
dependencies = [
"clipboard-win",
"core-graphics 0.23.2",
"image",
"image 0.25.5",
"log",
"objc2",
"objc2-app-kit",
@ -166,17 +175,6 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "arg_enum_proc_macro"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "arrayvec"
version = "0.7.6"
@ -495,29 +493,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "av1-grain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf"
dependencies = [
"anyhow",
"arrayvec",
"log",
"nom 7.1.3",
"num-rational",
"v_frame",
]
[[package]]
name = "avif-serialize"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62"
dependencies = [
"arrayvec",
]
[[package]]
name = "axum"
version = "0.6.20"
@ -617,12 +592,6 @@ dependencies = [
"serde",
]
[[package]]
name = "bitstream-io"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2"
[[package]]
name = "block"
version = "0.1.6"
@ -725,7 +694,7 @@ dependencies = [
"static_assertions",
"tap",
"thin-vec",
"thiserror 2.0.3",
"thiserror 2.0.9",
"time",
]
@ -829,12 +798,6 @@ dependencies = [
"alloc-stdlib",
]
[[package]]
name = "built"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b"
[[package]]
name = "bumpalo"
version = "3.16.0"
@ -875,9 +838,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
dependencies = [
"serde",
]
@ -1058,8 +1021,10 @@ dependencies = [
"delay_timer",
"dirs 5.0.1",
"dunce",
"futures",
"getrandom 0.2.15",
"image",
"image 0.24.9",
"imageproc",
"log",
"log4rs",
"nanoid",
@ -1072,6 +1037,7 @@ dependencies = [
"reqwest",
"reqwest_dav",
"runas",
"rusttype",
"serde",
"serde_json",
"serde_yaml",
@ -1092,6 +1058,7 @@ dependencies = [
"tauri-plugin-updater",
"tauri-plugin-window-state",
"tokio",
"tokio-tungstenite 0.26.1",
"url",
"users",
"warp",
@ -1240,6 +1207,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "conv"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
dependencies = [
"custom_derive",
]
[[package]]
name = "convert_case"
version = "0.4.0"
@ -1471,6 +1447,12 @@ dependencies = [
"cipher",
]
[[package]]
name = "custom_derive"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
[[package]]
name = "darling"
version = "0.20.10"
@ -3173,6 +3155,24 @@ dependencies = [
"icu_properties",
]
[[package]]
name = "image"
version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"exr",
"gif",
"jpeg-decoder",
"num-traits",
"png",
"qoi",
"tiff",
]
[[package]]
name = "image"
version = "0.25.5"
@ -3181,37 +3181,29 @@ checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
dependencies = [
"bytemuck",
"byteorder-lite",
"color_quant",
"exr",
"gif",
"image-webp",
"num-traits",
"png",
"qoi",
"ravif",
"rayon",
"rgb",
"tiff",
"zune-core",
"zune-jpeg",
]
[[package]]
name = "image-webp"
version = "0.2.0"
name = "imageproc"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f"
checksum = "b6aee993351d466301a29655d628bfc6f5a35a0d062b6160ca0808f425805fd7"
dependencies = [
"byteorder-lite",
"quick-error",
"approx",
"conv",
"image 0.24.9",
"itertools 0.10.5",
"nalgebra",
"num",
"rand 0.7.3",
"rand_distr",
"rayon",
"rusttype",
]
[[package]]
name = "imgref"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408"
[[package]]
name = "indexmap"
version = "1.9.3"
@ -3277,17 +3269,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "interpolate_name"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "intrusive-collections"
version = "0.9.7"
@ -3344,6 +3325,15 @@ dependencies = [
"once_cell",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -3433,6 +3423,9 @@ name = "jpeg-decoder"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
dependencies = [
"rayon",
]
[[package]]
name = "js-sys"
@ -3531,16 +3524,6 @@ version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "libfuzzer-sys"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "libloading"
version = "0.7.4"
@ -3661,15 +3644,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "loop9"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
dependencies = [
"imgref",
]
[[package]]
name = "lru"
version = "0.7.8"
@ -3753,13 +3727,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "maybe-rayon"
version = "0.1.1"
name = "matrixmultiply"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
dependencies = [
"cfg-if",
"rayon",
"autocfg",
"rawpointer",
]
[[package]]
@ -3890,6 +3864,21 @@ dependencies = [
"version_check",
]
[[package]]
name = "nalgebra"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb2d0de08694bed883320212c18ee3008576bfe8c306f4c3c4a58b4876998be"
dependencies = [
"approx",
"matrixmultiply",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nanoid"
version = "0.4.0"
@ -4042,12 +4031,6 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "noop_proc_macro"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "notify-rust"
version = "4.11.3"
@ -4080,6 +4063,20 @@ dependencies = [
"winapi",
]
[[package]]
name = "num"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@ -4091,6 +4088,15 @@ dependencies = [
"serde",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@ -4108,17 +4114,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "num-integer"
version = "0.1.46"
@ -4128,6 +4123,17 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
@ -4563,6 +4569,15 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owned_ttf_parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb"
dependencies = [
"ttf-parser",
]
[[package]]
name = "pango"
version = "0.18.3"
@ -5068,25 +5083,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "profiling"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
"syn 2.0.90",
]
[[package]]
name = "prost"
version = "0.12.6"
@ -5174,7 +5170,7 @@ dependencies = [
"rustc-hash",
"rustls",
"socket2 0.5.7",
"thiserror 2.0.3",
"thiserror 2.0.9",
"tokio",
"tracing",
]
@ -5193,7 +5189,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.3",
"thiserror 2.0.9",
"tinyvec",
"tracing",
"web-time",
@ -5285,6 +5281,15 @@ dependencies = [
"getrandom 0.2.15",
]
[[package]]
name = "rand_distr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
dependencies = [
"rand 0.7.3",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
@ -5303,56 +5308,6 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rav1e"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9"
dependencies = [
"arbitrary",
"arg_enum_proc_macro",
"arrayvec",
"av1-grain",
"bitstream-io",
"built",
"cfg-if",
"interpolate_name",
"itertools 0.12.1",
"libc",
"libfuzzer-sys",
"log",
"maybe-rayon",
"new_debug_unreachable",
"noop_proc_macro",
"num-derive 0.4.2",
"num-traits",
"once_cell",
"paste",
"profiling",
"rand 0.8.5",
"rand_chacha 0.3.1",
"simd_helpers",
"system-deps",
"thiserror 1.0.69",
"v_frame",
"wasm-bindgen",
]
[[package]]
name = "ravif"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6"
dependencies = [
"avif-serialize",
"imgref",
"loop9",
"quick-error",
"rav1e",
"rayon",
"rgb",
]
[[package]]
name = "raw-window-handle"
version = "0.5.2"
@ -5365,6 +5320,12 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon"
version = "1.10.0"
@ -5552,12 +5513,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "rgb"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
[[package]]
name = "ring"
version = "0.17.8"
@ -5712,6 +5667,16 @@ dependencies = [
"untrusted",
]
[[package]]
name = "rusttype"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff8374aa04134254b7995b63ad3dc41c7f7236f69528b28553da7d72efaa967"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
]
[[package]]
name = "rustversion"
version = "1.0.18"
@ -5730,6 +5695,15 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
@ -6144,21 +6118,25 @@ dependencies = [
"libc",
]
[[package]]
name = "simba"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f3fd720c48c53cace224ae62bef1bbff363a70c68c4802a78b5cc6159618176"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simd_helpers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
dependencies = [
"quote",
]
[[package]]
name = "siphasher"
version = "0.3.11"
@ -6539,7 +6517,7 @@ dependencies = [
"heck 0.5.0",
"http 1.1.0",
"http-range",
"image",
"image 0.25.5",
"jni",
"libc",
"log",
@ -6562,7 +6540,7 @@ dependencies = [
"tauri-runtime",
"tauri-runtime-wry",
"tauri-utils",
"thiserror 2.0.3",
"thiserror 2.0.9",
"tokio",
"tracing",
"tray-icon",
@ -6616,7 +6594,7 @@ dependencies = [
"sha2 0.10.8",
"syn 2.0.90",
"tauri-utils",
"thiserror 2.0.3",
"thiserror 2.0.9",
"time",
"url",
"uuid",
@ -6665,7 +6643,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
]
[[package]]
@ -6680,7 +6658,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
]
[[package]]
@ -6696,7 +6674,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-utils",
"thiserror 2.0.3",
"thiserror 2.0.9",
"tracing",
"url",
"windows-registry 0.3.0",
@ -6744,7 +6722,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-plugin-fs",
"thiserror 2.0.3",
"thiserror 2.0.9",
"url",
]
@ -6765,7 +6743,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-utils",
"thiserror 2.0.3",
"thiserror 2.0.9",
"toml 0.8.19",
"url",
"uuid",
@ -6783,7 +6761,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
]
[[package]]
@ -6800,7 +6778,7 @@ dependencies = [
"serde_repr",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
"time",
"url",
]
@ -6832,7 +6810,7 @@ dependencies = [
"shared_child",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
"tokio",
]
@ -6858,7 +6836,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tempfile",
"thiserror 2.0.3",
"thiserror 2.0.9",
"time",
"tokio",
"url",
@ -6878,7 +6856,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.3",
"thiserror 2.0.9",
]
[[package]]
@ -6895,7 +6873,7 @@ dependencies = [
"serde",
"serde_json",
"tauri-utils",
"thiserror 2.0.3",
"thiserror 2.0.9",
"url",
"windows 0.58.0",
]
@ -6956,7 +6934,7 @@ dependencies = [
"serde_json",
"serde_with",
"swift-rs",
"thiserror 2.0.3",
"thiserror 2.0.9",
"toml 0.8.19",
"url",
"urlpattern",
@ -7047,7 +7025,7 @@ dependencies = [
"libc",
"log",
"memmem",
"num-derive 0.3.3",
"num-derive",
"num-traits",
"ordered-float",
"regex",
@ -7086,11 +7064,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.3"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
dependencies = [
"thiserror-impl 2.0.3",
"thiserror-impl 2.0.9",
]
[[package]]
@ -7106,9 +7084,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
version = "2.0.3"
version = "2.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
dependencies = [
"proc-macro2",
"quote",
@ -7295,7 +7273,19 @@ dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite",
"tungstenite 0.21.0",
]
[[package]]
name = "tokio-tungstenite"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4bf6fecd69fcdede0ec680aaf474cdab988f9de6bc73d3758f0160e3b7025a"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.26.1",
]
[[package]]
@ -7586,6 +7576,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ttf-parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]]
name = "tungstenite"
version = "0.21.0"
@ -7605,6 +7601,24 @@ dependencies = [
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413083a99c579593656008130e29255e54dcaae495be556cc26888f211648c24"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 1.1.0",
"httparse",
"log",
"rand 0.8.5",
"sha1",
"thiserror 2.0.9",
"utf-8",
]
[[package]]
name = "typeid"
version = "1.0.2"
@ -7801,17 +7815,6 @@ dependencies = [
"serde",
]
[[package]]
name = "v_frame"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b"
dependencies = [
"aligned-vec",
"num-traits",
"wasm-bindgen",
]
[[package]]
name = "valuable"
version = "0.1.0"
@ -7913,7 +7916,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-tungstenite",
"tokio-tungstenite 0.21.0",
"tokio-util",
"tower-service",
"tracing",
@ -8198,6 +8201,16 @@ dependencies = [
"rustix 0.38.41",
]
[[package]]
name = "wide"
version = "0.7.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58e6db2670d2be78525979e9a5f9c69d296fd7d670549fe9ebf70f8708cb5019"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -9141,12 +9154,6 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
[[package]]
name = "zune-inflate"
version = "0.2.54"
@ -9156,15 +9163,6 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "zune-jpeg"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768"
dependencies = [
"zune-core",
]
[[package]]
name = "zvariant"
version = "4.2.0"

View File

@ -36,7 +36,9 @@ tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", rev = "3d748b5" }
image = "0.25.5"
image = "0.24"
imageproc = "0.23"
rusttype = "0.9"
tauri = { version = "2.1.1", features = [
"protocol-asset",
"devtools",
@ -59,6 +61,8 @@ reqwest_dav = "0.1.14"
aes-gcm = { version = "0.10.3", features = ["std"] }
base64 = "0.22.1"
getrandom = "0.2"
tokio-tungstenite = "0.26.1"
futures = "0.3"
[target.'cfg(windows)'.dependencies]
runas = "=1.2.0"

Binary file not shown.

View File

@ -73,7 +73,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult {
match CoreManager::global().update_config().await {
Ok(_) => {
handle::Handle::refresh_clash();
let _ = handle::Handle::update_systray_tooltip();
let _ = tray::Tray::global().update_tooltip();
Config::profiles().apply();
wrap_err!(Config::profiles().data().save_file())?;
Ok(())

View File

@ -156,17 +156,20 @@ impl IClashTemp {
}
pub fn guard_mixed_port(config: &Mapping) -> u16 {
let mut port = config
.get("mixed-port")
let raw_value = config.get("mixed-port");
let mut port = raw_value
.and_then(|value| match value {
Value::String(val_str) => val_str.parse().ok(),
Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
_ => None,
})
.unwrap_or(7897);
if port == 0 {
port = 7897;
}
port
}

View File

@ -123,6 +123,12 @@ pub fn parse_check_output(log: String) -> String {
log
}
pub fn get_traffic_ws_url() -> Result<String> {
let (url, _) = clash_client_info()?;
let ws_url = url.replace("http://", "ws://") + "/traffic";
Ok(ws_url)
}
#[test]
fn test_parse_check_output() {
let str1 = r#"xxxx\n time="2022-11-18T20:42:58+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'""#;

View File

@ -76,7 +76,6 @@ impl CoreManager {
service::stop_core_by_service().await?;
}
*running = false;
Ok(())
}
@ -96,6 +95,7 @@ impl CoreManager {
service::run_core_by_service(&config_path).await?;
*running = true;
}
Ok(())
}

View File

@ -1,6 +1,4 @@
use super::tray::Tray;
use crate::log_err;
use anyhow::Result;
use once_cell::sync::OnceCell;
use parking_lot::RwLock;
use std::sync::Arc;
@ -65,27 +63,6 @@ impl Handle {
}
}
/// update the system tray state
pub fn update_systray_part() -> Result<()> {
Tray::update_part()?;
Ok(())
}
pub fn update_systray_menu() -> Result<()> {
Tray::update_menu()?;
Ok(())
}
pub fn update_systray_icon() -> Result<()> {
Tray::update_icon()?;
Ok(())
}
pub fn update_systray_tooltip() -> Result<()> {
Tray::update_tooltip()?;
Ok(())
}
pub fn set_is_exiting(&self) {
let mut is_exiting = self.is_exiting.write();
*is_exiting = true;

View File

@ -1,3 +1,7 @@
pub mod speed_rate;
use speed_rate::Rate;
pub use speed_rate::{SpeedRate, Traffic};
use crate::utils::dirs;
use crate::{
cmds,
@ -6,6 +10,10 @@ use crate::{
utils::resolve::{self, VERSION},
};
use anyhow::Result;
use futures::StreamExt;
use once_cell::sync::OnceCell;
use parking_lot::{Mutex, RwLock};
use std::sync::Arc;
use tauri::AppHandle;
use tauri::{
menu::CheckMenuItem,
@ -15,12 +23,33 @@ use tauri::{
menu::{MenuEvent, MenuItem, PredefinedMenuItem, Submenu},
Wry,
};
use tokio::sync::broadcast;
use super::handle;
pub struct Tray {}
pub struct Tray {
pub speed_rate: Arc<Mutex<Option<SpeedRate>>>,
#[cfg(target_os = "macos")]
shutdown_tx: Arc<RwLock<Option<broadcast::Sender<()>>>>,
}
impl Tray {
pub fn create_systray() -> Result<()> {
pub fn global() -> &'static Tray {
static TRAY: OnceCell<Tray> = OnceCell::new();
TRAY.get_or_init(|| Tray {
speed_rate: Arc::new(Mutex::new(None)),
#[cfg(target_os = "macos")]
shutdown_tx: Arc::new(RwLock::new(None)),
})
}
pub fn init(&self) -> Result<()> {
let mut speed_rate = self.speed_rate.lock();
*speed_rate = Some(SpeedRate::new());
Ok(())
}
pub fn create_systray(&self) -> Result<()> {
let app_handle = handle::Handle::global().app_handle().unwrap();
let tray_incon_id = TrayIconId::new("main");
let tray = app_handle.tray_by_id(&tray_incon_id).unwrap();
@ -64,7 +93,7 @@ impl Tray {
}
/// 更新托盘菜单
pub fn update_menu() -> Result<()> {
pub fn update_menu(&self) -> Result<()> {
let app_handle = handle::Handle::global().app_handle().unwrap();
let verge = Config::verge().latest().clone();
let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
@ -91,7 +120,7 @@ impl Tray {
}
/// 更新托盘图标
pub fn update_icon() -> Result<()> {
pub fn update_icon(&self, rate: Option<Rate>) -> Result<()> {
let app_handle = handle::Handle::global().app_handle().unwrap();
let verge = Config::verge().latest().clone();
let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
@ -109,12 +138,12 @@ impl Tray {
let icon_bytes = if *system_proxy && !*tun_mode {
#[cfg(target_os = "macos")]
let mut icon = match tray_icon.as_str() {
"colorful" => include_bytes!("../../icons/tray-icon-sys.ico").to_vec(),
_ => include_bytes!("../../icons/tray-icon-sys-mono.ico").to_vec(),
"colorful" => include_bytes!("../../../icons/tray-icon-sys.ico").to_vec(),
_ => include_bytes!("../../../icons/tray-icon-sys-mono.ico").to_vec(),
};
#[cfg(not(target_os = "macos"))]
let mut icon = include_bytes!("../../icons/tray-icon-sys.ico").to_vec();
let mut icon = include_bytes!("../../../icons/tray-icon-sys.ico").to_vec();
if *sysproxy_tray_icon {
let icon_dir_path = dirs::app_home_dir()?.join("icons");
let png_path = icon_dir_path.join("sysproxy.png");
@ -129,8 +158,8 @@ impl Tray {
} else if *tun_mode {
#[cfg(target_os = "macos")]
let mut icon = match tray_icon.as_str() {
"colorful" => include_bytes!("../../icons/tray-icon-tun.ico").to_vec(),
_ => include_bytes!("../../icons/tray-icon-tun-mono.ico").to_vec(),
"colorful" => include_bytes!("../../../icons/tray-icon-tun.ico").to_vec(),
_ => include_bytes!("../../../icons/tray-icon-tun-mono.ico").to_vec(),
};
#[cfg(not(target_os = "macos"))]
@ -149,8 +178,8 @@ impl Tray {
} else {
#[cfg(target_os = "macos")]
let mut icon = match tray_icon.as_str() {
"colorful" => include_bytes!("../../icons/tray-icon.ico").to_vec(),
_ => include_bytes!("../../icons/tray-icon-mono.ico").to_vec(),
"colorful" => include_bytes!("../../../icons/tray-icon.ico").to_vec(),
_ => include_bytes!("../../../icons/tray-icon-mono.ico").to_vec(),
};
#[cfg(not(target_os = "macos"))]
@ -172,6 +201,14 @@ impl Tray {
{
let is_template =
crate::utils::help::is_monochrome_image_from_bytes(&icon_bytes).unwrap_or(false);
// 如果rate为None获取当前速率
let rate = rate.or_else(|| {
self.speed_rate
.lock()
.as_ref()
.and_then(|speed_rate| speed_rate.get_curent_rate())
});
let icon_bytes = SpeedRate::add_speed_text(icon_bytes, rate)?;
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?));
let _ = tray.set_icon_as_template(is_template);
}
@ -183,7 +220,7 @@ impl Tray {
}
/// 更新托盘提示
pub fn update_tooltip() -> Result<()> {
pub fn update_tooltip(&self) -> Result<()> {
let app_handle = handle::Handle::global().app_handle().unwrap();
let use_zh = { Config::verge().latest().language == Some("zh".into()) };
let version = VERSION.get().unwrap();
@ -223,12 +260,55 @@ impl Tray {
Ok(())
}
pub fn update_part() -> Result<()> {
Self::update_menu()?;
Self::update_icon()?;
Self::update_tooltip()?;
pub fn update_part(&self) -> Result<()> {
self.update_menu()?;
self.update_icon(None)?;
self.update_tooltip()?;
Ok(())
}
/// 订阅流量数据
#[cfg(target_os = "macos")]
pub async fn subscribe_traffic(&self) -> Result<()> {
log::info!(target: "app", "subscribe traffic");
let (shutdown_tx, shutdown_rx) = broadcast::channel(1);
*self.shutdown_tx.write() = Some(shutdown_tx);
let speed_rate = Arc::clone(&self.speed_rate);
tauri::async_runtime::spawn(async move {
let mut shutdown = shutdown_rx;
if let Ok(mut stream) = Traffic::get_traffic_stream().await {
loop {
tokio::select! {
Some(traffic) = stream.next() => {
if let Ok(traffic) = traffic {
let guard = speed_rate.lock();
if let Some(sr) = guard.as_ref() {
if let Some(rate) = sr.update_and_check_changed(traffic.up, traffic.down) {
let _ = Tray::global().update_icon(Some(rate));
}
}
}
}
_ = shutdown.recv() => break,
}
}
}
});
Ok(())
}
/// 取消订阅 traffic 数据
#[cfg(target_os = "macos")]
#[allow(unused)]
pub fn unsubscribe_traffic(&self) {
log::info!(target: "app", "unsubscribe traffic");
if let Some(tx) = self.shutdown_tx.write().take() {
drop(tx); // 发送端被丢弃时会自动发送关闭信号
}
}
}
fn create_tray_menu(

View File

@ -0,0 +1,189 @@
use crate::core::clash_api::get_traffic_ws_url;
use crate::utils::help::format_bytes_speed;
use anyhow::Result;
use futures::Stream;
use image::{ImageBuffer, Rgba};
use imageproc::drawing::draw_text_mut;
use parking_lot::Mutex;
use rusttype::{Font, Scale};
use std::io::Cursor;
use std::sync::Arc;
use tokio_tungstenite::tungstenite::Message;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Rate {
pub up: u64,
pub down: u64,
}
#[derive(Debug, Clone)]
pub struct SpeedRate {
rate: Arc<Mutex<(Rate, Rate)>>,
}
impl SpeedRate {
pub fn new() -> Self {
Self {
rate: Arc::new(Mutex::new((Rate::default(), Rate::default()))),
}
}
/// 更新流量数据并返回变化后的速率(如果有变化)
pub fn update_and_check_changed(&self, up: u64, down: u64) -> Option<Rate> {
let mut rates = self.rate.lock();
let (current, previous) = &mut *rates;
*previous = current.clone();
current.up = up;
current.down = down;
if previous != current {
Some(current.clone())
} else {
None
}
}
// 获取当前的速率
pub fn get_curent_rate(&self) -> Option<Rate> {
let rates = self.rate.lock();
let (current, _) = &*rates;
Some(current.clone())
}
/// 在图标上添加速率显示
pub fn add_speed_text(icon: Vec<u8>, rate: Option<Rate>) -> Result<Vec<u8>> {
let rate = rate.unwrap_or(Rate { up: 0, down: 0 });
let img = image::load_from_memory(&icon)?;
let (width, height) = (img.width(), img.height());
let mut image = ImageBuffer::new((width as f32 * 4.0) as u32, height);
image::imageops::replace(&mut image, &img, 0, 0);
let font =
Font::try_from_bytes(include_bytes!("../../../assets/fonts/SFCompact.ttf")).unwrap();
// 修改颜色和阴影参数
let text_color = Rgba([255u8, 255u8, 255u8, 255u8]); // 纯白色
let shadow_color = Rgba([0u8, 0u8, 0u8, 180u8]); // 半透明黑色阴影
let base_size = (height as f32 * 0.5) as f32;
let scale = Scale::uniform(base_size);
let up_text = format_bytes_speed(rate.up);
let down_text = format_bytes_speed(rate.down);
// 计算文本位置(保持不变)
let up_width = font
.layout(&up_text, scale, rusttype::Point { x: 0.0, y: 0.0 })
.map(|g| g.position().x + g.unpositioned().h_metrics().advance_width)
.last()
.unwrap_or(0.0);
let down_width = font
.layout(&down_text, scale, rusttype::Point { x: 0.0, y: 0.0 })
.map(|g| g.position().x + g.unpositioned().h_metrics().advance_width)
.last()
.unwrap_or(0.0);
let right_margin = 8;
let canvas_width = width * 4;
let up_x = canvas_width as f32 - up_width - right_margin as f32;
let down_x = canvas_width as f32 - down_width - right_margin as f32;
// 添加阴影效果
let shadow_offset = 1; // 阴影偏移量
// 绘制上行速率(先画阴影,再画文字)
draw_text_mut(
&mut image,
shadow_color,
up_x as i32 + shadow_offset,
1 + shadow_offset,
scale,
&font,
&up_text,
);
draw_text_mut(
&mut image,
text_color,
up_x as i32,
1,
scale,
&font,
&up_text,
);
// 绘制下行速率(先画阴影,再画文字)
draw_text_mut(
&mut image,
shadow_color,
down_x as i32 + shadow_offset,
height as i32 - (base_size as i32) - 1 + shadow_offset,
scale,
&font,
&down_text,
);
draw_text_mut(
&mut image,
text_color,
down_x as i32,
height as i32 - (base_size as i32) - 1,
scale,
&font,
&down_text,
);
let mut bytes: Vec<u8> = Vec::new();
let mut cursor = Cursor::new(&mut bytes);
image.write_to(&mut cursor, image::ImageFormat::Png)?;
Ok(bytes)
}
}
#[derive(Debug, Clone)]
pub struct Traffic {
pub up: u64,
pub down: u64,
}
impl Traffic {
pub async fn get_traffic_stream() -> Result<impl Stream<Item = Result<Traffic, anyhow::Error>>>
{
use futures::stream::{self, StreamExt};
use std::time::Duration;
let stream = Box::pin(
stream::unfold((), |_| async {
loop {
let ws_url = get_traffic_ws_url().unwrap();
match tokio_tungstenite::connect_async(&ws_url).await {
Ok((ws_stream, _)) => {
log::info!(target: "app", "traffic ws connection established");
return Some((
ws_stream.map(|msg| {
msg.map_err(anyhow::Error::from).and_then(|msg: Message| {
let data = msg.into_text()?;
let json: serde_json::Value = serde_json::from_str(&data)?;
Ok(Traffic {
up: json["up"].as_u64().unwrap_or(0),
down: json["down"].as_u64().unwrap_or(0),
})
})
}),
(),
));
}
Err(e) => {
log::error!(target: "app", "traffic ws connection failed: {e}");
tokio::time::sleep(Duration::from_secs(5)).await;
continue;
}
}
}
})
.flatten(),
);
Ok(stream)
}
}

View File

@ -76,9 +76,9 @@ pub fn change_clash_mode(mode: String) {
if Config::clash().data().save_config().is_ok() {
handle::Handle::refresh_clash();
log_err!(handle::Handle::update_systray_menu());
log_err!(tray::Tray::global().update_menu());
#[cfg(target_os = "macos")]
log_err!(handle::Handle::update_systray_icon());
log_err!(tray::Tray::global().update_icon(None));
}
}
Err(err) => log::error!(target: "app", "{err}"),
@ -141,9 +141,9 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
CoreManager::global().restart_core().await?;
} else {
if patch.get("mode").is_some() {
log_err!(handle::Handle::update_systray_menu());
log_err!(tray::Tray::global().update_menu());
#[cfg(target_os = "macos")]
log_err!(handle::Handle::update_systray_icon());
log_err!(tray::Tray::global().update_icon(None));
}
Config::runtime().latest().patch_config(patch);
CoreManager::global().update_config().await?;
@ -267,7 +267,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
}
if should_update_systray_icon {
handle::Handle::update_systray_icon()?;
tray::Tray::global().update_icon(None)?;
}
<Result<()>>::Ok(())

View File

@ -201,22 +201,34 @@ macro_rules! t {
};
}
#[test]
fn test_parse_value() {
let test_1 = "upload=111; download=2222; total=3333; expire=444";
let test_2 = "attachment; filename=Clash.yaml";
assert_eq!(parse_str::<usize>(test_1, "upload").unwrap(), 111);
assert_eq!(parse_str::<usize>(test_1, "download").unwrap(), 2222);
assert_eq!(parse_str::<usize>(test_1, "total").unwrap(), 3333);
assert_eq!(parse_str::<usize>(test_1, "expire").unwrap(), 444);
assert_eq!(
parse_str::<String>(test_2, "filename").unwrap(),
format!("Clash.yaml")
);
assert_eq!(parse_str::<usize>(test_1, "aaa"), None);
assert_eq!(parse_str::<usize>(test_1, "upload1"), None);
assert_eq!(parse_str::<usize>(test_1, "expire1"), None);
assert_eq!(parse_str::<usize>(test_2, "attachment"), None);
/// 将字节数转换为可读的流量字符串
/// 支持 B/s、KB/s、MB/s、GB/s 的自动转换
///
/// # Examples
/// ```
/// assert_eq!(format_bytes_speed(1000), "1000B/s");
/// assert_eq!(format_bytes_speed(1024), "1.0KB/s");
/// assert_eq!(format_bytes_speed(1024 * 1024), "1.0MB/s");
/// ```
pub fn format_bytes_speed(speed: u64) -> String {
if speed < 1024 {
format!("{}B/s", speed)
} else if speed < 1024 * 1024 {
format!("{:.1}KB/s", speed as f64 / 1024.0)
} else if speed < 1024 * 1024 * 1024 {
format!("{:.1}MB/s", speed as f64 / 1024.0 / 1024.0)
} else {
format!("{:.1}GB/s", speed as f64 / 1024.0 / 1024.0 / 1024.0)
}
}
#[test]
fn test_format_bytes_speed() {
assert_eq!(format_bytes_speed(0), "0B/s");
assert_eq!(format_bytes_speed(1023), "1023B/s");
assert_eq!(format_bytes_speed(1024), "1.0KB/s");
assert_eq!(format_bytes_speed(1024 * 1024), "1.0MB/s");
assert_eq!(format_bytes_speed(1024 * 1024 * 1024), "1.0GB/s");
assert_eq!(format_bytes_speed(1024 * 500), "500.0KB/s");
assert_eq!(format_bytes_speed(1024 * 1024 * 2), "2.0MB/s");
}

View File

@ -92,7 +92,8 @@ pub async fn resolve_setup(app: &mut App) {
server::embed_server();
log::trace!(target: "app", "init system tray");
log_err!(tray::Tray::create_systray());
log_err!(tray::Tray::global().init());
log_err!(tray::Tray::global().create_systray());
let silent_start = { Config::verge().data().enable_silent_start };
if !silent_start.unwrap_or(false) {
@ -102,14 +103,21 @@ pub async fn resolve_setup(app: &mut App) {
log_err!(sysopt::Sysopt::global().update_sysproxy().await);
log_err!(sysopt::Sysopt::global().init_guard_sysproxy());
log_err!(handle::Handle::update_systray_part());
log_err!(tray::Tray::global().update_part());
log_err!(hotkey::Hotkey::global().init());
log_err!(timer::Timer::global().init());
// 流量订阅
#[cfg(target_os = "macos")]
log_err!(tray::Tray::global().subscribe_traffic().await);
}
/// reset system proxy
pub fn resolve_reset() {
tauri::async_runtime::block_on(async move {
#[cfg(target_os = "macos")]
tray::Tray::global().unsubscribe_traffic();
log_err!(sysopt::Sysopt::global().reset_sysproxy().await);
log_err!(CoreManager::global().stop_core().await);
#[cfg(target_os = "macos")]