From 967355cd4a0505d63a6c8ba952b8152575ea886d Mon Sep 17 00:00:00 2001 From: reya Date: Wed, 7 Jan 2026 14:05:24 +0700 Subject: [PATCH] . --- Cargo.lock | 327 ++++++++++++++------------- crates/chat/src/lib.rs | 89 ++------ crates/chat/src/room.rs | 25 +- crates/common/src/constants.rs | 3 - crates/common/src/event.rs | 8 +- crates/coop/src/main.rs | 14 +- crates/coop/src/user/mod.rs | 3 +- crates/coop/src/views/setup_relay.rs | 3 +- crates/person/src/lib.rs | 136 +++++++++-- crates/state/src/device.rs | 34 +++ crates/state/src/identity.rs | 6 + crates/state/src/lib.rs | 228 +++++++++++-------- 12 files changed, 511 insertions(+), 365 deletions(-) create mode 100644 crates/state/src/device.rs diff --git a/Cargo.lock b/Cargo.lock index 03c7dca..94b019f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,7 +114,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -367,7 +367,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -443,7 +443,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -605,9 +605,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82" [[package]] name = "bech32" @@ -632,7 +632,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -711,8 +711,7 @@ dependencies = [ [[package]] name = "blade-graphics" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4deb8f595ce7f00dee3543ebf6fd9a20ea86fc421ab79600dac30876250bdae" +source = "git+https://github.com/kvark/blade?rev=e3cf011ca18a6dfd907d1dedd93e85e21f005fe3#e3cf011ca18a6dfd907d1dedd93e85e21f005fe3" dependencies = [ "ash", "ash-window", @@ -746,19 +745,17 @@ dependencies = [ [[package]] name = "blade-macros" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27142319e2f4c264581067eaccb9f80acccdde60d8b4bf57cc50cd3152f109ca" +source = "git+https://github.com/kvark/blade?rev=e3cf011ca18a6dfd907d1dedd93e85e21f005fe3#e3cf011ca18a6dfd907d1dedd93e85e21f005fe3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "blade-util" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6be3a82c001ba7a17b6f8e413ede5d1004e6047213f8efaf0ffc15b5c4904c" +source = "git+https://github.com/kvark/blade?rev=e3cf011ca18a6dfd907d1dedd93e85e21f005fe3#e3cf011ca18a6dfd907d1dedd93e85e21f005fe3" dependencies = [ "blade-graphics", "bytemuck", @@ -857,7 +854,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -925,16 +922,16 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.111", + "syn 2.0.113", "tempfile", "toml 0.8.23", ] [[package]] name = "cc" -version = "1.2.50" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "jobserver", @@ -1176,7 +1173,7 @@ dependencies = [ [[package]] name = "collections" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "indexmap", "rustc-hash 2.1.1", @@ -1597,17 +1594,17 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "derive_refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -1686,7 +1683,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -1823,7 +1820,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -1843,7 +1840,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -1966,7 +1963,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -2012,9 +2009,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] name = "flatbuffers" @@ -2160,7 +2157,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -2213,9 +2210,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "ftree" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae0379499242d3b9355c5069b43b9417def8c9b09903b930db1fe49318dc9e9" +checksum = "eeef4a9366aaf0ed0bb5292b7c489d80600a7431fca0d96271e10e23ac0bc2b0" dependencies = [ "serde", ] @@ -2314,7 +2311,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -2489,7 +2486,7 @@ dependencies = [ [[package]] name = "gpui" version = "0.2.2" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "as-raw-xcb-connection", @@ -2561,6 +2558,7 @@ dependencies = [ "stacksafe", "strum 0.27.2", "sum_tree", + "swash", "taffy", "thiserror 2.0.17", "usvg", @@ -2589,18 +2587,18 @@ dependencies = [ [[package]] name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "gpui_tokio" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "gpui", @@ -2616,9 +2614,9 @@ checksum = "12101ecc8225ea6d675bc70263074eab6169079621c2186fe0c66590b2df9681" [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2822,7 +2820,7 @@ dependencies = [ [[package]] name = "http_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "async-compression", @@ -2847,7 +2845,7 @@ dependencies = [ [[package]] name = "http_client_tls" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "rustls", "rustls-platform-verifier", @@ -3160,7 +3158,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -3192,9 +3190,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -3239,9 +3237,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jni" @@ -3363,9 +3361,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libfuzzer-sys" @@ -3395,13 +3393,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall 0.6.0", + "redox_syscall 0.7.0", ] [[package]] @@ -3608,7 +3606,7 @@ dependencies = [ [[package]] name = "media" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "bindgen", @@ -3770,7 +3768,7 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", "security-framework 2.11.1", @@ -3849,7 +3847,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" [[package]] name = "nostr" version = "0.44.1" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "aes", "base64", @@ -3874,7 +3872,7 @@ dependencies = [ [[package]] name = "nostr-connect" version = "0.44.0" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "async-utility", "nostr", @@ -3886,7 +3884,7 @@ dependencies = [ [[package]] name = "nostr-database" version = "0.44.0" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "btreecap", "flatbuffers", @@ -3898,7 +3896,7 @@ dependencies = [ [[package]] name = "nostr-gossip" version = "0.44.0" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "nostr", ] @@ -3906,7 +3904,7 @@ dependencies = [ [[package]] name = "nostr-lmdb" version = "0.44.0" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "async-utility", "flume", @@ -3920,7 +3918,7 @@ dependencies = [ [[package]] name = "nostr-relay-pool" version = "0.44.0" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "async-utility", "async-wsocket", @@ -3937,7 +3935,7 @@ dependencies = [ [[package]] name = "nostr-sdk" version = "0.44.1" -source = "git+https://github.com/rust-nostr/nostr#038e66a5eb003048b17756bbb525a06edb2eea87" +source = "git+https://github.com/rust-nostr/nostr#3fc1b32732909cc388d10e6cb2f4904e0abfdb2c" dependencies = [ "async-utility", "nostr", @@ -4024,7 +4022,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4301,7 +4299,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4310,6 +4308,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + [[package]] name = "openssl-sys" version = "0.9.111" @@ -4454,7 +4458,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perf" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "collections", "serde", @@ -4506,7 +4510,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4541,7 +4545,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4672,7 +4676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4703,14 +4707,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] @@ -4731,7 +4735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -4788,9 +4792,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.37.5" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", ] @@ -4852,9 +4856,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -5048,9 +5052,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ "bitflags 2.10.0", ] @@ -5083,13 +5087,13 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "derive_refineable", ] @@ -5188,7 +5192,7 @@ dependencies = [ [[package]] name = "reqwest_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "bytes", @@ -5242,7 +5246,7 @@ dependencies = [ [[package]] name = "rope" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "arrayvec", "log", @@ -5280,7 +5284,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.111", + "syn 2.0.113", "walkdir", ] @@ -5354,9 +5358,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "aws-lc-rs", "log", @@ -5370,11 +5374,11 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.0", "rustls-pki-types", "schannel", "security-framework 3.5.1", @@ -5481,9 +5485,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "salsa20" @@ -5535,7 +5539,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -5648,9 +5652,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" @@ -5689,7 +5693,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -5700,7 +5704,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -5714,9 +5718,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.147" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af14725505314343e673e9ecb7cd7e8a36aa9791eb936235a3567cc31447ae4" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "indexmap", "itoa", @@ -5747,7 +5751,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6006,7 +6010,7 @@ checksum = "172175341049678163e979d9107ca3508046d4d2a7c6682bee46ac541b17db69" dependencies = [ "proc-macro-error2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6067,7 +6071,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6079,7 +6083,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6091,7 +6095,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sum_tree" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "arrayvec", "log", @@ -6218,9 +6222,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -6253,7 +6257,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6403,7 +6407,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6414,7 +6418,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6519,9 +6523,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -6540,7 +6544,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6593,9 +6597,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -6761,7 +6765,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -6893,9 +6897,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-bidi" @@ -6996,14 +7000,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -7048,7 +7053,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "util" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "async-fs", @@ -7084,11 +7089,11 @@ dependencies = [ [[package]] name = "util_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "perf", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -7280,7 +7285,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", "wasm-bindgen-shared", ] @@ -7308,9 +7313,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" dependencies = [ "cc", "downcast-rs", @@ -7322,9 +7327,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.11" +version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" dependencies = [ "bitflags 2.10.0", "rustix 1.1.3", @@ -7334,9 +7339,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.11" +version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" dependencies = [ "rustix 1.1.3", "wayland-client", @@ -7345,9 +7350,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.9" +version = "0.32.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" dependencies = [ "bitflags 2.10.0", "wayland-backend", @@ -7357,9 +7362,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" dependencies = [ "bitflags 2.10.0", "wayland-backend", @@ -7370,9 +7375,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" dependencies = [ "bitflags 2.10.0", "wayland-backend", @@ -7383,20 +7388,20 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.7" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", - "quick-xml 0.37.5", + "quick-xml 0.38.4", "quote", ] [[package]] name = "wayland-sys" -version = "0.31.7" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ "dlib", "log", @@ -7446,14 +7451,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" dependencies = [ - "webpki-root-certs 1.0.4", + "webpki-root-certs 1.0.5", ] [[package]] name = "webpki-root-certs" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" dependencies = [ "rustls-pki-types", ] @@ -7464,14 +7469,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.4", + "webpki-roots 1.0.5", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -7638,7 +7643,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -7649,7 +7654,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -7660,7 +7665,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -7671,7 +7676,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -8186,9 +8191,9 @@ dependencies = [ [[package]] name = "xcb" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07c123b796139bfe0603e654eaf08e132e52387ba95b252c78bad3640ba37ea" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" dependencies = [ "bitflags 1.3.2", "libc", @@ -8284,7 +8289,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", "synstructure", ] @@ -8331,7 +8336,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", "zbus_names", "zvariant", "zvariant_utils", @@ -8479,7 +8484,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -8499,7 +8504,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", "synstructure", ] @@ -8514,13 +8519,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] @@ -8553,13 +8558,13 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", ] [[package]] name = "zlog" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "anyhow", "chrono", @@ -8569,14 +8574,14 @@ dependencies = [ [[package]] name = "zmij" -version = "0.1.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0095ecd462946aa3927d9297b63ef82fb9a5316d7a37d134eeb36e58228615a" +checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" [[package]] name = "ztracing" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" dependencies = [ "tracing", "tracing-subscriber", @@ -8587,7 +8592,7 @@ dependencies = [ [[package]] name = "ztracing_macro" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#f03987fb68224e3b7fb993ce2ffaf364836a003c" +source = "git+https://github.com/zed-industries/zed#189241bf74da9fd5a7fdf3cfce09ae7f0b59b6ef" [[package]] name = "zune-core" @@ -8652,7 +8657,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.113", "zvariant_utils", ] @@ -8665,6 +8670,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.111", + "syn 2.0.113", "winnow", ] diff --git a/crates/chat/src/lib.rs b/crates/chat/src/lib.rs index 560a2aa..d02bf0d 100644 --- a/crates/chat/src/lib.rs +++ b/crates/chat/src/lib.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use std::time::Duration; use anyhow::{anyhow, Context as AnyhowContext, Error}; -use common::{EventUtils, BOOTSTRAP_RELAYS, METADATA_BATCH_LIMIT}; +use common::EventUtils; use flume::Sender; use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; @@ -154,7 +154,6 @@ impl ChatRegistry { let subscription_id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION); let mut notifications = client.notifications(); - let mut public_keys = HashSet::new(); let mut processed_events = HashSet::new(); while let Ok(notification) = notifications.recv().await { @@ -177,41 +176,26 @@ impl ChatRegistry { // Extract the rumor from the gift wrap event match Self::extract_rumor(client, event.as_ref()).await { - Ok(rumor) => { - // Get all public keys - public_keys.extend(rumor.all_pubkeys()); + Ok(rumor) => match rumor.created_at >= initialized_at { + true => { + let sent_by_coop = { + let tracker = tracker().read().await; + tracker.is_sent_by_coop(&event.id) + }; - let limit_reached = public_keys.len() >= METADATA_BATCH_LIMIT; - let done = !loading.load(Ordering::Acquire) && !public_keys.is_empty(); + if !sent_by_coop { + let new_message = NewMessage::new(event.id, rumor); + let signal = NostrEvent::Message(new_message); - // Get metadata for all public keys if the limit is reached - if limit_reached || done { - let public_keys = std::mem::take(&mut public_keys); - // Get metadata for the public keys - Self::get_metadata(client, public_keys).await.ok(); - } - - match rumor.created_at >= initialized_at { - true => { - let sent_by_coop = { - let tracker = tracker().read().await; - tracker.is_sent_by_coop(&event.id) - }; - - if !sent_by_coop { - let new_message = NewMessage::new(event.id, rumor); - let signal = NostrEvent::Message(new_message); - - if let Err(e) = tx.send_async(signal).await { - log::error!("Failed to send signal: {}", e); - } + if let Err(e) = tx.send_async(signal).await { + log::error!("Failed to send signal: {}", e); } } - false => { - loading.store(true, Ordering::Release); - } } - } + false => { + loading.store(true, Ordering::Release); + } + }, Err(e) => { log::warn!("Failed to unwrap gift wrap event: {}", e); } @@ -230,7 +214,7 @@ impl ChatRegistry { } async fn unwrapping_status(client: &Client, status: &Arc, tx: &Sender) { - let loop_duration = Duration::from_secs(20); + let loop_duration = Duration::from_secs(12); let mut is_start_processing = false; let mut total_loops = 0; @@ -240,22 +224,16 @@ impl ChatRegistry { if status.load(Ordering::Acquire) { is_start_processing = true; - // Reset gift wrap processing flag _ = status.compare_exchange(true, false, Ordering::Release, Ordering::Relaxed); - // Send loading signal - if let Err(e) = tx.send_async(NostrEvent::Unwrapping(true)).await { - log::error!("Failed to send signal: {}", e); - } + tx.send_async(NostrEvent::Unwrapping(true)).await.ok(); } else { // Only run further if we are already processing // Wait until after 2 loops to prevent exiting early while events are still being processed if is_start_processing && total_loops >= 2 { - // Send loading signal - if let Err(e) = tx.send_async(NostrEvent::Unwrapping(false)).await { - log::error!("Failed to send signal: {}", e); - } + tx.send_async(NostrEvent::Unwrapping(false)).await.ok(); + // Reset the counter is_start_processing = false; total_loops = 0; @@ -654,33 +632,6 @@ impl ChatRegistry { } } - /// Get metadata for a list of public keys - async fn get_metadata(client: &Client, public_keys: I) -> Result<(), Error> - where - I: IntoIterator, - { - let authors: Vec = public_keys.into_iter().collect(); - let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); - let kinds = vec![Kind::Metadata, Kind::ContactList]; - - // Return if the list is empty - if authors.is_empty() { - return Err(anyhow!("You need at least one public key".to_string(),)); - } - - let filter = Filter::new() - .limit(authors.len() * kinds.len()) - .authors(authors) - .kinds(kinds); - - // Subscribe to filters to the bootstrap relays - client - .subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts)) - .await?; - - Ok(()) - } - /// Get the conversation ID for a given rumor (message). fn conversation_id(rumor: &UnsignedEvent) -> u64 { let mut hasher = DefaultHasher::new(); diff --git a/crates/chat/src/room.rs b/crates/chat/src/room.rs index a8daf18..d9ebced 100644 --- a/crates/chat/src/room.rs +++ b/crates/chat/src/room.rs @@ -147,7 +147,7 @@ impl From<&UnsignedEvent> for Room { let created_at = val.created_at; // Get the members from the event's tags and event's pubkey - let members = val.all_pubkeys(); + let members = val.extract_public_keys(); // Get subject from tags let subject = val @@ -228,16 +228,25 @@ impl Room { } /// Returns the members of the room with their messaging relays - pub fn members_with_relays(&self, cx: &App) -> Vec<(PublicKey, Vec)> { + pub fn members_with_relays(&self, cx: &App) -> Task)>> { let nostr = NostrRegistry::global(cx); - let mut result = vec![]; + let mut tasks = vec![]; for member in self.members.iter() { - let messaging_relays = nostr.read(cx).messaging_relays(member, cx); - result.push((member.to_owned(), messaging_relays)); + let task = nostr.read(cx).messaging_relays(member, cx); + tasks.push((*member, task)); } - result + cx.background_spawn(async move { + let mut results = vec![]; + + for (public_key, task) in tasks.into_iter() { + let urls = task.await; + results.push((public_key, urls)); + } + + results + }) } /// Checks if the room has more than two members (group) @@ -457,10 +466,12 @@ impl Room { let rumor = rumor.to_owned(); // Get all members and their messaging relays - let mut members = self.members_with_relays(cx); + let task = self.members_with_relays(cx); cx.background_spawn(async move { let signer = client.signer().await?; + let current_user_relays = current_user_relays.await; + let mut members = task.await; // Remove the current user's public key from the list of receivers // the current user will be handled separately diff --git a/crates/common/src/constants.rs b/crates/common/src/constants.rs index 391752b..bfa6c11 100644 --- a/crates/common/src/constants.rs +++ b/crates/common/src/constants.rs @@ -27,8 +27,5 @@ pub const NOSTR_CONNECT_TIMEOUT: u64 = 200; /// Default timeout (in seconds) for Nostr Connect (Bunker) pub const BUNKER_TIMEOUT: u64 = 30; -/// Total metadata requests will be grouped. -pub const METADATA_BATCH_LIMIT: usize = 20; - /// Default width of the sidebar. pub const DEFAULT_SIDEBAR_WIDTH: f32 = 240.; diff --git a/crates/common/src/event.rs b/crates/common/src/event.rs index c206746..03833c7 100644 --- a/crates/common/src/event.rs +++ b/crates/common/src/event.rs @@ -5,19 +5,19 @@ use nostr_sdk::prelude::*; pub trait EventUtils { fn uniq_id(&self) -> u64; - fn all_pubkeys(&self) -> Vec; + fn extract_public_keys(&self) -> Vec; } impl EventUtils for Event { fn uniq_id(&self) -> u64 { let mut hasher = DefaultHasher::new(); - let mut pubkeys: Vec = self.all_pubkeys(); + let mut pubkeys: Vec = self.extract_public_keys(); pubkeys.sort(); pubkeys.hash(&mut hasher); hasher.finish() } - fn all_pubkeys(&self) -> Vec { + fn extract_public_keys(&self) -> Vec { let mut public_keys: Vec = self.tags.public_keys().copied().collect(); public_keys.push(self.pubkey); @@ -45,7 +45,7 @@ impl EventUtils for UnsignedEvent { hasher.finish() } - fn all_pubkeys(&self) -> Vec { + fn extract_public_keys(&self) -> Vec { let mut public_keys: Vec = self.tags.public_keys().copied().collect(); public_keys.push(self.pubkey); public_keys.into_iter().unique().sorted().collect() diff --git a/crates/coop/src/main.rs b/crates/coop/src/main.rs index 845ba74..9277d49 100644 --- a/crates/coop/src/main.rs +++ b/crates/coop/src/main.rs @@ -73,7 +73,6 @@ fn main() { // Bring the app to the foreground cx.activate(true); - // Root Entity cx.new(|cx| { // Initialize the tokio runtime gpui_tokio::init(cx); @@ -90,21 +89,22 @@ fn main() { // Initialize the nostr client state::init(cx); - // Initialize person registry - person::init(cx); - // Initialize settings settings::init(cx); - // Initialize app registry - chat::init(cx); - // Initialize relay auth registry relay_auth::init(window, cx); + // Initialize app registry + chat::init(cx); + + // Initialize person registry + person::init(cx); + // Initialize auto update auto_update::init(cx); + // Root Entity Root::new(chatspace::init(window, cx).into(), window, cx) }) }) diff --git a/crates/coop/src/user/mod.rs b/crates/coop/src/user/mod.rs index c94840b..34207bb 100644 --- a/crates/coop/src/user/mod.rs +++ b/crates/coop/src/user/mod.rs @@ -263,13 +263,14 @@ impl UserProfile { let write_relays = nostr.read(cx).write_relays(&public_key, cx); cx.background_spawn(async move { + let urls = write_relays.await; let signer = client.signer().await?; // Sign the new metadata event let event = EventBuilder::metadata(&new_metadata).sign(&signer).await?; // Send event to user's write relayss - client.send_event_to(write_relays, &event).await?; + client.send_event_to(urls, &event).await?; // Return the updated profile let metadata = Metadata::from_json(&event.content).unwrap_or_default(); diff --git a/crates/coop/src/views/setup_relay.rs b/crates/coop/src/views/setup_relay.rs index c1205e7..cbc2809 100644 --- a/crates/coop/src/views/setup_relay.rs +++ b/crates/coop/src/views/setup_relay.rs @@ -164,6 +164,7 @@ impl SetupRelay { let relays = self.relays.clone(); let task: Task> = cx.background_spawn(async move { + let urls = write_relays.await; let signer = client.signer().await?; let tags: Vec = relays @@ -177,7 +178,7 @@ impl SetupRelay { .await?; // Set messaging relays - client.send_event_to(write_relays, &event).await?; + client.send_event_to(urls, &event).await?; // Connect to messaging relays for relay in relays.iter() { diff --git a/crates/person/src/lib.rs b/crates/person/src/lib.rs index 42cb957..f04b61b 100644 --- a/crates/person/src/lib.rs +++ b/crates/person/src/lib.rs @@ -1,9 +1,14 @@ +use std::cell::RefCell; use std::collections::{HashMap, HashSet}; +use std::rc::Rc; +use std::time::Duration; +use anyhow::{anyhow, Error}; +use common::{EventUtils, BOOTSTRAP_RELAYS}; use gpui::{App, AppContext, Context, Entity, Global, Task}; use nostr_sdk::prelude::*; use smallvec::{smallvec, SmallVec}; -use state::NostrRegistry; +use state::{NostrRegistry, TIMEOUT}; pub fn init(cx: &mut App) { PersonRegistry::set_global(cx.new(PersonRegistry::new), cx); @@ -19,8 +24,14 @@ pub struct PersonRegistry { /// Collection of all persons (user profiles) persons: HashMap>, + /// Set of public keys that have been seen + seen: Rc>>, + + /// Sender for requesting metadata + sender: flume::Sender, + /// Tasks for asynchronous operations - _tasks: SmallVec<[Task<()>; 3]>, + _tasks: SmallVec<[Task<()>; 4]>, } impl PersonRegistry { @@ -41,6 +52,7 @@ impl PersonRegistry { // Channel for communication between nostr and gpui let (tx, rx) = flume::bounded::(100); + let (mta_tx, mta_rx) = flume::bounded::(100); let mut tasks = smallvec![]; @@ -49,7 +61,20 @@ impl PersonRegistry { cx.background_spawn({ let client = client.clone(); - async move { Self::handle_notifications(&client, &tx).await } + async move { + Self::handle_notifications(&client, &tx).await; + } + }), + ); + + tasks.push( + // Handle metadata requests + cx.background_spawn({ + let client = client.clone(); + + async move { + Self::handle_requests(&client, &mta_rx).await; + } }), ); @@ -89,6 +114,8 @@ impl PersonRegistry { Self { persons: HashMap::new(), + seen: Rc::new(RefCell::new(HashSet::new())), + sender: mta_tx, _tasks: tasks, } } @@ -110,17 +137,82 @@ impl PersonRegistry { continue; } - // Only process metadata events - if event.kind == Kind::Metadata { - let metadata = Metadata::from_json(&event.content).unwrap_or_default(); - let profile = Profile::new(event.pubkey, metadata); + match event.kind { + Kind::Metadata => { + let metadata = Metadata::from_json(&event.content).unwrap_or_default(); + let profile = Profile::new(event.pubkey, metadata); - tx.send_async(profile).await.ok(); - }; + tx.send_async(profile).await.ok(); + } + Kind::ContactList => { + let public_keys = event.extract_public_keys(); + + Self::get_metadata(client, public_keys).await.ok(); + } + _ => {} + } } } } + /// Handle request for metadata + async fn handle_requests(client: &Client, rx: &flume::Receiver) { + let mut batch: HashSet = HashSet::new(); + + loop { + match flume::Selector::new() + .recv(rx, |result| result.ok()) + .wait_timeout(Duration::from_secs(2)) + { + Ok(Some(public_key)) => { + log::info!("Received public key: {}", public_key); + batch.insert(public_key); + // Process the batch if it's full + if batch.len() >= 20 { + Self::get_metadata(client, std::mem::take(&mut batch)) + .await + .ok(); + } + } + _ => { + Self::get_metadata(client, std::mem::take(&mut batch)) + .await + .ok(); + } + } + } + } + + /// Get metadata for all public keys in a event + async fn get_metadata(client: &Client, public_keys: I) -> Result<(), Error> + where + I: IntoIterator, + { + let authors: Vec = public_keys.into_iter().collect(); + let limit = authors.len(); + + if authors.is_empty() { + return Err(anyhow!("You need at least one public key")); + } + + // Construct the subscription option + let opts = SubscribeAutoCloseOptions::default() + .exit_policy(ReqExitPolicy::ExitOnEOSE) + .timeout(Some(Duration::from_secs(TIMEOUT))); + + // Construct the filter for metadata + let filter = Filter::new() + .kind(Kind::Metadata) + .authors(authors) + .limit(limit); + + client + .subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts)) + .await?; + + Ok(()) + } + /// Load all user profiles from the database async fn load_persons(client: &Client) -> Result, Error> { let filter = Filter::new().kind(Kind::Metadata).limit(200); @@ -165,10 +257,26 @@ impl PersonRegistry { /// Get single person by public key pub fn get(&self, public_key: &PublicKey, cx: &App) -> Profile { - self.persons - .get(public_key) - .map(|e| e.read(cx)) - .cloned() - .unwrap_or(Profile::new(public_key.to_owned(), Metadata::default())) + if let Some(profile) = self.persons.get(public_key) { + return profile.read(cx).clone(); + } + + let public_key = *public_key; + let mut seen = self.seen.borrow_mut(); + + if seen.insert(public_key) { + let sender = self.sender.clone(); + + // Spawn background task to request metadata + cx.background_spawn(async move { + if let Err(e) = sender.send_async(public_key).await { + log::warn!("Failed to send public key for metadata request: {}", e); + } + }) + .detach(); + } + + // Return a temporary profile with default metadata + Profile::new(public_key, Metadata::default()) } } diff --git a/crates/state/src/device.rs b/crates/state/src/device.rs new file mode 100644 index 0000000..d0a1ab7 --- /dev/null +++ b/crates/state/src/device.rs @@ -0,0 +1,34 @@ +use gpui::SharedString; +use nostr_sdk::prelude::*; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Announcement { + id: EventId, + public_key: PublicKey, + client_name: Option, +} + +impl Announcement { + pub fn new(id: EventId, client_name: Option, public_key: PublicKey) -> Self { + Self { + id, + client_name, + public_key, + } + } + + pub fn id(&self) -> EventId { + self.id + } + + pub fn public_key(&self) -> PublicKey { + self.public_key + } + + pub fn client_name(&self) -> SharedString { + self.client_name + .as_ref() + .map(SharedString::from) + .unwrap_or(SharedString::from("Unknown")) + } +} diff --git a/crates/state/src/identity.rs b/crates/state/src/identity.rs index f594602..fccc202 100644 --- a/crates/state/src/identity.rs +++ b/crates/state/src/identity.rs @@ -1,5 +1,7 @@ use nostr_sdk::prelude::*; +use crate::Announcement; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum RelayState { #[default] @@ -19,6 +21,9 @@ pub struct Identity { /// The public key of the account public_key: Option, + /// Encryption key announcement + announcement: Option, + /// Status of the current user NIP-65 relays relay_list: RelayState, @@ -36,6 +41,7 @@ impl Identity { pub fn new() -> Self { Self { public_key: None, + announcement: None, relay_list: RelayState::default(), messaging_relays: RelayState::default(), } diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 3620635..fdebe53 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -7,10 +7,12 @@ use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task}; use nostr_lmdb::NostrLmdb; use nostr_sdk::prelude::*; +mod device; mod event; mod gossip; mod identity; +pub use device::*; pub use event::*; pub use gossip::*; pub use identity::*; @@ -116,15 +118,14 @@ impl NostrRegistry { subscriptions.push( // Observe the identity entity cx.observe(&identity, |this, state, cx| { - let identity = state.read(cx); - - if identity.has_public_key() { - match identity.relay_list_state() { + if state.read(cx).has_public_key() { + match state.read(cx).relay_list_state() { RelayState::Initial => { this.get_relay_list(cx); } - RelayState::Set => match identity.messaging_relays_state() { + RelayState::Set => match state.read(cx).messaging_relays_state() { RelayState::Initial => { + this.get_profile(cx); this.get_messaging_relays(cx); } RelayState::Set => { @@ -138,30 +139,6 @@ impl NostrRegistry { }), ); - tasks.push( - // Establish connection to the bootstrap relays - cx.background_spawn({ - let client = client.clone(); - - async move { - // Add bootstrap relay to the relay pool - for url in BOOTSTRAP_RELAYS.into_iter() { - client.add_relay(url).await?; - } - - // Add search relay to the relay pool - for url in SEARCH_RELAYS.into_iter() { - client.add_relay(url).await?; - } - - // Connect to all added relays - client.connect().await; - - Ok(()) - } - }), - ); - tasks.push( // Handle nostr notifications cx.background_spawn({ @@ -208,6 +185,19 @@ impl NostrRegistry { // Handle nostr notifications async fn handle_notifications(client: &Client, tx: &flume::Sender) -> Result<(), Error> { + // Add bootstrap relay to the relay pool + for url in BOOTSTRAP_RELAYS.into_iter() { + client.add_relay(url).await?; + } + + // Add search relay to the relay pool + for url in SEARCH_RELAYS.into_iter() { + client.add_relay(url).await?; + } + + // Connect to all added relays + client.connect().await; + let mut notifications = client.notifications(); let mut processed_events = HashSet::new(); @@ -281,7 +271,7 @@ impl NostrRegistry { // Ensure relay connections for relay in write_relays.iter() { - client.add_write_relay(*relay).await?; + client.add_relay(*relay).await?; client.connect_relay(*relay).await?; } @@ -347,57 +337,51 @@ impl NostrRegistry { } /// Get a list of write relays for a given public key - pub fn write_relays(&self, public_key: &PublicKey, cx: &App) -> Vec { + pub fn write_relays(&self, public_key: &PublicKey, cx: &App) -> Task> { let client = self.client(); let relays = self.gossip.read(cx).write_relays(public_key); - let async_relays = relays.clone(); - // Ensure relay connections cx.background_spawn(async move { - for url in async_relays.iter() { - client.add_write_relay(url).await.ok(); - client.connect_relay(url).await.ok(); - } - }) - .detach(); - - relays - } - - /// Get a list of read relays for a given public key - pub fn read_relays(&self, public_key: &PublicKey, cx: &App) -> Vec { - let client = self.client(); - let relays = self.gossip.read(cx).read_relays(public_key); - let async_relays = relays.clone(); - - // Ensure relay connections - cx.background_spawn(async move { - for url in async_relays.iter() { - client.add_read_relay(url).await.ok(); - client.connect_relay(url).await.ok(); - } - }) - .detach(); - - relays - } - - /// Get a list of messaging relays for a given public key - pub fn messaging_relays(&self, public_key: &PublicKey, cx: &App) -> Vec { - let client = self.client(); - let relays = self.gossip.read(cx).messaging_relays(public_key); - let async_relays = relays.clone(); - - // Ensure relay connections - cx.background_spawn(async move { - for url in async_relays.iter() { + // Ensure relay connections + for url in relays.iter() { client.add_relay(url).await.ok(); client.connect_relay(url).await.ok(); } - }) - .detach(); - relays + relays + }) + } + + /// Get a list of read relays for a given public key + pub fn read_relays(&self, public_key: &PublicKey, cx: &App) -> Task> { + let client = self.client(); + let relays = self.gossip.read(cx).read_relays(public_key); + + cx.background_spawn(async move { + // Ensure relay connections + for url in relays.iter() { + client.add_relay(url).await.ok(); + client.connect_relay(url).await.ok(); + } + + relays + }) + } + + /// Get a list of messaging relays for a given public key + pub fn messaging_relays(&self, public_key: &PublicKey, cx: &App) -> Task> { + let client = self.client(); + let relays = self.gossip.read(cx).messaging_relays(public_key); + + cx.background_spawn(async move { + // Ensure relay connections + for url in relays.iter() { + client.add_relay(url).await.ok(); + client.connect_relay(url).await.ok(); + } + + relays + }) } /// Set the signer for the nostr client and verify the public key @@ -479,9 +463,14 @@ impl NostrRegistry { .await?; while let Some((_url, res)) = stream.next().await { - if let Ok(event) = res { - log::info!("Received relay list event: {event:?}"); - return Ok(RelayState::Set); + match res { + Ok(event) => { + log::info!("Received relay list event: {event:?}"); + return Ok(RelayState::Set); + } + Err(e) => { + log::error!("Failed to receive relay list event: {e}"); + } } } @@ -507,6 +496,48 @@ impl NostrRegistry { })); } + /// Get profile and contact list for current user + fn get_profile(&mut self, cx: &mut Context) { + let client = self.client(); + let public_key = self.identity().read(cx).public_key(); + let write_relays = self.write_relays(&public_key, cx); + + let task: Task> = cx.background_spawn(async move { + let mut urls = vec![]; + urls.extend(write_relays.await); + urls.extend( + BOOTSTRAP_RELAYS + .iter() + .filter_map(|url| RelayUrl::parse(url).ok()), + ); + + // Construct subscription options + let opts = SubscribeAutoCloseOptions::default() + .exit_policy(ReqExitPolicy::ExitOnEOSE) + .timeout(Some(Duration::from_secs(TIMEOUT))); + + // Filter for metadata + let metadata = Filter::new() + .kind(Kind::Metadata) + .limit(1) + .author(public_key); + + // Filter for contact list + let contact_list = Filter::new() + .kind(Kind::ContactList) + .limit(1) + .author(public_key); + + client + .subscribe_to(urls, vec![metadata, contact_list], Some(opts)) + .await?; + + Ok(()) + }); + + task.detach(); + } + /// Get messaging relays for current user fn get_messaging_relays(&mut self, cx: &mut Context) { let client = self.client(); @@ -515,19 +546,28 @@ impl NostrRegistry { let write_relays = self.write_relays(&public_key, cx); let task: Task> = cx.background_spawn(async move { + let urls = write_relays.await; + + // Construct the filter for inbox relays let filter = Filter::new() .kind(Kind::InboxRelays) .author(public_key) .limit(1); + // Stream events from the write relays let mut stream = client - .stream_events_from(write_relays, vec![filter], Duration::from_secs(TIMEOUT)) + .stream_events_from(urls, vec![filter], Duration::from_secs(TIMEOUT)) .await?; while let Some((_url, res)) = stream.next().await { - if let Ok(event) = res { - log::info!("Received messaging relays event: {event:?}"); - return Ok(RelayState::Set); + match res { + Ok(event) => { + log::info!("Received messaging relays event: {event:?}"); + return Ok(RelayState::Set); + } + Err(e) => { + log::error!("Failed to get messaging relays: {e}"); + } } } @@ -560,11 +600,12 @@ impl NostrRegistry { let messaging_relays = self.messaging_relays(&public_key, cx); cx.background_spawn(async move { + let urls = messaging_relays.await; let id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION); let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); if let Err(e) = client - .subscribe_with_id_to(messaging_relays, id, vec![filter], None) + .subscribe_with_id_to(urls, id, vec![filter], None) .await { log::error!("Failed to subscribe to gift wrap events: {e}"); @@ -573,14 +614,6 @@ impl NostrRegistry { .detach(); } - /// Publish an event to author's write relays - pub fn publish(&self, event: Event, cx: &App) -> Task, Error>> { - let client = self.client(); - let write_relays = self.write_relays(&event.pubkey, cx); - - cx.background_spawn(async move { Ok(client.send_event_to(&write_relays, &event).await?) }) - } - /// Subscribe to event kinds to author's write relays pub fn subscribe(&self, kinds: I, author: PublicKey, cx: &App) where @@ -596,16 +629,15 @@ impl NostrRegistry { .map(|kind| Filter::new().kind(kind).author(author).limit(1)) .collect(); - // Construct subscription options - let opts = SubscribeAutoCloseOptions::default() - .timeout(Some(Duration::from_secs(TIMEOUT))) - .exit_policy(ReqExitPolicy::ExitOnEOSE); - cx.background_spawn(async move { - if let Err(e) = client - .subscribe_to(&write_relays, filters, Some(opts)) - .await - { + let urls = write_relays.await; + + // Construct subscription options + let opts = SubscribeAutoCloseOptions::default() + .timeout(Some(Duration::from_secs(TIMEOUT))) + .exit_policy(ReqExitPolicy::ExitOnEOSE); + + if let Err(e) = client.subscribe_to(urls, filters, Some(opts)).await { log::error!("Failed to create a subscription: {e}"); }; })