From 32a0401907b499999cdacccca2dedd3848893ede Mon Sep 17 00:00:00 2001 From: reya Date: Fri, 17 Oct 2025 08:51:34 +0700 Subject: [PATCH] chore: simplify codebase --- Cargo.lock | 557 +++++++++++--------------- crates/app_state/src/lib.rs | 2 +- crates/app_state/src/state/gossip.rs | 332 --------------- crates/app_state/src/state/mod.rs | 252 +++++++++--- crates/coop/src/chatspace.rs | 10 +- crates/coop/src/views/edit_profile.rs | 7 +- crates/coop/src/views/new_account.rs | 8 +- crates/coop/src/views/setup_relay.rs | 6 +- crates/registry/src/room.rs | 40 +- crates/ui/Cargo.toml | 2 +- crates/ui/src/input/rope_ext.rs | 6 +- crates/ui/src/input/state.rs | 2 +- 12 files changed, 489 insertions(+), 735 deletions(-) delete mode 100644 crates/app_state/src/state/gossip.rs diff --git a/Cargo.lock b/Cargo.lock index 882ed66..fb090e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -567,31 +558,15 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.32.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b715a6010afb9e457ca2b7c9d2b9c344baa8baed7b38dc476034c171b32575" +checksum = "107a4e9d9cab9963e04e84bb8dee0e25f2a987f9a8bad5ed054abd439caa8f8c" dependencies = [ "bindgen 0.72.1", "cc", "cmake", "dunce", "fs_extra", - "libloading", -] - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link 0.2.1", ] [[package]] @@ -1036,9 +1011,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1205,6 +1180,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "collections" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "indexmap", + "rustc-hash 2.1.1", + "workspace-hack", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -1637,6 +1622,17 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "derive_refineable" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "workspace-hack", +] + [[package]] name = "digest" version = "0.10.7" @@ -2385,9 +2381,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -2395,12 +2391,12 @@ dependencies = [ [[package]] name = "gethostname" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.2", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -2412,21 +2408,21 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] @@ -2440,12 +2436,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "glob" version = "0.3.3" @@ -2454,9 +2444,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +checksum = "eab69130804d941f8075cfd713bf8848a2c3b3f201a9457a11e6f87e1ab62305" dependencies = [ "aho-corasick", "bstr", @@ -2532,8 +2522,8 @@ dependencies = [ [[package]] name = "gpui" -version = "0.2.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +version = "0.2.1" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "anyhow", "as-raw-xcb-connection", @@ -2549,6 +2539,7 @@ dependencies = [ "calloop-wayland-source", "cbindgen", "cocoa 0.26.1", + "collections", "core-foundation 0.10.1", "core-foundation-sys", "core-graphics 0.24.0", @@ -2563,13 +2554,15 @@ dependencies = [ "flume", "foreign-types 0.5.0", "futures", - "gpui-macros", + "gpui_macros", + "http_client", "image", "inventory", "itertools 0.14.0", "libc", "log", "lyon", + "media", "metal", "naga", "num_cpus", @@ -2583,9 +2576,11 @@ dependencies = [ "profiling", "rand 0.9.2", "raw-window-handle", + "refineable", "resvg", "schemars", "seahash", + "semantic_version", "serde", "serde_json", "slotmap", @@ -2593,9 +2588,12 @@ dependencies = [ "smol", "stacksafe", "strum 0.27.2", + "sum_tree", "taffy", "thiserror 2.0.17", "usvg", + "util", + "util_macros", "uuid", "waker-fn", "wayland-backend", @@ -2611,23 +2609,15 @@ dependencies = [ "x11-clipboard", "x11rb", "xkbcommon", - "zed-collections", "zed-font-kit", - "zed-http-client", - "zed-media", - "zed-refineable", "zed-scap", - "zed-semantic-version", - "zed-sum-tree", - "zed-util", - "zed-util-macros", "zed-xim", ] [[package]] -name = "gpui-macros" +name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -2639,13 +2629,13 @@ dependencies = [ [[package]] name = "gpui_tokio" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "anyhow", "gpui", "tokio", + "util", "workspace-hack", - "zed-util", ] [[package]] @@ -2675,9 +2665,9 @@ dependencies = [ [[package]] name = "half" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54c115d4f30f52c67202f079c5f9d8b49db4691f460fdb0b4c2e838261b2ba5" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", @@ -2866,10 +2856,36 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http_client" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "anyhow", + "async-compression", + "async-fs", + "async-tar", + "bytes", + "derive_more", + "futures", + "http", + "http-body", + "log", + "parking_lot", + "serde", + "serde_json", + "sha2", + "tempfile", + "url", + "util", + "workspace-hack", + "zed-reqwest", +] + [[package]] name = "http_client_tls" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "rustls", "rustls-platform-verifier", @@ -3110,9 +3126,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +checksum = "81776e6f9464432afcc28d03e52eb101c93b6f0566f52aef2427663e700f0403" dependencies = [ "crossbeam-deque", "globset", @@ -3245,17 +3261,6 @@ dependencies = [ "leaky-cow", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -3361,7 +3366,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] @@ -3453,12 +3458,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.5", + "windows-link 0.2.1", ] [[package]] @@ -3569,9 +3574,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe949189f46fabb938b3a9a0be30fdd93fd8a09260da863399a8cf3db756ec8" +checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" [[package]] name = "lru-slab" @@ -3679,6 +3684,22 @@ dependencies = [ "digest", ] +[[package]] +name = "media" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "anyhow", + "bindgen 0.71.1", + "core-foundation 0.10.1", + "core-video", + "ctor 0.4.3", + "foreign-types 0.5.0", + "metal", + "objc", + "workspace-hack", +] + [[package]] name = "memchr" version = "2.7.6" @@ -3778,7 +3799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.59.0", ] @@ -3914,7 +3935,7 @@ dependencies = [ [[package]] name = "nostr" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "aes", "base64", @@ -3938,7 +3959,7 @@ dependencies = [ [[package]] name = "nostr-connect" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "async-utility", "nostr", @@ -3950,7 +3971,7 @@ dependencies = [ [[package]] name = "nostr-database" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "flatbuffers", "lru", @@ -3961,7 +3982,7 @@ dependencies = [ [[package]] name = "nostr-lmdb" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "async-utility", "flume", @@ -3975,7 +3996,7 @@ dependencies = [ [[package]] name = "nostr-relay-pool" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "async-utility", "async-wsocket", @@ -3992,13 +4013,14 @@ dependencies = [ [[package]] name = "nostr-sdk" version = "0.43.0" -source = "git+https://github.com/rust-nostr/nostr#506cb68f53afad23ce2cdc2bad9a75643bcb7371" +source = "git+https://github.com/rust-nostr/nostr#a499845dce2b16f52c0350771fe60608da887435" dependencies = [ "async-utility", "nostr", "nostr-database", "nostr-relay-pool", "tokio", + "tracing", ] [[package]] @@ -4265,15 +4287,6 @@ dependencies = [ "objc", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -4304,7 +4317,7 @@ dependencies = [ "endi", "futures-lite 2.6.1", "futures-util", - "getrandom 0.3.3", + "getrandom 0.3.4", "hkdf", "hmac", "md-5", @@ -4340,9 +4353,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" dependencies = [ "bitflags 2.9.4", "cfg-if", @@ -4372,9 +4385,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" dependencies = [ "cc", "libc", @@ -4505,6 +4518,17 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "perf" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "collections", + "serde", + "serde_json", + "workspace-hack", +] + [[package]] name = "phf" version = "0.11.3" @@ -4856,7 +4880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring", @@ -4955,7 +4979,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -5111,11 +5135,20 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "refineable" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "derive_refineable", + "workspace-hack", +] + [[package]] name = "regex" -version = "1.12.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a52d8d02cacdb176ef4678de6c052efb4b3da14b78e4db683a4252762be5433" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -5125,9 +5158,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722166aa0d7438abbaa4d5cc2c649dac844e8c56d82fb3d33e9c34b5cd268fc6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -5136,9 +5169,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3160422bbd54dd5ecfdca71e5fd59b7b8fe2b1697ab2baf64f6d05dcc66d298" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "registry" @@ -5160,9 +5193,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64", "bytes", @@ -5210,18 +5243,18 @@ dependencies = [ [[package]] name = "reqwest_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "anyhow", "bytes", "futures", + "http_client", "http_client_tls", "log", "regex", "serde", "tokio", "workspace-hack", - "zed-http-client", "zed-reqwest", ] @@ -5265,16 +5298,16 @@ dependencies = [ [[package]] name = "rope" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" dependencies = [ "arrayvec", "log", "rayon", "smallvec", + "sum_tree", "unicode-segmentation", + "util", "workspace-hack", - "zed-sum-tree", - "zed-util", ] [[package]] @@ -5382,12 +5415,6 @@ dependencies = [ "ordered-multimap", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -5453,9 +5480,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -5736,6 +5763,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" +[[package]] +name = "semantic_version" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "anyhow", + "serde", + "workspace-hack", +] + [[package]] name = "semver" version = "1.0.27" @@ -6048,12 +6085,12 @@ checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -6178,6 +6215,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "sum_tree" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "arrayvec", + "log", + "rayon", + "workspace-hack", +] + [[package]] name = "sval" version = "2.15.0" @@ -6445,7 +6493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand 2.3.0", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix 1.1.2", "windows-sys 0.61.2", @@ -6655,27 +6703,24 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -7041,10 +7086,10 @@ dependencies = [ "serde_json", "smallvec", "smol", + "sum_tree", "theme", "unicode-segmentation", "uuid", - "zed-sum-tree", ] [[package]] @@ -7207,13 +7252,60 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "util" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "anyhow", + "async-fs", + "async_zip", + "collections", + "command-fds", + "dirs 4.0.0", + "dunce", + "futures", + "futures-lite 1.13.0", + "globset", + "itertools 0.14.0", + "libc", + "log", + "nix 0.29.0", + "regex", + "rust-embed", + "schemars", + "serde", + "serde_json", + "serde_json_lenient", + "shlex", + "smol", + "take-until", + "tempfile", + "tendril", + "unicase", + "walkdir", + "which", + "workspace-hack", +] + +[[package]] +name = "util_macros" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed#908ae95cf86930893140bee37cf37c8918ac90e8" +dependencies = [ + "perf", + "quote", + "syn 2.0.106", + "workspace-hack", +] + [[package]] name = "uuid" version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "sha1_smol", @@ -7342,15 +7434,6 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -7570,9 +7653,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf4f3c0ba838e82b4e5ccc4157003fb8c324ee24c058470ffb82820becbde98" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" dependencies = [ "core-foundation 0.10.1", "jni", @@ -8434,9 +8517,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d07e46d035fb8e375b2ce63ba4e4ff90a7f73cf2ffb0138b29e1158d2eaadf7" +checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" dependencies = [ "async-broadcast", "async-executor", @@ -8458,7 +8541,8 @@ dependencies = [ "serde_repr", "tracing", "uds_windows", - "windows-sys 0.60.2", + "uuid", + "windows-sys 0.61.2", "winnow", "zbus_macros", "zbus_names", @@ -8467,9 +8551,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e797a9c847ed3ccc5b6254e8bcce056494b375b511b3d6edcec0aeb4defaca" +checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -8492,27 +8576,6 @@ dependencies = [ "zvariant", ] -[[package]] -name = "zed-collections" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "indexmap", - "rustc-hash 2.1.1", - "workspace-hack", -] - -[[package]] -name = "zed-derive-refineable" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "workspace-hack", -] - [[package]] name = "zed-font-kit" version = "0.14.1-zed" @@ -8537,68 +8600,6 @@ dependencies = [ "yeslogic-fontconfig-sys", ] -[[package]] -name = "zed-http-client" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "anyhow", - "async-compression", - "async-fs", - "async-tar", - "bytes", - "derive_more", - "futures", - "http", - "http-body", - "log", - "parking_lot", - "serde", - "serde_json", - "sha2", - "tempfile", - "url", - "workspace-hack", - "zed-reqwest", - "zed-util", -] - -[[package]] -name = "zed-media" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "anyhow", - "bindgen 0.71.1", - "core-foundation 0.10.1", - "core-video", - "ctor 0.4.3", - "foreign-types 0.5.0", - "metal", - "objc", - "workspace-hack", -] - -[[package]] -name = "zed-perf" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "serde", - "serde_json", - "workspace-hack", - "zed-collections", -] - -[[package]] -name = "zed-refineable" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "workspace-hack", - "zed-derive-refineable", -] - [[package]] name = "zed-reqwest" version = "0.12.15-zed" @@ -8669,74 +8670,6 @@ dependencies = [ "xcb", ] -[[package]] -name = "zed-semantic-version" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "anyhow", - "serde", - "workspace-hack", -] - -[[package]] -name = "zed-sum-tree" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "arrayvec", - "log", - "rayon", - "workspace-hack", -] - -[[package]] -name = "zed-util" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "anyhow", - "async-fs", - "async_zip", - "command-fds", - "dirs 4.0.0", - "dunce", - "futures", - "futures-lite 1.13.0", - "globset", - "itertools 0.14.0", - "libc", - "log", - "nix 0.29.0", - "regex", - "rust-embed", - "schemars", - "serde", - "serde_json", - "serde_json_lenient", - "shlex", - "smol", - "take-until", - "tempfile", - "tendril", - "unicase", - "walkdir", - "which", - "workspace-hack", - "zed-collections", -] - -[[package]] -name = "zed-util-macros" -version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#998fece3af752121c2aa336588934d86958547b5" -dependencies = [ - "quote", - "syn 2.0.106", - "workspace-hack", - "zed-perf", -] - [[package]] name = "zed-xim" version = "0.4.0-zed" @@ -8876,9 +8809,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.7.0" +version = "5.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db" +checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" dependencies = [ "endi", "enumflags2", @@ -8891,9 +8824,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.7.0" +version = "5.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e" +checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/crates/app_state/src/lib.rs b/crates/app_state/src/lib.rs index 9747d27..ea5090d 100644 --- a/crates/app_state/src/lib.rs +++ b/crates/app_state/src/lib.rs @@ -34,7 +34,7 @@ pub fn nostr_client() -> &'static Client { let lmdb = NostrLMDB::open(nostr_file()).expect("Database is NOT initialized"); let opts = ClientOptions::new() - .gossip(false) + .gossip(true) .automatic_authentication(false) .verify_subscriptions(false) .sleep_when_idle(SleepWhenIdle::Enabled { diff --git a/crates/app_state/src/state/gossip.rs b/crates/app_state/src/state/gossip.rs deleted file mode 100644 index 02dc825..0000000 --- a/crates/app_state/src/state/gossip.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::time::Duration; - -use anyhow::{anyhow, Error}; -use nostr_sdk::prelude::*; - -use crate::constants::BOOTSTRAP_RELAYS; -use crate::state::SignalKind; -use crate::{app_state, nostr_client}; - -#[derive(Debug, Clone, Default)] -pub struct Gossip { - pub nip17: HashMap>, - pub nip65: HashMap)>>, -} - -impl Gossip { - /// Parse and insert NIP-65 or NIP-17 relays into the gossip state. - pub fn insert(&mut self, event: &Event) { - match event.kind { - Kind::InboxRelays => { - let urls: Vec = nip17::extract_relay_list(event).cloned().collect(); - - if !urls.is_empty() { - self.nip17.entry(event.pubkey).or_default().extend(urls); - } - } - Kind::RelayList => { - let urls: Vec<(RelayUrl, Option)> = nip65::extract_relay_list(event) - .map(|(url, metadata)| (url.to_owned(), metadata.to_owned())) - .collect(); - - if !urls.is_empty() { - self.nip65.entry(event.pubkey).or_default().extend(urls); - } - } - _ => {} - } - } - - /// Get all write relays for a given public key - pub fn write_relays(&self, public_key: &PublicKey) -> Vec<&RelayUrl> { - self.nip65 - .get(public_key) - .map(|relays| { - relays - .iter() - .filter(|(_, metadata)| metadata.as_ref() == Some(&RelayMetadata::Write)) - .map(|(url, _)| url) - .take(3) - .collect() - }) - .unwrap_or_default() - } - - /// Get all read relays for a given public key - pub fn read_relays(&self, public_key: &PublicKey) -> Vec<&RelayUrl> { - self.nip65 - .get(public_key) - .map(|relays| { - relays - .iter() - .filter(|(_, metadata)| metadata.as_ref() == Some(&RelayMetadata::Read)) - .map(|(url, _)| url) - .take(3) - .collect() - }) - .unwrap_or_default() - } - - /// Get all messaging relays for a given public key - pub fn messaging_relays(&self, public_key: &PublicKey) -> Vec<&RelayUrl> { - self.nip17 - .get(public_key) - .map(|relays| relays.iter().collect()) - .unwrap_or_default() - } - - /// Get and verify NIP-65 relays for a given public key - /// - /// Only fetch from the public relays - pub async fn get_nip65(&self, public_key: PublicKey) -> Result<(), Error> { - let client = nostr_client(); - let timeout = Duration::from_secs(5); - let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); - - let filter = Filter::new() - .kind(Kind::RelayList) - .author(public_key) - .limit(1); - - // Subscribe to events from the bootstrapping relays - client - .subscribe_to(BOOTSTRAP_RELAYS, filter.clone(), Some(opts)) - .await?; - - // Verify the received data after a timeout - smol::spawn(async move { - smol::Timer::after(timeout).await; - - if client.database().count(filter).await.unwrap_or(0) < 1 { - app_state() - .signal - .send(SignalKind::GossipRelaysNotFound) - .await; - } - }) - .detach(); - - Ok(()) - } - - /// Set NIP-65 relays for a current user - pub async fn set_nip65( - &mut self, - relays: &[(RelayUrl, Option)], - ) -> Result<(), Error> { - let client = nostr_client(); - let signer = client.signer().await?; - - let tags: Vec = relays - .iter() - .map(|(url, metadata)| Tag::relay_metadata(url.to_owned(), metadata.to_owned())) - .collect(); - - let event = EventBuilder::new(Kind::RelayList, "") - .tags(tags) - .sign(&signer) - .await?; - - // Send event to the public relays - client.send_event_to(BOOTSTRAP_RELAYS, &event).await?; - - // Update gossip data - for relay in relays { - self.nip65 - .entry(event.pubkey) - .or_default() - .insert(relay.to_owned()); - } - - // Get NIP-17 relays - self.get_nip17(event.pubkey).await?; - - Ok(()) - } - - /// Get and verify NIP-17 relays for a given public key - /// - /// Only fetch from public key's write relays - pub async fn get_nip17(&self, public_key: PublicKey) -> Result<(), Error> { - let client = nostr_client(); - let timeout = Duration::from_secs(5); - let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); - - let urls = self.write_relays(&public_key); - - // Ensure user's have at least one write relay - if urls.is_empty() { - return Err(anyhow!("Write relays are empty")); - } - - // Ensure connection to relays - for url in urls.iter().cloned() { - client.add_relay(url).await?; - client.connect_relay(url).await?; - } - - let filter = Filter::new() - .kind(Kind::InboxRelays) - .author(public_key) - .limit(1); - - // Subscribe to events from the bootstrapping relays - client - .subscribe_to(urls, filter.clone(), Some(opts)) - .await?; - - // Verify the received data after a timeout - smol::spawn(async move { - smol::Timer::after(timeout).await; - - if client.database().count(filter).await.unwrap_or(0) < 1 { - app_state() - .signal - .send(SignalKind::MessagingRelaysNotFound) - .await; - } - }) - .detach(); - - Ok(()) - } - - /// Set NIP-17 relays for a current user - pub async fn set_nip17(&mut self, relays: &[RelayUrl]) -> Result<(), Error> { - let client = nostr_client(); - let signer = client.signer().await?; - let public_key = signer.get_public_key().await?; - - let urls = self.write_relays(&public_key); - - // Ensure user's have at least one relay - if urls.is_empty() { - return Err(anyhow!("Relays are empty")); - } - - // Ensure connection to relays - for url in urls.iter().cloned() { - client.add_relay(url).await?; - client.connect_relay(url).await?; - } - - let event = EventBuilder::new(Kind::InboxRelays, "") - .tags(relays.iter().map(|relay| Tag::relay(relay.to_owned()))) - .sign(&signer) - .await?; - - // Send event to the public relays - client.send_event_to(urls, &event).await?; - - // Update gossip data - for relay in relays { - self.nip17 - .entry(event.pubkey) - .or_default() - .insert(relay.to_owned()); - } - - // Run inbox monitor - self.monitor_inbox(event.pubkey).await?; - - Ok(()) - } - - /// Subscribe for events that match the given kind for a given author - /// - /// Only fetch from author's write relays - pub async fn subscribe(&self, public_key: PublicKey, kind: Kind) -> Result<(), Error> { - let client = nostr_client(); - let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); - - let filter = Filter::new().author(public_key).kind(kind).limit(1); - let urls = self.write_relays(&public_key); - - // Ensure user's have at least one write relay - if urls.is_empty() { - return Err(anyhow!("Write relays are empty")); - } - - // Ensure connection to relays - for url in urls.iter().cloned() { - client.add_relay(url).await?; - client.connect_relay(url).await?; - } - - // Subscribe to filters to user's write relays - client.subscribe_to(urls, filter, Some(opts)).await?; - - Ok(()) - } - - /// Bulk subscribe to metadata events for a list of public keys - /// - /// Only fetch from the public relays - pub async fn bulk_subscribe(&self, public_keys: HashSet) -> Result<(), Error> { - if public_keys.is_empty() { - return Err(anyhow!("You need at least one public key")); - } - - let client = nostr_client(); - let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); - - let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList]; - let limit = public_keys.len() * kinds.len() + 20; - - let filter = Filter::new().authors(public_keys).kinds(kinds).limit(limit); - let urls = BOOTSTRAP_RELAYS; - - // Subscribe to filters to the bootstrap relays - client.subscribe_to(urls, filter, Some(opts)).await?; - - Ok(()) - } - - /// Monitor all gift wrap events in the messaging relays for a given public key - pub async fn monitor_inbox(&self, public_key: PublicKey) -> Result<(), Error> { - let client = nostr_client(); - let id = SubscriptionId::new("inbox"); - let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); - let urls = self.messaging_relays(&public_key); - - // Ensure user's have at least one messaging relay - if urls.is_empty() { - return Err(anyhow!("Messaging relays are empty")); - } - - // Ensure connection to relays - for url in urls.iter().cloned() { - client.add_relay(url).await?; - client.connect_relay(url).await?; - } - - // Subscribe to filters to user's messaging relays - client.subscribe_with_id_to(urls, id, filter, None).await?; - - Ok(()) - } - - /// Send an event to author's write relays - pub async fn send_event_to_write_relays(&self, event: &Event) -> Result<(), Error> { - let client = nostr_client(); - let public_key = event.pubkey; - let urls = self.write_relays(&public_key); - - // Ensure user's have at least one relay - if urls.is_empty() { - return Err(anyhow!("Relays are empty")); - } - - // Ensure connection to relays - for url in urls.iter().cloned() { - client.add_relay(url).await?; - client.connect_relay(url).await?; - } - - // Send event to relays - client.send_event(event).await?; - - Ok(()) - } -} diff --git a/crates/app_state/src/state/mod.rs b/crates/app_state/src/state/mod.rs index 73c91ba..3ff5dfa 100644 --- a/crates/app_state/src/state/mod.rs +++ b/crates/app_state/src/state/mod.rs @@ -13,9 +13,6 @@ use crate::constants::{ }; use crate::nostr_client; use crate::paths::support_dir; -use crate::state::gossip::Gossip; - -mod gossip; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct AuthRequest { @@ -95,6 +92,10 @@ impl Signal { &self.rx } + pub fn sender(&self) -> &Sender { + &self.tx + } + pub async fn send(&self, kind: SignalKind) { if let Err(e) = self.tx.send_async(kind).await { log::error!("Failed to send signal: {e}"); @@ -182,9 +183,6 @@ pub struct AppState { /// Auto-close options for relay subscriptions pub auto_close_opts: Option, - /// NIP-65: https://github.com/nostr-protocol/nips/blob/master/65.md - pub gossip: RwLock, - /// Tracks activity related to Nostr events pub event_tracker: RwLock, @@ -218,7 +216,6 @@ impl AppState { gift_wrap_sub_id: SubscriptionId::new("inbox"), gift_wrap_processing: AtomicBool::new(false), auto_close_opts: Some(opts), - gossip: RwLock::new(Gossip::default()), event_tracker: RwLock::new(EventTracker::default()), } } @@ -267,59 +264,45 @@ impl AppState { match event.kind { Kind::RelayList => { - // Update NIP-65 relays for event's public key - { - let mut gossip = self.gossip.write().await; - gossip.insert(&event); - } - - let is_self_authored = Self::is_self_authored(&event).await; - // Get events if relay list belongs to current user - if is_self_authored { - let gossip = self.gossip.read().await; + if let Ok(true) = Self::is_self_authored(&event).await { + let author = event.pubkey; // Fetch user's metadata event - gossip.subscribe(event.pubkey, Kind::Metadata).await.ok(); + if let Err(e) = self.subscribe(author, Kind::Metadata).await { + log::error!("Failed to subscribe to metadata event: {e}"); + } // Fetch user's contact list event - gossip.subscribe(event.pubkey, Kind::ContactList).await.ok(); + if let Err(e) = self.subscribe(author, Kind::ContactList).await { + log::error!("Failed to subscribe to contact list event: {e}"); + } // Fetch user's messaging relays event - gossip.get_nip17(event.pubkey).await.ok(); + if let Err(e) = self.get_nip17(author).await { + log::error!("Failed to fetch messaging relays event: {e}"); + } } } Kind::InboxRelays => { - // Update NIP-17 relays for event's public key - { - let mut gossip = self.gossip.write().await; - gossip.insert(&event); - } - - let is_self_authored = Self::is_self_authored(&event).await; - // Subscribe to gift wrap events if messaging relays belong to the current user - if is_self_authored { - let gossip = self.gossip.read().await; + if let Ok(true) = Self::is_self_authored(&event).await { + let urls: Vec = + nip17::extract_relay_list(event.as_ref()).cloned().collect(); - if gossip.monitor_inbox(event.pubkey).await.is_err() { - self.signal.send(SignalKind::MessagingRelaysNotFound).await; + if let Err(e) = self.get_messages(event.pubkey, &urls).await { + log::error!("Failed to fetch messages: {e}"); } } } Kind::ContactList => { - let is_self_authored = Self::is_self_authored(&event).await; - - if is_self_authored { + if let Ok(true) = Self::is_self_authored(&event).await { let public_keys: HashSet = event.tags.public_keys().copied().collect(); - self.gossip - .read() - .await - .bulk_subscribe(public_keys) - .await - .ok(); + if let Err(e) = self.get_metadata_for_list(public_keys).await { + log::error!("Failed to get metadata for list: {e}"); + } } } Kind::Metadata => { @@ -406,17 +389,20 @@ impl AppState { // Process the batch if it's full if batch.len() >= METADATA_BATCH_LIMIT { - let gossip = self.gossip.read().await; - gossip.bulk_subscribe(std::mem::take(&mut batch)).await.ok(); + self.get_metadata_for_list(std::mem::take(&mut batch)) + .await + .ok(); } } BatchEvent::Timeout => { - let gossip = self.gossip.read().await; - gossip.bulk_subscribe(std::mem::take(&mut batch)).await.ok(); + self.get_metadata_for_list(std::mem::take(&mut batch)) + .await + .ok(); } BatchEvent::Closed => { - let gossip = self.gossip.read().await; - gossip.bulk_subscribe(std::mem::take(&mut batch)).await.ok(); + self.get_metadata_for_list(std::mem::take(&mut batch)) + .await + .ok(); // Exit the current loop break; @@ -425,18 +411,174 @@ impl AppState { } } - async fn is_self_authored(event: &Event) -> bool { + async fn is_self_authored(event: &Event) -> Result { let client = nostr_client(); + let signer = client.signer().await?; + let public_key = signer.get_public_key().await?; - let Ok(signer) = client.signer().await else { - return false; - }; + Ok(public_key == event.pubkey) + } - let Ok(public_key) = signer.get_public_key().await else { - return false; - }; + /// Subscribe for events that match the given kind for a given author + async fn subscribe(&self, author: PublicKey, kind: Kind) -> Result<(), Error> { + let client = nostr_client(); + let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + let filter = Filter::new().author(author).kind(kind).limit(1); - public_key == event.pubkey + // Subscribe to filters from the user's write relays + client.subscribe(filter, Some(opts)).await?; + + Ok(()) + } + + /// Get metadata for a list of public keys + async fn get_metadata_for_list(&self, public_keys: HashSet) -> Result<(), Error> { + if public_keys.is_empty() { + return Err(anyhow!("You need at least one public key")); + } + + let client = nostr_client(); + let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + + let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList]; + let limit = public_keys.len() * kinds.len() + 20; + let filter = Filter::new().authors(public_keys).kinds(kinds).limit(limit); + + // Subscribe to filters to the bootstrap relays + client + .subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts)) + .await?; + + Ok(()) + } + + /// Get and verify NIP-65 relays for a given public key + pub async fn get_nip65(&self, public_key: PublicKey) -> Result<(), Error> { + let client = nostr_client(); + let tx = self.signal.sender().clone(); + let timeout = Duration::from_secs(5); + let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + + let filter = Filter::new() + .kind(Kind::RelayList) + .author(public_key) + .limit(1); + + // Subscribe to events from the bootstrapping relays + client + .subscribe_to(BOOTSTRAP_RELAYS, filter.clone(), Some(opts)) + .await?; + + // Verify the received data after a timeout + smol::spawn(async move { + smol::Timer::after(timeout).await; + + if client.database().count(filter).await.unwrap_or(0) < 1 { + tx.send_async(SignalKind::GossipRelaysNotFound).await.ok(); + } + }) + .detach(); + + Ok(()) + } + + /// Set NIP-65 relays for a current user + pub async fn set_nip65( + &self, + relays: &[(RelayUrl, Option)], + ) -> Result<(), Error> { + let client = nostr_client(); + let signer = client.signer().await?; + + let tags: Vec = relays + .iter() + .map(|(url, metadata)| Tag::relay_metadata(url.to_owned(), metadata.to_owned())) + .collect(); + + let event = EventBuilder::new(Kind::RelayList, "") + .tags(tags) + .sign(&signer) + .await?; + + // Send event to the public relays + client.send_event_to(BOOTSTRAP_RELAYS, &event).await?; + + // Get NIP-17 relays + self.get_nip17(event.pubkey).await?; + + Ok(()) + } + + /// Get and verify NIP-17 relays for a given public key + pub async fn get_nip17(&self, public_key: PublicKey) -> Result<(), Error> { + let client = nostr_client(); + let tx = self.signal.sender().clone(); + let timeout = Duration::from_secs(5); + let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + + let filter = Filter::new() + .kind(Kind::InboxRelays) + .author(public_key) + .limit(1); + + // Subscribe to events from the bootstrapping relays + client.subscribe(filter.clone(), Some(opts)).await?; + + // Verify the received data after a timeout + smol::spawn(async move { + smol::Timer::after(timeout).await; + + if client.database().count(filter).await.unwrap_or(0) < 1 { + tx.send_async(SignalKind::MessagingRelaysNotFound) + .await + .ok(); + } + }) + .detach(); + + Ok(()) + } + + /// Set NIP-17 relays for a current user + pub async fn set_nip17(&self, relays: &[RelayUrl]) -> Result<(), Error> { + let client = nostr_client(); + let signer = client.signer().await?; + + let event = EventBuilder::new(Kind::InboxRelays, "") + .tags(relays.iter().map(|relay| Tag::relay(relay.to_owned()))) + .sign(&signer) + .await?; + + // Send event to the public relays + client.send_event(&event).await?; + + // Run inbox monitor + self.get_messages(event.pubkey, relays).await?; + + Ok(()) + } + + /// Get all gift wrap events in the messaging relays for a given public key + async fn get_messages(&self, public_key: PublicKey, urls: &[RelayUrl]) -> Result<(), Error> { + let client = nostr_client(); + let id = SubscriptionId::new("inbox"); + let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key); + + // Ensure user's have at least one relay + if urls.is_empty() { + return Err(anyhow!("Relays are empty")); + } + + // Ensure connection to relays + for url in urls.iter() { + client.add_relay(url).await?; + client.connect_relay(url).await?; + } + + // Subscribe to filters to user's messaging relays + client.subscribe_with_id_to(urls, id, filter, None).await?; + + Ok(()) } /// Stores an unwrapped event in local database with reference to original diff --git a/crates/coop/src/chatspace.rs b/crates/coop/src/chatspace.rs index 31e84ce..d142db0 100644 --- a/crates/coop/src/chatspace.rs +++ b/crates/coop/src/chatspace.rs @@ -225,7 +225,7 @@ impl ChatSpace { app_state.signal.send(SignalKind::SignerSet(pk)).await; // Get user's gossip relays - app_state.gossip.write().await.get_nip65(pk).await.ok(); + app_state.get_nip65(pk).await.ok(); // Exit the current loop break; @@ -877,9 +877,7 @@ impl ChatSpace { .spawn(cx, async move |cx| { let app_state = app_state(); let relays = default_nip65_relays(); - - let mut gossip = app_state.gossip.write().await; - let result = gossip.set_nip65(relays).await; + let result = app_state.set_nip65(relays).await; cx.update(|window, cx| { match result { @@ -981,9 +979,7 @@ impl ChatSpace { .spawn(cx, async move |cx| { let app_state = app_state(); let relays = default_nip17_relays(); - - let mut gossip = app_state.gossip.write().await; - let result = gossip.set_nip17(relays).await; + let result = app_state.set_nip17(relays).await; cx.update(|window, cx| { match result { diff --git a/crates/coop/src/views/edit_profile.rs b/crates/coop/src/views/edit_profile.rs index 377a3de..9e5f764 100644 --- a/crates/coop/src/views/edit_profile.rs +++ b/crates/coop/src/views/edit_profile.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use std::time::Duration; use anyhow::Error; -use app_state::{app_state, nostr_client}; +use app_state::nostr_client; use common::nip96::nip96_upload; use gpui::prelude::FluentBuilder; use gpui::{ @@ -188,9 +188,6 @@ impl EditProfile { } cx.background_spawn(async move { - let app_state = app_state(); - let gossip = app_state.gossip.read().await; - let client = nostr_client(); let signer = client.signer().await?; @@ -198,7 +195,7 @@ impl EditProfile { let event = EventBuilder::metadata(&new_metadata).sign(&signer).await?; // Send event to user's write relayss - gossip.send_event_to_write_relays(&event).await?; + client.send_event(&event).await?; // Return the updated profile let metadata = Metadata::from_json(&event.content).unwrap_or_default(); diff --git a/crates/coop/src/views/new_account.rs b/crates/coop/src/views/new_account.rs index 7acf006..a7b1ec9 100644 --- a/crates/coop/src/views/new_account.rs +++ b/crates/coop/src/views/new_account.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Error}; use app_state::constants::{ACCOUNT_IDENTIFIER, BOOTSTRAP_RELAYS}; -use app_state::{app_state, default_nip17_relays, default_nip65_relays, nostr_client}; +use app_state::{default_nip17_relays, default_nip65_relays, nostr_client}; use common::nip96::nip96_upload; use gpui::{ div, relative, rems, AnyElement, App, AppContext, AsyncWindowContext, Context, Entity, @@ -125,8 +125,6 @@ impl NewAccount { // Set the client's signer with the current keys let task: Task> = cx.background_spawn(async move { let client = nostr_client(); - let app_state = app_state(); - let gossip = app_state.gossip.read().await; // Set the client's signer with the current keys client.set_signer(keys).await; @@ -156,13 +154,13 @@ impl NewAccount { .await?; // Set NIP-17 relays - gossip.send_event_to_write_relays(&event).await?; + client.send_event(&event).await?; // Construct a metadata event let event = EventBuilder::metadata(&metadata).sign(&signer).await?; // Set metadata - gossip.send_event_to_write_relays(&event).await?; + client.send_event(&event).await?; Ok(()) }); diff --git a/crates/coop/src/views/setup_relay.rs b/crates/coop/src/views/setup_relay.rs index a5e651b..3b5a196 100644 --- a/crates/coop/src/views/setup_relay.rs +++ b/crates/coop/src/views/setup_relay.rs @@ -152,13 +152,11 @@ impl SetupRelay { let relays = self.relays.clone(); let task: Task> = cx.background_spawn(async move { + let app_state = app_state(); let client = nostr_client(); let signer = client.signer().await?; let public_key = signer.get_public_key().await?; - let app_state = app_state(); - let gossip = app_state.gossip.read().await; - let tags: Vec = relays .iter() .map(|relay| Tag::relay(relay.clone())) @@ -170,7 +168,7 @@ impl SetupRelay { .await?; // Set messaging relays - gossip.send_event_to_write_relays(&event).await?; + client.send_event(&event).await?; // Connect to messaging relays for relay in relays.iter() { diff --git a/crates/registry/src/room.rs b/crates/registry/src/room.rs index ddba3fe..d099275 100644 --- a/crates/registry/src/room.rs +++ b/crates/registry/src/room.rs @@ -9,6 +9,7 @@ use app_state::{app_state, nostr_client}; use common::display::RenderedProfile; use common::event::EventUtils; use gpui::{App, AppContext, Context, EventEmitter, SharedString, SharedUri, Task}; +use itertools::Itertools; use nostr_sdk::prelude::*; use crate::Registry; @@ -495,9 +496,7 @@ impl Room { for receiver in members.into_iter() { let rumor = rumor.clone(); let event = EventBuilder::gift_wrap(&signer, &receiver, rumor, vec![]).await?; - - let gossip = app_state.gossip.read().await; - let urls = gossip.messaging_relays(&receiver); + let urls = Self::messaging_relays(receiver).await; // Check if there are any relays to send the event to if urls.is_empty() { @@ -549,8 +548,7 @@ impl Room { // Only send a backup message to current user if sent successfully to others if reports.iter().all(|r| r.is_sent_success()) && backup { - let gossip = app_state.gossip.read().await; - let urls = gossip.messaging_relays(&public_key); + let urls = Self::messaging_relays(public_key).await; // Check if there are any relays to send the event to if urls.is_empty() { @@ -582,8 +580,6 @@ impl Room { ) -> Task, Error>> { cx.background_spawn(async move { let client = nostr_client(); - let app_state = app_state(); - let mut resend_reports = vec![]; for report in reports.into_iter() { @@ -612,8 +608,7 @@ impl Room { // Process the on hold event if it exists if let Some(event) = report.on_hold { - let gossip = app_state.gossip.read().await; - let urls = gossip.messaging_relays(&receiver); + let urls = Self::messaging_relays(receiver).await; // Check if there are any relays to send the event to if urls.is_empty() { @@ -635,4 +630,31 @@ impl Room { Ok(resend_reports) }) } + + /// Gets messaging relays for public key + async fn messaging_relays(public_key: PublicKey) -> Vec { + let client = nostr_client(); + let mut relay_urls = vec![]; + + let filter = Filter::new() + .kind(Kind::InboxRelays) + .author(public_key) + .limit(1); + + if let Ok(events) = client.database().query(filter).await { + if let Some(event) = events.first_owned() { + let urls: Vec = nip17::extract_owned_relay_list(event).collect(); + + // Connect to relays + for url in urls.iter() { + client.add_relay(url).await.ok(); + client.connect_relay(url).await.ok(); + } + + relay_urls.extend(urls.into_iter().take(3).unique()); + } + } + + relay_urls + } } diff --git a/crates/ui/Cargo.toml b/crates/ui/Cargo.toml index b7080bc..ed44a7b 100644 --- a/crates/ui/Cargo.toml +++ b/crates/ui/Cargo.toml @@ -30,4 +30,4 @@ image = "0.25.1" linkify = "0.10.0" lsp-types = "0.97.0" rope = { git = "https://github.com/zed-industries/zed" } -zed-sum-tree = { git = "https://github.com/zed-industries/zed" } +sum_tree = { git = "https://github.com/zed-industries/zed" } diff --git a/crates/ui/src/input/rope_ext.rs b/crates/ui/src/input/rope_ext.rs index e08bacc..96685c5 100644 --- a/crates/ui/src/input/rope_ext.rs +++ b/crates/ui/src/input/rope_ext.rs @@ -128,7 +128,7 @@ impl RopeExt for Rope { fn offset_to_position(&self, offset: usize) -> Position { let point = self.offset_to_point(offset); let line = self.line(point.row as usize); - let column = line.clip_offset(point.column as usize, zed_sum_tree::Bias::Left); + let column = line.clip_offset(point.column as usize, sum_tree::Bias::Left); let character = line.slice(0..column).chars().count(); Position::new(point.row, character as u32) } @@ -162,7 +162,7 @@ impl RopeExt for Rope { return None; } - let offset = self.clip_offset(offset, zed_sum_tree::Bias::Left); + let offset = self.clip_offset(offset, sum_tree::Bias::Left); self.slice(offset..self.len()).chars().next() } @@ -171,7 +171,7 @@ impl RopeExt for Rope { return None; } - let offset = self.clip_offset(offset, zed_sum_tree::Bias::Left); + let offset = self.clip_offset(offset, sum_tree::Bias::Left); let mut left = String::new(); for c in self.reversed_chars_at(offset) { diff --git a/crates/ui/src/input/state.rs b/crates/ui/src/input/state.rs index 55d69dc..8a430fd 100644 --- a/crates/ui/src/input/state.rs +++ b/crates/ui/src/input/state.rs @@ -14,8 +14,8 @@ use lsp_types::Position; use rope::{OffsetUtf16, Rope}; use serde::Deserialize; use smallvec::SmallVec; +use sum_tree::Bias; use unicode_segmentation::*; -use zed_sum_tree::Bias; use super::blink_cursor::BlinkCursor; use super::change::Change;