From 6ed6f5b8f81560c66c01ffb79ab64941e8182c2a Mon Sep 17 00:00:00 2001 From: KeelrLeek <156356974+KeelrLeek@users.noreply.github.com> Date: Wed, 2 Sep 2026 14:27:54 -0500 Subject: [PATCH] community: the soulseek link proof, one message to yourself links the account and one question links anyone who answers --- Cargo.lock | 1057 +++++++++++-------------- crates/persona-state/src/lib.rs | 11 +- crates/persona-state/src/slsk_link.rs | 194 +++++ src-tauri/Cargo.toml | 1 + src-tauri/src/commands.rs | 5 + src-tauri/src/lib.rs | 6 + src-tauri/src/slsk_link.rs | 337 ++++++++ src/lib/api.js | 5 + src/lib/community.svelte.js | 56 +- src/views/Community.svelte | 77 +- 10 files changed, 1156 insertions(+), 593 deletions(-) create mode 100644 crates/persona-state/src/slsk_link.rs create mode 100644 src-tauri/src/slsk_link.rs diff --git a/Cargo.lock b/Cargo.lock index a3faace..f8b6cb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,17 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.17", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.12" @@ -33,9 +22,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -62,7 +51,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 2.13.0", + "bitflags 2.13.1", "cfg-if", "libc", ] @@ -96,9 +85,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -155,9 +144,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "app" @@ -178,6 +167,7 @@ dependencies = [ "persona-state", "player", "quick-xml 0.37.5", + "rand 0.8.8", "realfft", "reqwest 0.12.28", "serde", @@ -301,25 +291,13 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" dependencies = [ "serde_core", ] -[[package]] -name = "bitvec" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blake3" version = "1.8.7" @@ -361,30 +339,6 @@ dependencies = [ "objc2", ] -[[package]] -name = "borsh" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3f6da4992df95bbcd9af42a6c7dcb994498fc9048230405f3b36ff7cd3f145" -dependencies = [ - "borsh-derive", - "bytes", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8fb4fb5740e4b2c4884ff95f5f32f5e8479db1e8fd8eb49ddbe09eb09bb7c" -dependencies = [ - "once_cell", - "proc-macro-crate 3.5.0", - "proc-macro2", - "quote", - "syn 2.0.118", -] - [[package]] name = "brotli" version = "8.0.4" @@ -421,45 +375,11 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" -[[package]] -name = "byte-unit" -version = "5.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a813de7f2bbedb7dce265b64f1cf5908ebe4d56281ece8d847e98113788b9b0" -dependencies = [ - "rust_decimal", - "schemars 1.2.1", - "serde", - "utf8-width", -] - -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" [[package]] name = "byteorder" @@ -488,7 +408,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cairo-sys-rs", "glib", "libc", @@ -509,9 +429,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" dependencies = [ "serde_core", ] @@ -536,7 +456,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] @@ -551,9 +471,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.66" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" +checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" dependencies = [ "find-msvc-tools", "shlex", @@ -592,12 +512,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "chrono" version = "0.4.45" @@ -624,9 +538,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" -version = "4.6.7" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", "memchr", @@ -646,9 +560,9 @@ checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "cookie" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" dependencies = [ "time", "version_check", @@ -686,7 +600,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation 0.10.1", "core-graphics-types", "foreign-types 0.5.0", @@ -699,7 +613,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation 0.10.1", "libc", ] @@ -764,9 +678,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" dependencies = [ "cfg-if", ] @@ -844,7 +758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -896,7 +810,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -919,7 +833,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -930,7 +844,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -941,9 +855,9 @@ checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] name = "data-encoding" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" [[package]] name = "dbus" @@ -975,7 +889,7 @@ dependencies = [ "defmt-parser", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -984,7 +898,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] @@ -1024,7 +938,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -1075,7 +989,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "libc", "objc2", @@ -1083,13 +997,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -1112,7 +1026,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -1208,9 +1122,9 @@ dependencies = [ [[package]] name = "either" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" [[package]] name = "embed-resource" @@ -1221,7 +1135,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 1.1.2+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", "vswhom", "winreg", ] @@ -1321,9 +1235,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "fdeflate" @@ -1361,9 +1275,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" [[package]] name = "flatbuffers" @@ -1377,12 +1291,13 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.9.1", + "zlib-rs", ] [[package]] @@ -1418,13 +1333,13 @@ dependencies = [ [[package]] name = "foreign-types-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -1456,7 +1371,7 @@ dependencies = [ "freenet-stdlib", "log", "serde", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", "tokio-tungstenite", ] @@ -1469,7 +1384,7 @@ checksum = "d26e5c6bee9ffa0e2683bc8b41a7bd9f1e57e7fd49ac4f6ae433e5a82e9006df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -1493,7 +1408,7 @@ dependencies = [ "serde-wasm-bindgen", "serde_json", "serde_with", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", "tokio-tungstenite", "tracing", @@ -1502,17 +1417,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -1525,9 +1434,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -1535,15 +1444,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -1552,38 +1461,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -1777,7 +1686,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "futures-channel", "futures-core", "futures-executor", @@ -1805,7 +1714,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -1820,9 +1729,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "gobject-sys" @@ -1884,22 +1793,22 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "h2" -version = "0.4.15" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.4.2", - "indexmap 2.14.0", + "http 1.5.0", + "indexmap 2.14.1", "slab", "tokio", "tokio-util", @@ -1911,9 +1820,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] [[package]] name = "hashbrown" @@ -1921,7 +1827,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.12", + "ahash", ] [[package]] @@ -1980,9 +1886,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -1990,23 +1896,23 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", - "http 1.4.2", + "http 1.5.0", ] [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", - "http 1.4.2", + "http 1.5.0", "http-body", "pin-project-lite", ] @@ -2034,16 +1940,16 @@ dependencies = [ [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", "h2", - "http 1.4.2", + "http 1.5.0", "http-body", "httparse", "itoa", @@ -2059,7 +1965,7 @@ version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "http 1.4.2", + "http 1.5.0", "hyper", "hyper-util", "rustls", @@ -2094,7 +2000,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body", "hyper", "ipnet", @@ -2145,9 +2051,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" dependencies = [ "displaydoc", "potential_utf", @@ -2159,9 +2065,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", @@ -2172,9 +2078,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -2186,16 +2092,17 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" [[package]] name = "icu_properties" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" dependencies = [ + "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -2206,15 +2113,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", @@ -2260,7 +2167,7 @@ checksum = "76b0d7d4541def58a37bf8efc559683f21edce7c82f0d866c93ac21f7e098f93" dependencies = [ "attohttpc", "log", - "rand 0.8.6", + "rand 0.8.8", "url", "xmltree", ] @@ -2304,9 +2211,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" dependencies = [ "equivalent", "hashbrown 0.17.1", @@ -2325,9 +2232,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" [[package]] name = "is_terminal_polyfill" @@ -2366,27 +2273,55 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.32" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961d16382652bfdd8c6f68b223b26a8c93e0d475c672f414411db31c6c5c900e" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" dependencies = [ "defmt", + "jiff-core", "jiff-static", + "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", + "windows-link 0.2.1", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", ] [[package]] name = "jiff-static" -version = "0.2.32" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" dependencies = [ + "jiff-core", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", ] [[package]] @@ -2430,14 +2365,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if", "futures-util", @@ -2472,7 +2407,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "serde", "unicode-segmentation", ] @@ -2521,9 +2456,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libdbus-sys" @@ -2552,14 +2487,14 @@ dependencies = [ "log", "rusqlite", "serde", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed" dependencies = [ "libc", ] @@ -2583,9 +2518,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "lock_api" @@ -2619,17 +2554,14 @@ checksum = "ed9983e64b2358522f745c1251924e3ab7252d55637e80f6a0a3de642d6a9efc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" -dependencies = [ - "value-bag", -] +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "mach2" @@ -2696,7 +2628,7 @@ dependencies = [ "reqwest 0.12.28", "serde", "serde_json", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", ] @@ -2717,10 +2649,20 @@ dependencies = [ ] [[package]] -name = "mio" -version = "1.2.1" +name = "miniz_oxide" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi", @@ -2754,7 +2696,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.18", + "thiserror 2.0.20", "windows-sys 0.61.2", ] @@ -2781,7 +2723,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "jni-sys 0.3.1", "log", "ndk-sys", @@ -2862,14 +2804,14 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" dependencies = [ "num-traits", ] @@ -2913,7 +2855,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -2941,7 +2883,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-core-foundation", @@ -2954,7 +2896,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "libc", "objc2", "objc2-core-audio", @@ -2969,7 +2911,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-foundation", ] @@ -2992,7 +2934,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", ] @@ -3012,7 +2954,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "dispatch2", "objc2", ] @@ -3023,7 +2965,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "dispatch2", "objc2", "objc2-core-foundation", @@ -3056,7 +2998,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -3083,7 +3025,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "libc", "objc2", @@ -3096,7 +3038,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", ] @@ -3107,7 +3049,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -3119,7 +3061,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-cloud-kit", @@ -3150,7 +3092,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "objc2", "objc2-app-kit", @@ -3185,7 +3127,7 @@ version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cfg-if", "foreign-types 0.3.2", "libc", @@ -3201,7 +3143,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -3339,7 +3281,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -3369,9 +3311,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "player" @@ -3383,7 +3325,7 @@ dependencies = [ "rodio", "serde_json", "symphonia", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] @@ -3393,7 +3335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ "base64 0.22.1", - "indexmap 2.14.0", + "indexmap 2.14.1", "quick-xml 0.41.0", "serde", "time", @@ -3409,7 +3351,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] @@ -3418,18 +3360,18 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.8.9", ] [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "portable-atomic-util" @@ -3442,9 +3384,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ "zerovec", ] @@ -3505,7 +3447,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.12+spec-1.1.0", + "toml_edit 0.25.13+spec-1.1.0", ] [[package]] @@ -3534,33 +3476,13 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "pxfm" version = "0.1.30" @@ -3593,9 +3515,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -3612,17 +3534,11 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -3718,7 +3634,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", ] [[package]] @@ -3729,34 +3645,34 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] name = "ref-cast" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] name = "regex" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -3766,9 +3682,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -3781,15 +3697,6 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - [[package]] name = "reqwest" version = "0.12.28" @@ -3801,7 +3708,7 @@ dependencies = [ "encoding_rs", "futures-core", "h2", - "http 1.4.2", + "http 1.5.0", "http-body", "http-body-util", "hyper", @@ -3840,7 +3747,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body", "http-body-util", "hyper", @@ -3902,35 +3809,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rkyv" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rodio" version = "0.21.1" @@ -3949,7 +3827,7 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -3957,23 +3835,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rust_decimal" -version = "1.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2a24f50780bc85f09cc6ac299bdf1424302742d77221106859c9d8b102126a" -dependencies = [ - "arrayvec", - "borsh", - "bytes", - "num-traits", - "rand 0.8.6", - "rkyv", - "serde", - "serde_json", - "wasm-bindgen", -] - [[package]] name = "rustc-hash" version = "2.1.3" @@ -4009,7 +3870,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -4018,9 +3879,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.41" +version = "0.23.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" dependencies = [ "once_cell", "rustls-pki-types", @@ -4031,18 +3892,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "ring", "rustls-pki-types", @@ -4108,9 +3969,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" dependencies = [ "dyn-clone", "ref-cast", @@ -4127,7 +3988,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -4136,19 +3997,13 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "security-framework" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -4171,7 +4026,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "cssparser", "derive_more", "log", @@ -4196,9 +4051,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -4229,22 +4084,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -4255,14 +4110,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -4273,13 +4128,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -4314,18 +4169,19 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.21.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" dependencies = [ "base64 0.22.1", "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.14.0", + "indexmap 2.14.1", + "jiff", "schemars 0.9.0", - "schemars 1.2.1", + "schemars 1.2.2", "serde_core", "serde_json", "serde_with_macros", @@ -4334,14 +4190,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.21.0" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" +checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -4363,7 +4219,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -4423,15 +4279,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "siphasher" @@ -4447,15 +4297,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", @@ -4493,7 +4343,7 @@ dependencies = [ "igd-next", "log", "soulseek-proto", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", "tokio-util", ] @@ -4505,7 +4355,7 @@ dependencies = [ "bytes", "flate2", "md-5", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] @@ -4594,9 +4444,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "swift-rs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e" dependencies = [ "base64 0.21.7", "serde", @@ -4803,6 +4653,16 @@ name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -4811,9 +4671,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.118" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -4837,7 +4697,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -4851,7 +4711,7 @@ dependencies = [ "memchr", "ntapi", "rayon", - "windows 0.54.0", + "windows 0.57.0", ] [[package]] @@ -4860,7 +4720,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4894,7 +4754,7 @@ version = "1.6.0-alpha" dependencies = [ "lofty", "log", - "thiserror 2.0.18", + "thiserror 2.0.20", ] [[package]] @@ -4903,7 +4763,7 @@ version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "block2", "core-foundation 0.10.1", "core-graphics", @@ -4939,21 +4799,15 @@ dependencies = [ [[package]] name = "tao-macros" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +checksum = "5f7eeb6d99155545da6150a1795945f16ac9c178deb2a5f2e74d776107bd5849" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "target-lexicon" version = "0.12.16" @@ -4976,7 +4830,7 @@ dependencies = [ "glob", "gtk", "heck 0.5.0", - "http 1.4.2", + "http 1.5.0", "jni", "libc", "log", @@ -5001,7 +4855,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.20", "tokio", "tray-icon", "url", @@ -5050,9 +4904,9 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.118", + "syn 2.0.119", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.20", "time", "url", "uuid", @@ -5068,7 +4922,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", "tauri-codegen", "tauri-utils", ] @@ -5091,9 +4945,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.7.1" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65981abb771e74e571a38196c3baa11c459379164791eba0e67abc1a5fac9884" +checksum = "61854a36651aa48381e5e209f69a01273b77f3f9f91f0c430b1b98d33bd47229" dependencies = [ "log", "raw-window-handle", @@ -5103,15 +4957,15 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.18", + "thiserror 2.0.20", "url", ] [[package]] name = "tauri-plugin-fs" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ecc274121aca0c036a2b42d1cbe83d368d348f54e0bb8a735c2b1548e8f371" +checksum = "de22eef34fd78c0da050e748710edd50bf127e651d02ea1b2bfada1523cc5c51" dependencies = [ "anyhow", "dunce", @@ -5126,19 +4980,18 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.18", - "toml 1.1.2+spec-1.1.0", + "thiserror 2.0.20", + "toml 1.1.5+spec-1.1.0", "url", ] [[package]] name = "tauri-plugin-log" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93" +checksum = "b4e8861142c21636b03ff6eb9682a073814112e35220435670738a8be7b49896" dependencies = [ "android_logger", - "byte-unit", "fern", "log", "objc2", @@ -5149,7 +5002,7 @@ dependencies = [ "swift-rs", "tauri", "tauri-plugin", - "thiserror 2.0.18", + "thiserror 2.0.20", "time", ] @@ -5162,7 +5015,7 @@ dependencies = [ "cookie", "dpi", "gtk", - "http 1.4.2", + "http 1.5.0", "jni", "objc2", "objc2-ui-kit", @@ -5171,7 +5024,7 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "thiserror 2.0.18", + "thiserror 2.0.20", "url", "webkit2gtk", "webview2-com", @@ -5185,7 +5038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", - "http 1.4.2", + "http 1.5.0", "jni", "log", "objc2", @@ -5217,7 +5070,7 @@ dependencies = [ "dom_query", "dunce", "glob", - "http 1.4.2", + "http 1.5.0", "infer", "json-patch", "log", @@ -5234,8 +5087,8 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.18", - "toml 1.1.2+spec-1.1.0", + "thiserror 2.0.20", + "toml 1.1.5+spec-1.1.0", "url", "urlpattern", "uuid", @@ -5250,7 +5103,7 @@ checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" dependencies = [ "dunce", "embed-resource", - "toml 1.1.2+spec-1.1.0", + "toml 1.1.5+spec-1.1.0", ] [[package]] @@ -5286,11 +5139,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.20", ] [[package]] @@ -5301,18 +5154,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -5326,9 +5179,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", "libc", @@ -5348,9 +5201,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -5358,9 +5211,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", "zerovec", @@ -5368,9 +5221,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -5383,9 +5236,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ "bytes", "libc", @@ -5399,13 +5252,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -5442,13 +5295,14 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] @@ -5471,7 +5325,7 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "serde_core", "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", @@ -5482,17 +5336,17 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.2+spec-1.1.0" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "serde_core", "serde_spanned 1.1.1", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] @@ -5528,7 +5382,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -5539,7 +5393,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.3", @@ -5548,30 +5402,30 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.12+spec-1.1.0" +version = "0.25.13+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.14.1", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] name = "toml_parser" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ - "winnow 1.0.3", + "winnow 1.0.4", ] [[package]] name = "toml_writer" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tower" @@ -5594,10 +5448,10 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.1", "bytes", "futures-util", - "http 1.4.2", + "http 1.5.0", "http-body", "pin-project-lite", "tower", @@ -5637,7 +5491,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -5691,9 +5545,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" +checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" dependencies = [ "crossbeam-channel", "dirs", @@ -5707,7 +5561,7 @@ dependencies = [ "once_cell", "png 0.18.1", "serde", - "thiserror 2.0.18", + "thiserror 2.0.20", "windows-sys 0.61.2", ] @@ -5725,12 +5579,12 @@ checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" dependencies = [ "bytes", "data-encoding", - "http 1.4.2", + "http 1.5.0", "httparse", "log", "rand 0.9.5", "sha1", - "thiserror 2.0.18", + "thiserror 2.0.20", "utf-8", ] @@ -5836,12 +5690,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "159a7cadce548703edd50d24069bc294c5415ecab0a480e0cd1ca06d112dc94a" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -5856,9 +5704,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.4" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" +checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -5872,12 +5720,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "value-bag" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" - [[package]] name = "vcpkg" version = "0.2.15" @@ -5952,9 +5794,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -5967,9 +5809,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.76" +version = "0.4.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" dependencies = [ "js-sys", "wasm-bindgen", @@ -5977,9 +5819,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5987,22 +5829,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] @@ -6022,9 +5864,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.103" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", @@ -6032,9 +5874,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" +checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3" dependencies = [ "phf", "phf_codegen", @@ -6096,8 +5938,8 @@ dependencies = [ "webview2-com-sys", "windows 0.61.3", "windows-core 0.61.2", - "windows-implement", - "windows-interface", + "windows-implement 0.60.2", + "windows-interface 0.59.3", ] [[package]] @@ -6108,7 +5950,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -6117,7 +5959,7 @@ version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "thiserror 2.0.18", + "thiserror 2.0.20", "windows 0.61.3", "windows-core 0.61.2", ] @@ -6178,6 +6020,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.61.3" @@ -6210,14 +6062,26 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.60.2", + "windows-interface 0.59.3", "windows-link 0.1.3", "windows-result 0.3.4", "windows-strings 0.4.2", @@ -6229,8 +6093,8 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.60.2", + "windows-interface 0.59.3", "windows-link 0.2.1", "windows-result 0.4.1", "windows-strings 0.5.1", @@ -6247,6 +6111,17 @@ dependencies = [ "windows-threading", ] +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -6255,7 +6130,18 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -6266,7 +6152,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -6613,9 +6499,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" [[package]] name = "winnow" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] @@ -6638,9 +6524,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "writeable" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "wry" @@ -6658,7 +6544,7 @@ dependencies = [ "dunce", "gdkx11", "gtk", - "http 1.4.2", + "http 1.5.0", "javascriptcore-rs", "jni", "libc", @@ -6675,7 +6561,7 @@ dependencies = [ "sha2", "soup3", "tao-macros", - "thiserror 2.0.18", + "thiserror 2.0.20", "url", "webkit2gtk", "webkit2gtk-sys", @@ -6686,15 +6572,6 @@ dependencies = [ "x11-dl", ] -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x11" version = "2.21.0" @@ -6718,9 +6595,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.28" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" [[package]] name = "xmltree" @@ -6750,28 +6627,28 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.54" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.54" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -6791,7 +6668,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", "synstructure", ] @@ -6803,9 +6680,9 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -6814,9 +6691,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ "yoke", "zerofrom", @@ -6825,26 +6702,32 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] -name = "zmij" -version = "1.0.21" +name = "zlib-rs" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "zune-core" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" [[package]] name = "zune-jpeg" diff --git a/crates/persona-state/src/lib.rs b/crates/persona-state/src/lib.rs index 6e6e0c5..b4f0efa 100644 --- a/crates/persona-state/src/lib.rs +++ b/crates/persona-state/src/lib.rs @@ -15,6 +15,8 @@ use ed25519_dalek::{Signature, Verifier, VerifyingKey}; use serde::{Deserialize, Serialize}; +pub mod slsk_link; + pub const SCHEMA_VERSION: u32 = 1; pub const SIGN_DOMAIN: &str = "soulstream.profile/v1"; @@ -76,7 +78,7 @@ pub fn profile_sign_payload(p: &ProfileState) -> Vec { .expect("serializes") } -fn signable(domain: &str, payload: &[u8]) -> Vec { +pub(crate) fn signable(domain: &str, payload: &[u8]) -> Vec { let mut msg = Vec::new(); msg.extend_from_slice(b"soulstream.sig.v1"); msg.push(0); @@ -87,9 +89,14 @@ fn signable(domain: &str, payload: &[u8]) -> Vec { } pub fn verify_sig(public: &[u8; 32], payload: &[u8], sig: &[u8]) -> bool { + verify_sig_in(SIGN_DOMAIN, public, payload, sig) +} + +/// The same check under an explicit domain — the link and friend families. +pub fn verify_sig_in(domain: &str, public: &[u8; 32], payload: &[u8], sig: &[u8]) -> bool { let Ok(vk) = VerifyingKey::from_bytes(public) else { return false }; let Ok(sig) = Signature::from_slice(sig) else { return false }; - vk.verify(&signable(SIGN_DOMAIN, payload), &sig).is_ok() + vk.verify(&signable(domain, payload), &sig).is_ok() } pub fn make_profile_params(owner: &[u8; 32]) -> Vec { diff --git a/crates/persona-state/src/slsk_link.rs b/crates/persona-state/src/slsk_link.rs new file mode 100644 index 0000000..9143713 --- /dev/null +++ b/crates/persona-state/src/slsk_link.rs @@ -0,0 +1,194 @@ +//! The Soulseek link proof — F4 §7.4's exact claim shape and verifier, +//! transport-agnostic. Byte-compatibility matters here as everywhere in +//! this crate: the claim is what the delegate signs and what another +//! SoulStream client parses out of a Soulseek private message, so the field +//! order is the wire. +//! +//! Sign convention: the delegate is handed blake3(bincode(sig-body)) — the +//! F3/F4 convention — and `verify_claim` mirrors it. Verifiers answer from +//! signatures, nonces and clocks, never from names. + +use serde::{Deserialize, Serialize}; + +pub const SLSK_LINK_DOMAIN: &str = "soulstream.identity-link.soulseek/v1"; + +/// Exact-match normalization: trim + casefold. Nothing fuzzier — a claim is +/// for ONE account spelling class, never a lookalike. +pub fn normalize_username(name: &str) -> String { + name.trim().to_lowercase() +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SlskLinkClaim { + pub claim_type: String, + pub soulstream_public_key: [u8; 32], + pub soulseek_server_scope: String, + pub soulseek_username_normalized: String, + /// The verifier's nonce: an answer binds to the question that was asked. + pub nonce: [u8; 16], + pub issued_at: u64, + pub expires_at: u64, + pub sig: Vec, +} + +#[derive(Serialize)] +struct SigBody<'a> { + claim_type: &'a str, + soulstream_public_key: &'a [u8; 32], + soulseek_server_scope: &'a str, + soulseek_username_normalized: &'a str, + nonce: &'a [u8; 16], + issued_at: u64, + expires_at: u64, +} + +pub fn claim_sig_body(c: &SlskLinkClaim) -> Vec { + bincode::serialize(&SigBody { + claim_type: &c.claim_type, + soulstream_public_key: &c.soulstream_public_key, + soulseek_server_scope: &c.soulseek_server_scope, + soulseek_username_normalized: &c.soulseek_username_normalized, + nonce: &c.nonce, + issued_at: c.issued_at, + expires_at: c.expires_at, + }) + .expect("serializes") +} + +/// What the delegate is handed to sign: blake3(sig-body), 32 bytes. +pub fn claim_sign_payload(c: &SlskLinkClaim) -> Vec { + blake3::hash(&claim_sig_body(c)).as_bytes().to_vec() +} + +pub fn verify_claim(c: &SlskLinkClaim) -> bool { + c.claim_type == SLSK_LINK_DOMAIN + && crate::verify_sig_in( + SLSK_LINK_DOMAIN, + &c.soulstream_public_key, + &claim_sign_payload(c), + &c.sig, + ) +} + +#[derive(Debug, PartialEq, Eq)] +pub enum LinkRefused { + WrongType, + BadSignature, + WrongScope, + NonceMismatch, + WrongSender { got: String }, + WrongAccount, + Expired, + NotYetValid, +} + +impl core::fmt::Display for LinkRefused { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + LinkRefused::WrongType => write!(f, "not a Soulseek link claim"), + LinkRefused::BadSignature => write!(f, "claim signature does not verify"), + LinkRefused::WrongScope => write!(f, "claim is for a different Soulseek server"), + LinkRefused::NonceMismatch => write!(f, "answer does not carry the nonce that was asked"), + LinkRefused::WrongSender { got } => { + write!(f, "answer came from {got:?}, not the claimed account") + } + LinkRefused::WrongAccount => write!(f, "claim names an account that was not asked"), + LinkRefused::Expired => write!(f, "claim expired before it arrived"), + LinkRefused::NotYetValid => write!(f, "claim is dated in the future"), + } + } +} + +/// Allowed clock skew between two clients, in seconds. +const SKEW_SECS: u64 = 300; + +/// Verify an answer to OUR question. `expected_username` is who we asked +/// (normalized), `nonce` what we sent, `from_username` who the server says +/// answered — the one fact a Soulseek server vouches for. +pub fn check_response( + c: &SlskLinkClaim, + expected_username: &str, + nonce: &[u8; 16], + from_username: &str, + now: u64, + scope: &str, +) -> Result<(), LinkRefused> { + if c.claim_type != SLSK_LINK_DOMAIN { + return Err(LinkRefused::WrongType); + } + if !verify_claim(c) { + return Err(LinkRefused::BadSignature); + } + if c.soulseek_server_scope != scope { + return Err(LinkRefused::WrongScope); + } + if &c.nonce != nonce { + return Err(LinkRefused::NonceMismatch); + } + let from = normalize_username(from_username); + if from != c.soulseek_username_normalized { + return Err(LinkRefused::WrongSender { got: from }); + } + if c.soulseek_username_normalized != expected_username { + return Err(LinkRefused::WrongAccount); + } + if now > c.expires_at { + return Err(LinkRefused::Expired); + } + if c.issued_at > now + SKEW_SECS { + return Err(LinkRefused::NotYetValid); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use ed25519_dalek::{Signer, SigningKey}; + + const SCOPE: &str = "server.slsknet.org:2242"; + + fn signed(key: &SigningKey, user: &str, nonce: [u8; 16], issued: u64, expires: u64) -> SlskLinkClaim { + let mut c = SlskLinkClaim { + claim_type: SLSK_LINK_DOMAIN.into(), + soulstream_public_key: key.verifying_key().to_bytes(), + soulseek_server_scope: SCOPE.into(), + soulseek_username_normalized: normalize_username(user), + nonce, + issued_at: issued, + expires_at: expires, + sig: vec![], + }; + c.sig = key + .sign(&crate::signable(SLSK_LINK_DOMAIN, &claim_sign_payload(&c))) + .to_bytes() + .to_vec(); + c + } + + #[test] + fn the_happy_path_and_every_refusal() { + let key = SigningKey::from_bytes(&[9u8; 32]); + let nonce = [7u8; 16]; + let c = signed(&key, "ZooCone", nonce, 1000, 1300); + assert!(verify_claim(&c)); + assert_eq!(check_response(&c, "zoocone", &nonce, "ZooCone", 1100, SCOPE), Ok(())); + // the server said someone else answered + assert!(matches!( + check_response(&c, "zoocone", &nonce, "mallory", 1100, SCOPE), + Err(LinkRefused::WrongSender { .. }) + )); + // we asked a different account than the claim names + assert_eq!(check_response(&c, "someone", &nonce, "zoocone", 1100, SCOPE), Err(LinkRefused::WrongAccount)); + // a replayed answer to an older question + assert_eq!(check_response(&c, "zoocone", &[1u8; 16], "zoocone", 1100, SCOPE), Err(LinkRefused::NonceMismatch)); + // late + assert_eq!(check_response(&c, "zoocone", &nonce, "zoocone", 1301, SCOPE), Err(LinkRefused::Expired)); + // another server's account + assert_eq!(check_response(&c, "zoocone", &nonce, "zoocone", 1100, "other:1"), Err(LinkRefused::WrongScope)); + // tampered after signing + let mut t = c.clone(); + t.soulseek_username_normalized = "mallory".into(); + assert_eq!(check_response(&t, "mallory", &nonce, "mallory", 1100, SCOPE), Err(LinkRefused::BadSignature)); + } +} diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index eaa1cf1..b89205a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -31,6 +31,7 @@ tokio.workspace = true base64 = "0.22" bincode = "1" bs58 = "0.5" +rand = "0.8" # Shazam signature packets (shazam.rs) carry a CRC-32 of their body. crc32fast = "1" # Inflate for the deno release zip (ytdlp.rs) — already in the lock via the diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 3cf369c..dd5d4be 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -926,6 +926,11 @@ pub async fn connect_and_login( username, message, } => { + // Identity-link handshakes ride private messages and + // never reach the Inbox (slsk_link.rs). + if crate::slsk_link::intercept_pm(&event_app, &username, &message).await { + continue; + } let _ = event_app.emit( "soulseek:private-message", serde_json::json!({ diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 912314c..8a1c27b 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -21,6 +21,7 @@ mod provider_playlist; mod preview; mod setlist_scan; mod shazam; +mod slsk_link; mod smtc; mod state; mod thumbbar; @@ -123,6 +124,11 @@ pub fn run() { commands::slsk_user_info, commands::slsk_user_interests, commands::slsk_similar_users, + slsk_link::slsk_link_status, + slsk_link::slsk_link_self, + slsk_link::slsk_link_unlink, + slsk_link::slsk_link_check, + slsk_link::slsk_link_forget, commands::buddy_list, commands::buddy_add, commands::buddy_remove, diff --git a/src-tauri/src/slsk_link.rs b/src-tauri/src/slsk_link.rs new file mode 100644 index 0000000..02d6d3a --- /dev/null +++ b/src-tauri/src/slsk_link.rs @@ -0,0 +1,337 @@ +//! The Soulseek link proof, product side (F4 §7.4 → the app). +//! +//! What a Soulseek server vouches for is exactly one thing: WHO sent a +//! private message. So a SoulStream client proves "this Soulseek account +//! is this SoulStream ID" by answering a question over a PM: the asker +//! sends a nonce, the answerer's persona signs a claim binding its key, its +//! username and that nonce, and sends it back. The asker checks the +//! signature, the nonce, and that the server-attributed sender is the +//! account the claim names. Names never decide anything. +//! +//! Two uses of the same handshake: +//! - LINK (You → Soulseek card): ask yourself. A self-PM is server-routed +//! and speaks to no one; the answer proves the wire both ways and the +//! result is stored locally — method and time, as the design asks. +//! Linking is also the consent act: from then on this client answers +//! other SoulStream users who ask. Nothing is ever published. +//! - CHECK (a person's drawer): ask them. A verified answer is remembered +//! locally as username → SoulStream ID and unlocks their signed profile. +//! +//! Wire: `SSLINK1? · SoulStream identity check — safe to ignore` +//! asks; `SSLINK1!` answers. Both are consumed by +//! the event pump before the Inbox ever sees them. A client that is not +//! SoulStream sees one plain line it can ignore. + +use std::collections::{BTreeMap, HashMap}; +use std::path::PathBuf; +use std::sync::{Mutex, OnceLock}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use persona_state::slsk_link as sl; +use serde::{Deserialize, Serialize}; +use tauri::Manager; +use tokio::sync::oneshot; + +use crate::persona; +use crate::state::AppState; + +/// The one Soulseek server SoulStream speaks to; a claim is scoped to it. +pub const SCOPE: &str = "server.slsknet.org:2242"; +const REQ_PREFIX: &str = "SSLINK1?"; +const RESP_PREFIX: &str = "SSLINK1!"; +const REQ_SUFFIX: &str = " · SoulStream identity check — safe to ignore"; +/// How long an asker waits for an answer. +const ASK_TIMEOUT: Duration = Duration::from_secs(30); +/// How long an answer stays valid (clock skew and slow delivery included). +const CLAIM_TTL_SECS: u64 = 300; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct KnownLink { + /// As the server spelled the sender. + pub username: String, + pub username_normalized: String, + pub persona_key: String, + pub verified_at: u64, + pub method: String, +} + +#[derive(Default, Serialize, Deserialize)] +struct Links { + /// Our own account ↔ our own persona, once verified through ourselves. + #[serde(default)] + own: Option, + /// Everyone we asked and who answered correctly, by normalized username. + #[serde(default)] + others: BTreeMap, +} + +#[derive(Debug, Serialize)] +pub struct LinkStatus { + pub own: Option, + pub others: Vec, + /// Whether this client answers other people's questions right now. + pub answering: bool, +} + +fn links_path(app: &tauri::AppHandle) -> Result { + Ok(app + .path() + .app_data_dir() + .map_err(|e| e.to_string())? + .join("freenet") + .join("soulseek-links.json")) +} +fn load(app: &tauri::AppHandle) -> Links { + links_path(app) + .ok() + .and_then(|p| std::fs::read(p).ok()) + .and_then(|b| serde_json::from_slice(&b).ok()) + .unwrap_or_default() +} +fn save(app: &tauri::AppHandle, links: &Links) -> Result<(), String> { + let p = links_path(app)?; + if let Some(dir) = p.parent() { + std::fs::create_dir_all(dir).map_err(|e| e.to_string())?; + } + std::fs::write(&p, serde_json::to_vec_pretty(links).map_err(|e| e.to_string())?) + .map_err(|e| e.to_string()) +} +fn status_of(links: Links) -> LinkStatus { + LinkStatus { + answering: links.own.is_some(), + others: links.others.into_values().collect(), + own: links.own, + } +} + +struct Pending { + username_normalized: String, + expires_at: u64, + reply: oneshot::Sender>, +} +static PENDING: OnceLock>> = OnceLock::new(); +fn pending() -> &'static Mutex> { + PENDING.get_or_init(Default::default) +} + +fn now_secs() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|d| d.as_secs()) + .unwrap_or(0) +} +fn nonce16() -> [u8; 16] { + use rand::RngCore; + let mut n = [0u8; 16]; + rand::thread_rng().fill_bytes(&mut n); + n +} +fn decode_key(b58: &str) -> Result<[u8; 32], String> { + bs58::decode(b58) + .into_vec() + .map_err(|e| format!("bad persona key: {e}"))? + .as_slice() + .try_into() + .map_err(|_| "persona key is not 32 bytes".to_string()) +} + +async fn own_username(app: &tauri::AppHandle) -> Option { + app.state::().connected_as.lock().await.clone() +} +async fn send_pm(app: &tauri::AppHandle, to: &str, text: &str) -> Result<(), String> { + let st = app.state::(); + let guard = st.client.lock().await; + guard + .as_ref() + .ok_or("not connected to Soulseek")? + .message_user(to, text) + .map_err(|e| e.to_string()) +} + +/// Ask `username` over Soulseek for their signed SoulStream ID and verify +/// the answer. One PM out, one in, thirty seconds at most. +async fn ask(app: &tauri::AppHandle, username: &str) -> Result { + let target = sl::normalize_username(username); + if target.is_empty() { + return Err("no username".into()); + } + own_username(app).await.ok_or("not connected to Soulseek")?; + let nonce = nonce16(); + let (tx, rx) = oneshot::channel(); + pending().lock().unwrap().insert( + nonce, + Pending { + username_normalized: target, + expires_at: now_secs() + ASK_TIMEOUT.as_secs(), + reply: tx, + }, + ); + let text = format!("{REQ_PREFIX}{}{REQ_SUFFIX}", bs58::encode(nonce).into_string()); + if let Err(e) = send_pm(app, username, &text).await { + pending().lock().unwrap().remove(&nonce); + return Err(e); + } + match tokio::time::timeout(ASK_TIMEOUT, rx).await { + Ok(Ok(result)) => result, + _ => { + pending().lock().unwrap().remove(&nonce); + Err("no answer — not a SoulStream user, or they have not linked their account".into()) + } + } +} + +/// Our half: answer ONLY when asked, and only with consent — our own link +/// exists (linking is the consent act) — or when the asker is ourselves +/// (the self-link's bootstrap). +async fn answer(app: &tauri::AppHandle, from: &str, nonce: [u8; 16]) { + let Some(me) = own_username(app).await else { return }; + let me_norm = sl::normalize_username(&me); + let from_norm = sl::normalize_username(from); + if from_norm != me_norm && load(app).own.is_none() { + log::debug!("soulseek link: {from} asked, but this account is not linked — not answering"); + return; + } + let adapter = app.state::().freenet.clone(); + let key = match persona::current(&adapter).await { + Ok(Some(info)) => match decode_key(&info.public_key) { + Ok(k) => k, + Err(e) => { + log::warn!("soulseek link: {e}"); + return; + } + }, + _ => { + log::debug!("soulseek link: {from} asked, but there is no persona to answer with"); + return; + } + }; + let now = now_secs(); + let mut claim = sl::SlskLinkClaim { + claim_type: sl::SLSK_LINK_DOMAIN.into(), + soulstream_public_key: key, + soulseek_server_scope: SCOPE.into(), + soulseek_username_normalized: me_norm, + nonce, + issued_at: now, + expires_at: now + CLAIM_TTL_SECS, + sig: vec![], + }; + claim.sig = match persona::sign(&adapter, sl::SLSK_LINK_DOMAIN, sl::claim_sign_payload(&claim)).await { + Ok(sig) => sig, + Err(e) => { + log::warn!("soulseek link: could not sign the claim: {e}"); + return; + } + }; + let Ok(bytes) = bincode::serialize(&claim) else { return }; + use base64::Engine; + let text = format!("{RESP_PREFIX}{}", base64::engine::general_purpose::STANDARD.encode(bytes)); + if let Err(e) = send_pm(app, from, &text).await { + log::warn!("soulseek link: could not answer {from}: {e}"); + } else { + log::info!("soulseek link: answered {from}"); + } +} + +/// Their half arrives: match it to the question we asked and judge it. +fn accept(from: &str, payload_b64: &str) { + use base64::Engine; + let Ok(bytes) = base64::engine::general_purpose::STANDARD.decode(payload_b64.trim()) else { + return; + }; + let Ok(claim) = bincode::deserialize::(&bytes) else { return }; + let Some(p) = pending().lock().unwrap().remove(&claim.nonce) else { + log::debug!("soulseek link: answer from {from} matches no open question"); + return; + }; + let now = now_secs(); + let result = match sl::check_response(&claim, &p.username_normalized, &claim.nonce, from, now, SCOPE) { + Ok(()) if now <= p.expires_at => Ok(KnownLink { + username: from.to_string(), + username_normalized: p.username_normalized.clone(), + persona_key: bs58::encode(claim.soulstream_public_key).into_string(), + verified_at: now, + method: "native soulseek pm".into(), + }), + Ok(()) => Err("the answer arrived after the question expired".into()), + Err(e) => Err(format!("refused: {e}")), + }; + let _ = p.reply.send(result); +} + +/// The event pump hands every private message here first. True means it +/// was ours and must not surface in the Inbox. +pub async fn intercept_pm(app: &tauri::AppHandle, from: &str, message: &str) -> bool { + let msg = message.trim(); + if let Some(rest) = msg.strip_prefix(REQ_PREFIX) { + let token = rest.split_whitespace().next().unwrap_or(""); + match bs58::decode(token).into_vec().ok().and_then(|v| <[u8; 16]>::try_from(v).ok()) { + Some(nonce) => answer(app, from, nonce).await, + None => log::debug!("soulseek link: malformed question from {from}"), + } + return true; + } + if let Some(rest) = msg.strip_prefix(RESP_PREFIX) { + accept(from, rest); + return true; + } + false +} + +// ---------------------------------------------------------------- commands + +#[tauri::command] +pub fn slsk_link_status(app: tauri::AppHandle) -> Result { + Ok(status_of(load(&app))) +} + +/// Link the signed-in Soulseek account to this device's persona by asking +/// ourselves. Stores method and time; publishes nothing. +#[tauri::command] +pub async fn slsk_link_self( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + let adapter = state.freenet.clone(); + let info = persona::current(&adapter) + .await? + .ok_or("create a SoulStream identity first")?; + let me = own_username(&app).await.ok_or("not connected to Soulseek")?; + let mut link = ask(&app, &me).await?; + if link.persona_key != info.public_key { + return Err("the answer was signed by a different persona than this device holds".into()); + } + link.method = "native soulseek pm (self)".into(); + let mut links = load(&app); + links.own = Some(link); + save(&app, &links)?; + log::info!("soulseek link: {me} linked to this persona"); + Ok(status_of(links)) +} + +/// Forget our own link; this client stops answering questions. +#[tauri::command] +pub fn slsk_link_unlink(app: tauri::AppHandle) -> Result { + let mut links = load(&app); + links.own = None; + save(&app, &links)?; + Ok(status_of(links)) +} + +/// Ask someone for their SoulStream ID; a verified answer is remembered. +#[tauri::command] +pub async fn slsk_link_check(app: tauri::AppHandle, username: String) -> Result { + let link = ask(&app, &username).await?; + let mut links = load(&app); + links.others.insert(link.username_normalized.clone(), link.clone()); + save(&app, &links)?; + Ok(link) +} + +#[tauri::command] +pub fn slsk_link_forget(app: tauri::AppHandle, username: String) -> Result { + let mut links = load(&app); + links.others.remove(&sl::normalize_username(&username)); + save(&app, &links)?; + Ok(status_of(links)) +} diff --git a/src/lib/api.js b/src/lib/api.js index a913626..d2b6331 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -151,6 +151,11 @@ export const slskBrowseUser = (username) => invoke("slsk_browse_user", { usernam export const slskUserInfo = (username) => invoke("slsk_user_info", { username }); export const slskUserInterests = (username) => invoke("slsk_user_interests", { username }); export const slskSimilarUsers = () => invoke("slsk_similar_users"); +export const slskLinkStatus = () => invoke("slsk_link_status"); +export const slskLinkSelf = () => invoke("slsk_link_self"); +export const slskLinkUnlink = () => invoke("slsk_link_unlink"); +export const slskLinkCheck = (username) => invoke("slsk_link_check", { username }); +export const slskLinkForget = (username) => invoke("slsk_link_forget", { username }); export const buddyList = () => invoke("buddy_list"); export const buddyAdd = (username) => invoke("buddy_add", { username }); export const buddyRemove = (username) => invoke("buddy_remove", { username }); diff --git a/src/lib/community.svelte.js b/src/lib/community.svelte.js index 3d8d2f5..179ebb7 100644 --- a/src/lib/community.svelte.js +++ b/src/lib/community.svelte.js @@ -59,6 +59,13 @@ export const community = $state({ interests: {}, /** The server's similar-users answer, or null before it was asked. */ similar: null, + /** slsk_link_status: our own verified link and everyone we verified. */ + links: null, + /** username → the last failed ask's reason. */ + linkErrors: {}, + /** persona key → ProfileView | {none} | {error} | {pending}: other + * people's signed profiles, read once per session when surfaced. */ + remoteProfiles: {}, /** key → true while an action runs (buttons disable on it). */ busy: {}, /** The last action's error, shown where it happened. */ @@ -303,7 +310,7 @@ export async function initCommunity() { if (p.status === 1 || p.status === 2) noteSeen(p.username); }); } - await Promise.all([refreshFreenet(), loadContacts()]); + await Promise.all([refreshFreenet(), loadContacts(), refreshLinks()]); await refreshPersona(); } @@ -337,6 +344,53 @@ export async function loadSimilar(force = false) { } } +// ---- the Soulseek link proof ---------------------------------------------------- +export async function refreshLinks() { + try { + community.links = await api.slskLinkStatus(); + } catch { + // stays null: the UI treats it as "not linked" + } +} +export const linkSelf = () => + run("linkself", async () => { + community.links = await api.slskLinkSelf(); + }); +export const unlinkSelf = () => + run("linkself", async () => { + community.links = await api.slskLinkUnlink(); + }); +/** Ask one person over Soulseek; success is remembered on the Rust side. */ +export async function checkLink(username) { + community.busy["link:" + username] = true; + delete community.linkErrors[username]; + try { + const k = await api.slskLinkCheck(username); + await refreshLinks(); + return k; + } catch (e) { + community.linkErrors[username] = String(e?.message ?? e); + return null; + } finally { + delete community.busy["link:" + username]; + } +} +export const linkFor = (username) => { + const n = (username ?? "").trim().toLowerCase(); + return community.links?.others?.find((l) => l.username_normalized === n) ?? null; +}; +export async function loadRemoteProfile(key, force = false) { + if (!key) return; + if (community.remoteProfiles[key] && !force) return; + community.remoteProfiles[key] = { pending: true }; + try { + community.remoteProfiles[key] = (await api.profileGet(key)) ?? { none: true }; + } catch (e) { + community.remoteProfiles[key] = { error: String(e?.message ?? e) }; + } +} + + // Dev handle beside `__soulstream` (state.svelte.js): probes reach the store // through this, never through a bare import (which would be a second copy). if (import.meta.env.DEV) globalThis.__community = community; diff --git a/src/views/Community.svelte b/src/views/Community.svelte index 603b33a..643277f 100644 --- a/src/views/Community.svelte +++ b/src/views/Community.svelte @@ -58,6 +58,12 @@ personaKey, loadUserInfo, loadSimilar, + refreshLinks, + linkSelf, + unlinkSelf, + checkLink, + linkFor, + loadRemoteProfile, } from "../lib/community.svelte.js"; onMount(() => { @@ -100,6 +106,12 @@ const nodeUp = $derived(adapterConnected(community.freenet?.status)); const online = $derived(app.connection === "online"); const me = $derived(app.username ?? ""); + const ownLink = $derived(community.links?.own ?? null); + /** The stored link is only "current" for the signed-in account and the + * persona this device holds now — a different login or key is unlinked. */ + const ownLinkCurrent = $derived( + !!ownLink && !!key && !!me && ownLink.username_normalized === me.trim().toLowerCase() && ownLink.persona_key === key, + ); const display = (u) => community.contacts[u]?.petname || u; const isContact = (u) => slsk.buddies.includes(u); @@ -398,6 +410,12 @@ const drawerPhoto = $derived( drawerInfo?.picture_png_base64 ? `data:image/png;base64,${drawerInfo.picture_png_base64}` : null, ); + const drawerLink = $derived(drawerUser ? linkFor(drawerUser) : null); + const drawerRemote = $derived(drawerLink ? community.remoteProfiles[drawerLink.persona_key] : null); + $effect(() => { + const lk = drawerLink; + if (lk) untrack(() => loadRemoteProfile(lk.persona_key)); + }); // Discover's similar-users shelf asks the server once per session. $effect(() => { if (community.section === "discover" && online) untrack(() => loadSimilar()); @@ -460,6 +478,7 @@ {#if me}{me} on Soulseek{:else}not signed in to Soulseek{/if} {online ? "online" : "offline"} + {#if ownLinkCurrent}linked{/if} @@ -771,6 +790,7 @@
Soulseek + {#if linkFor(p.u)}SoulStream{/if} {#if p.meta.group}·{p.meta.group}{/if} {#if p.st.file_count != null}·{fmtCount(p.st.file_count)} files{/if} {#if p.meta.note}·{p.meta.note}{/if} @@ -1054,8 +1074,27 @@
Soulseek {online ? "online" : "offline"}
{#if me}Signed in as {me} · {fmtCount(network.shareFiles)} files shared.{:else}Not signed in — see Settings.{/if} -
Linking this username to your SoulStream identity by a signed proof is the next identity slice; until then the two are simply side by side. +
+ {#if !key} + Create a SoulStream identity to link this account to it. + {:else if !me} + Sign in to Soulseek to link this account to your identity. + {:else if ownLinkCurrent} + Linked to this identity — proof verified {new Date(ownLink.verified_at * 1000).toLocaleString()} through a Soulseek message to yourself. Other SoulStream users who ask over Soulseek now get your signed ID; nothing is published. + {:else} + Not linked to your identity. Linking sends one message to yourself over Soulseek and verifies the signed answer — nothing is published, and from then on other SoulStream users who ask get your signed ID. + {/if}
+ {#if key && me} +
+ {#if ownLinkCurrent} + + {:else} + + {#if !nodeUp}needs the node connected{/if} + {/if} +
+ {/if}
@@ -1201,8 +1240,37 @@ {/if}
-

Signed SoulStream profile none presented

-

No SoulStream profile has been presented for this person. That is normal — most Soulseek users have none, and the link between a Soulseek name and a SoulStream ID is a signed proof that lands with the next identity slice.

+ {#if drawerLink} +

Signed SoulStream profile verified {fmtWhen(drawerLink.verified_at * 1000)}

+
+ +
+ {#if !drawerRemote || drawerRemote.pending} +
SoulStream ID {fpShort(drawerLink.persona_key)}
+

reading their profile from the network

+ {:else if drawerRemote.error} +
SoulStream ID {fpShort(drawerLink.persona_key)}
+

Could not read their profile: {drawerRemote.error}

+ {:else if drawerRemote.none} +
SoulStream ID {fpShort(drawerLink.persona_key)}
+

They proved their ID but have not published a profile yet.

+ {:else} +
{drawerRemote.display_name || "(no name)"} SoulStream
+
{fpShort(drawerLink.persona_key)} · revision {drawerRemote.sequence}
+ {#if drawerRemote.bio}

{drawerRemote.bio}

{/if} + {#if drawerRemote.avatar_note && drawerRemote.avatar_note !== "none published"}

{drawerRemote.avatar_note}

{/if} + {/if} +
+
+

Their client answered a one-time question over Soulseek with a claim signed by this key — the server vouched for the sender, the signature for the key.

+ {:else} +

Signed SoulStream profile not asked

+

Ask their client, over Soulseek, for a signed SoulStream ID. One message goes out; a client that is not SoulStream sees a line saying it is safe to ignore.

+
+ +
+ {#if community.linkErrors[drawerUser]}

{community.linkErrors[drawerUser]}

{/if} + {/if}
A SoulStream badge means a compatible, signed profile was presented and verified against its key. It is not proof of who @@ -1557,6 +1625,9 @@ .tag { font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 99px; background: var(--surf-hi); color: var(--text-secondary); } .tag.hate { text-decoration: line-through; opacity: 0.7; } .desc { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 180px; overflow-y: auto; } + .rp { display: flex; gap: 12px; align-items: flex-start; } + .rptx { min-width: 0; flex: 1; } + .rp .nm { font-size: 15px; font-weight: 800; display: flex; align-items: center; gap: 8px; } .dsec { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hair); } .dsec h4 { margin: 0 0 8px; font-size: 10.5px; font-weight: 900; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); display: flex; align-items: center; gap: 8px; } .dsec h4 .src, .dsec h4 .chip { margin-left: auto; }