From a631dd90d270fc1b4a61886f6e7486a8224beaf5 Mon Sep 17 00:00:00 2001
From: reya <123083837+reyamir@users.noreply.github.com>
Date: Wed, 23 Jul 2025 12:45:01 +0700
Subject: [PATCH] feat: screening (#96)
* .
* .
* refactor
* .
* screening
* add report user function
* add danger and warning styles
* update deps
* update
* fix line height
* .
---
Cargo.lock | 177 +-
assets/icons/open-url.svg | 3 +
crates/common/src/display.rs | 15 +-
crates/coop/src/chatspace.rs | 12 +-
crates/coop/src/main.rs | 7 +-
crates/coop/src/views/mod.rs | 1 +
crates/coop/src/views/preferences.rs | 2 +-
crates/coop/src/views/screening.rs | 288 ++
crates/coop/src/views/sidebar/element.rs | 122 -
crates/coop/src/views/sidebar/list_item.rs | 174 +
crates/coop/src/views/sidebar/mod.rs | 100 +-
crates/coop/src/views/user_profile.rs | 28 +-
crates/global/src/lib.rs | 2 +-
crates/registry/src/lib.rs | 47 +-
crates/registry/src/room.rs | 5 +-
crates/settings/src/lib.rs | 4 +-
crates/theme/src/colors.rs | 4418 ++++++++++----------
crates/theme/src/lib.rs | 357 +-
crates/ui/src/button.rs | 47 +-
crates/ui/src/icon.rs | 2 +
crates/ui/src/input/element.rs | 2 +-
crates/ui/src/modal.rs | 1004 ++---
locales/app.yml | 141 +-
script/linux | 0
24 files changed, 3706 insertions(+), 3252 deletions(-)
create mode 100644 assets/icons/open-url.svg
create mode 100644 crates/coop/src/views/screening.rs
delete mode 100644 crates/coop/src/views/sidebar/element.rs
create mode 100644 crates/coop/src/views/sidebar/list_item.rs
mode change 100644 => 100755 script/linux
diff --git a/Cargo.lock b/Cargo.lock
index 18dfe2c..e660a9a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -163,7 +163,7 @@ dependencies = [
"enumflags2",
"futures-channel",
"futures-util",
- "rand 0.9.1",
+ "rand 0.9.2",
"serde",
"serde_repr",
"url",
@@ -224,9 +224,9 @@ dependencies = [
[[package]]
name = "async-fs"
-version = "2.1.2"
+version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
+checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50"
dependencies = [
"async-lock",
"blocking",
@@ -235,9 +235,9 @@ dependencies = [
[[package]]
name = "async-io"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
+checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca"
dependencies = [
"async-lock",
"cfg-if",
@@ -248,8 +248,7 @@ dependencies = [
"polling",
"rustix 1.0.8",
"slab",
- "tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -276,9 +275,9 @@ dependencies = [
[[package]]
name = "async-process"
-version = "2.3.1"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
+checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00"
dependencies = [
"async-channel",
"async-io",
@@ -290,7 +289,6 @@ dependencies = [
"event-listener",
"futures-lite 2.6.0",
"rustix 1.0.8",
- "tracing",
]
[[package]]
@@ -306,9 +304,9 @@ dependencies = [
[[package]]
name = "async-signal"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
+checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1"
dependencies = [
"async-io",
"async-lock",
@@ -319,7 +317,7 @@ dependencies = [
"rustix 1.0.8",
"signal-hook-registry",
"slab",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -449,9 +447,9 @@ dependencies = [
[[package]]
name = "aws-lc-rs"
-version = "1.13.2"
+version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08b5d4e069cbc868041a64bd68dc8cb39a0d79585cd6c5a24caa8c2d622121be"
+checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba"
dependencies = [
"aws-lc-sys",
"zeroize",
@@ -644,7 +642,7 @@ checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2"
[[package]]
name = "blade-graphics"
version = "0.6.0"
-source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
+source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
dependencies = [
"ash",
"ash-window",
@@ -677,7 +675,7 @@ dependencies = [
[[package]]
name = "blade-macros"
version = "0.3.0"
-source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
+source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
dependencies = [
"proc-macro2",
"quote",
@@ -687,7 +685,7 @@ dependencies = [
[[package]]
name = "blade-util"
version = "0.2.0"
-source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
+source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
dependencies = [
"blade-graphics",
"bytemuck",
@@ -774,9 +772,9 @@ dependencies = [
[[package]]
name = "bytemuck_derive"
-version = "1.9.3"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
+checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4"
dependencies = [
"proc-macro2",
"quote",
@@ -856,9 +854,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.29"
+version = "1.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
+checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
dependencies = [
"jobserver",
"libc",
@@ -1075,7 +1073,7 @@ dependencies = [
[[package]]
name = "collections"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"indexmap",
"rustc-hash 2.1.1",
@@ -1476,7 +1474,7 @@ dependencies = [
[[package]]
name = "derive_refineable"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"proc-macro2",
"quote",
@@ -2328,7 +2326,7 @@ dependencies = [
[[package]]
name = "gpui"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"as-raw-xcb-connection",
@@ -2394,7 +2392,7 @@ dependencies = [
"slotmap",
"smallvec",
"smol",
- "strum 0.27.1",
+ "strum 0.27.2",
"sum_tree",
"taffy",
"thiserror 2.0.12",
@@ -2421,7 +2419,7 @@ dependencies = [
[[package]]
name = "gpui_macros"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -2433,7 +2431,7 @@ dependencies = [
[[package]]
name = "gpui_tokio"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"gpui",
"tokio",
@@ -2443,9 +2441,9 @@ dependencies = [
[[package]]
name = "grid"
-version = "0.13.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d196ffc1627db18a531359249b2bf8416178d84b729f3cebeb278f285fb9b58c"
+checksum = "71b01d27060ad58be4663b9e4ac9e2d4806918e8876af8912afbddd1a91d5eaa"
[[package]]
name = "h2"
@@ -2655,13 +2653,14 @@ dependencies = [
[[package]]
name = "http_client"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"bytes",
"derive_more",
"futures",
"http",
+ "http-body",
"log",
"serde",
"serde_json",
@@ -2672,7 +2671,7 @@ dependencies = [
[[package]]
name = "http_client_tls"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"rustls",
"rustls-platform-verifier",
@@ -2740,9 +2739,9 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.15"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df"
+checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
dependencies = [
"base64",
"bytes",
@@ -2756,7 +2755,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2",
+ "socket2 0.6.0",
"system-configuration",
"tokio",
"tower-service",
@@ -3048,9 +3047,9 @@ dependencies = [
[[package]]
name = "io-uring"
-version = "0.7.8"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
+checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
dependencies = [
"bitflags 2.9.1",
"cfg-if",
@@ -3194,11 +3193,12 @@ dependencies = [
[[package]]
name = "kurbo"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c"
+checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62"
dependencies = [
"arrayvec",
+ "euclid",
"smallvec",
]
@@ -3272,9 +3272,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
-version = "0.1.4"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
+checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
dependencies = [
"bitflags 2.9.1",
"libc",
@@ -3449,7 +3449,7 @@ dependencies = [
[[package]]
name = "media"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"bindgen 0.71.1",
@@ -3672,7 +3672,7 @@ dependencies = [
[[package]]
name = "nostr"
version = "0.42.1"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"aes",
"base64",
@@ -3695,7 +3695,7 @@ dependencies = [
[[package]]
name = "nostr-connect"
version = "0.42.0"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"async-utility",
"nostr",
@@ -3707,7 +3707,7 @@ dependencies = [
[[package]]
name = "nostr-database"
version = "0.42.0"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"flatbuffers",
"lru",
@@ -3718,7 +3718,7 @@ dependencies = [
[[package]]
name = "nostr-lmdb"
version = "0.42.0"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"async-utility",
"heed",
@@ -3731,7 +3731,7 @@ dependencies = [
[[package]]
name = "nostr-relay-pool"
version = "0.42.0"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"async-utility",
"async-wsocket",
@@ -3747,7 +3747,7 @@ dependencies = [
[[package]]
name = "nostr-sdk"
version = "0.42.0"
-source = "git+https://github.com/rust-nostr/nostr#ef342a983007ad46fc681d90afd9d8458f632b7b"
+source = "git+https://github.com/rust-nostr/nostr#b2d26225a156765d2de9456dd38cc7a40f7426f0"
dependencies = [
"async-utility",
"nostr",
@@ -4062,7 +4062,7 @@ dependencies = [
"num",
"num-bigint-dig",
"pbkdf2",
- "rand 0.9.1",
+ "rand 0.9.2",
"serde",
"sha2",
"subtle",
@@ -4364,17 +4364,16 @@ dependencies = [
[[package]]
name = "polling"
-version = "3.8.0"
+version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
+checksum = "8ee9b2fa7a4517d2c91ff5bc6c297a427a96749d15f98fcdbb22c05571a4d4b7"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix 1.0.8",
- "tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -4539,7 +4538,7 @@ dependencies = [
"quinn-udp",
"rustc-hash 2.1.1",
"rustls",
- "socket2",
+ "socket2 0.5.10",
"thiserror 2.0.12",
"tokio",
"tracing",
@@ -4555,7 +4554,7 @@ dependencies = [
"bytes",
"getrandom 0.3.3",
"lru-slab",
- "rand 0.9.1",
+ "rand 0.9.2",
"ring",
"rustc-hash 2.1.1",
"rustls",
@@ -4576,7 +4575,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2",
+ "socket2 0.5.10",
"tracing",
"windows-sys 0.59.0",
]
@@ -4609,9 +4608,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.1"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
@@ -4761,9 +4760,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.13"
+version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
+checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec"
dependencies = [
"bitflags 2.9.1",
]
@@ -4802,7 +4801,7 @@ dependencies = [
[[package]]
name = "refineable"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"derive_refineable",
"workspace-hack",
@@ -4953,7 +4952,7 @@ dependencies = [
[[package]]
name = "reqwest_client"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"bytes",
@@ -5308,7 +5307,7 @@ dependencies = [
[[package]]
name = "scap"
version = "0.0.8"
-source = "git+https://github.com/zed-industries/scap?rev=270538dc780f5240723233ff901e1054641ed318#270538dc780f5240723233ff901e1054641ed318"
+source = "git+https://github.com/zed-industries/scap?rev=808aa5c45b41e8f44729d02e38fd00a2fe2722e7#808aa5c45b41e8f44729d02e38fd00a2fe2722e7"
dependencies = [
"anyhow",
"cocoa 0.25.0",
@@ -5479,7 +5478,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
[[package]]
name = "semantic_version"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"serde",
@@ -5534,9 +5533,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.140"
+version = "1.0.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
dependencies = [
"indexmap",
"itoa",
@@ -5772,6 +5771,16 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "socket2"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "spin"
version = "0.9.8"
@@ -5822,11 +5831,11 @@ dependencies = [
[[package]]
name = "strum"
-version = "0.27.1"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
+checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
dependencies = [
- "strum_macros 0.27.1",
+ "strum_macros 0.27.2",
]
[[package]]
@@ -5844,14 +5853,13 @@ dependencies = [
[[package]]
name = "strum_macros"
-version = "0.27.1"
+version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
+checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "rustversion",
"syn 2.0.104",
]
@@ -5864,7 +5872,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "sum_tree"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"arrayvec",
"log",
@@ -6087,13 +6095,12 @@ dependencies = [
[[package]]
name = "taffy"
-version = "0.4.4"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ec17858c2d465b2f734b798b920818a974faf0babb15d7fef81818a4b2d16f1"
+checksum = "7aaef0ac998e6527d6d0d5582f7e43953bb17221ac75bb8eb2fcc2db3396db1c"
dependencies = [
"arrayvec",
"grid",
- "num-traits",
"serde",
"slotmap",
]
@@ -6297,7 +6304,7 @@ dependencies = [
"mio",
"pin-project-lite",
"slab",
- "socket2",
+ "socket2 0.5.10",
"tokio-macros",
"windows-sys 0.52.0",
]
@@ -6605,7 +6612,7 @@ dependencies = [
"http",
"httparse",
"log",
- "rand 0.9.1",
+ "rand 0.9.2",
"rustls",
"rustls-pki-types",
"sha1",
@@ -6838,7 +6845,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "util"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#ebad5ca50e11fc9d3fbbab397888d0944a825bb7"
+source = "git+https://github.com/zed-industries/zed#500ceaabcde9d78b3a1a0d14674523e497dbc6e4"
dependencies = [
"anyhow",
"async-fs",
@@ -7231,14 +7238,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e"
dependencies = [
- "webpki-root-certs 1.0.1",
+ "webpki-root-certs 1.0.2",
]
[[package]]
name = "webpki-root-certs"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86138b15b2b7d561bc4469e77027b8dd005a43dc502e9031d1f5afc8ce1f280e"
+checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a"
dependencies = [
"rustls-pki-types",
]
@@ -7249,14 +7256,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.1",
+ "webpki-roots 1.0.2",
]
[[package]]
name = "webpki-roots"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
+checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
dependencies = [
"rustls-pki-types",
]
diff --git a/assets/icons/open-url.svg b/assets/icons/open-url.svg
new file mode 100644
index 0000000..837e1e6
--- /dev/null
+++ b/assets/icons/open-url.svg
@@ -0,0 +1,3 @@
+
diff --git a/crates/common/src/display.rs b/crates/common/src/display.rs
index 630a627..86fd5fd 100644
--- a/crates/common/src/display.rs
+++ b/crates/common/src/display.rs
@@ -41,8 +41,17 @@ impl DisplayProfile for Profile {
}
}
- let Ok(pubkey) = self.public_key().to_bech32();
-
- format!("{}:{}", &pubkey[0..4], &pubkey[pubkey.len() - 4..]).into()
+ shorten_pubkey(self.public_key(), 4)
}
}
+
+pub fn shorten_pubkey(public_key: PublicKey, len: usize) -> SharedString {
+ let Ok(pubkey) = public_key.to_bech32();
+
+ format!(
+ "{}:{}",
+ &pubkey[0..(len + 1)],
+ &pubkey[pubkey.len() - len..]
+ )
+ .into()
+}
diff --git a/crates/coop/src/chatspace.rs b/crates/coop/src/chatspace.rs
index 9c9f61b..67eeaa4 100644
--- a/crates/coop/src/chatspace.rs
+++ b/crates/coop/src/chatspace.rs
@@ -25,6 +25,7 @@ use ui::modal::ModalButtonProps;
use ui::{ContextModal, IconName, Root, Sizable, StyledExt, TitleBar};
use crate::views::chat::{self, Chat};
+use crate::views::screening::Screening;
use crate::views::user_profile::UserProfile;
use crate::views::{
login, new_account, onboarding, preferences, sidebar, startup, user_profile, welcome,
@@ -73,7 +74,7 @@ pub struct ChatSpace {
dock: Entity,
toolbar: bool,
#[allow(unused)]
- subscriptions: SmallVec<[Subscription; 5]>,
+ subscriptions: SmallVec<[Subscription; 6]>,
}
impl ChatSpace {
@@ -172,13 +173,20 @@ impl ChatSpace {
}
}));
- // Automatically run on_load function from UserProfile
+ // Automatically run on_load function when UserProfile is created
subscriptions.push(cx.observe_new::(|this, window, cx| {
if let Some(window) = window {
this.on_load(window, cx);
}
}));
+ // Automatically run on_load function when Screening is created
+ subscriptions.push(cx.observe_new::(|this, window, cx| {
+ if let Some(window) = window {
+ this.on_load(window, cx);
+ }
+ }));
+
// Subscribe to open chat room requests
subscriptions.push(cx.subscribe_in(
®istry,
diff --git a/crates/coop/src/main.rs b/crates/coop/src/main.rs
index 5834460..963b877 100644
--- a/crates/coop/src/main.rs
+++ b/crates/coop/src/main.rs
@@ -405,10 +405,11 @@ async fn handle_nostr_notifications(
.kind(Kind::InboxRelays)
.limit(1);
- if client.subscribe(filter, Some(opts)).await.is_ok() {
+ if let Ok(output) = client.subscribe(filter, Some(opts)).await {
log::info!(
- "Subscribed to get DM relays: {}",
- event.pubkey.to_bech32().unwrap()
+ "Subscribed to get DM relays: {} - Relays: {:?}",
+ event.pubkey.to_bech32().unwrap(),
+ output.success
)
}
}
diff --git a/crates/coop/src/views/mod.rs b/crates/coop/src/views/mod.rs
index bd55380..cd7eede 100644
--- a/crates/coop/src/views/mod.rs
+++ b/crates/coop/src/views/mod.rs
@@ -6,6 +6,7 @@ pub mod new_account;
pub mod onboarding;
pub mod preferences;
pub mod relays;
+pub mod screening;
pub mod sidebar;
pub mod startup;
pub mod user_profile;
diff --git a/crates/coop/src/views/preferences.rs b/crates/coop/src/views/preferences.rs
index 1055e66..dac3191 100644
--- a/crates/coop/src/views/preferences.rs
+++ b/crates/coop/src/views/preferences.rs
@@ -51,7 +51,7 @@ impl Preferences {
fn open_edit_profile(&self, window: &mut Window, cx: &mut Context) {
let edit_profile = edit_profile::init(window, cx);
- let title = SharedString::new(t!("preferences.modal_profile_title"));
+ let title = SharedString::new(t!("profile.title"));
window.open_modal(cx, move |modal, _window, _cx| {
modal
diff --git a/crates/coop/src/views/screening.rs b/crates/coop/src/views/screening.rs
new file mode 100644
index 0000000..16e379d
--- /dev/null
+++ b/crates/coop/src/views/screening.rs
@@ -0,0 +1,288 @@
+use common::display::{shorten_pubkey, DisplayProfile};
+use common::nip05::nip05_verify;
+use global::nostr_client;
+use gpui::prelude::FluentBuilder;
+use gpui::{
+ div, relative, rems, App, AppContext, Context, Entity, IntoElement, ParentElement, Render,
+ SharedString, Styled, Task, Window,
+};
+use gpui_tokio::Tokio;
+use i18n::t;
+use identity::Identity;
+use nostr_sdk::prelude::*;
+use registry::Registry;
+use settings::AppSettings;
+use theme::ActiveTheme;
+use ui::avatar::Avatar;
+use ui::button::{Button, ButtonRounded, ButtonVariants};
+use ui::{h_flex, v_flex, ContextModal, Icon, IconName, Sizable, StyledExt};
+
+pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity {
+ Screening::new(public_key, window, cx)
+}
+
+pub struct Screening {
+ public_key: PublicKey,
+ followed: bool,
+ connections: usize,
+ verified: bool,
+}
+
+impl Screening {
+ pub fn new(public_key: PublicKey, _window: &mut Window, cx: &mut App) -> Entity {
+ cx.new(|_| Self {
+ public_key,
+ followed: false,
+ connections: 0,
+ verified: false,
+ })
+ }
+
+ pub fn on_load(&mut self, window: &mut Window, cx: &mut Context) {
+ // Skip if user isn't logged in
+ let Some(identity) = Identity::read_global(cx).public_key() else {
+ return;
+ };
+
+ let public_key = self.public_key;
+
+ let check_trust_score: Task<(bool, usize)> = cx.background_spawn(async move {
+ let client = nostr_client();
+
+ let follow = Filter::new()
+ .kind(Kind::ContactList)
+ .author(identity)
+ .pubkey(public_key)
+ .limit(1);
+
+ let connection = Filter::new()
+ .kind(Kind::ContactList)
+ .pubkey(public_key)
+ .limit(1);
+
+ let is_follow = client.database().count(follow).await.unwrap_or(0) >= 1;
+ let connects = client.database().count(connection).await.unwrap_or(0);
+
+ (is_follow, connects)
+ });
+
+ let verify_nip05 = if let Some(address) = self.address(cx) {
+ Some(Tokio::spawn(cx, async move {
+ nip05_verify(public_key, &address).await.unwrap_or(false)
+ }))
+ } else {
+ None
+ };
+
+ cx.spawn_in(window, async move |this, cx| {
+ let (followed, connections) = check_trust_score.await;
+
+ this.update(cx, |this, cx| {
+ this.followed = followed;
+ this.connections = connections;
+ cx.notify();
+ })
+ .ok();
+
+ // Update the NIP05 verification status if user has NIP05 address
+ if let Some(task) = verify_nip05 {
+ if let Ok(verified) = task.await {
+ this.update(cx, |this, cx| {
+ this.verified = verified;
+ cx.notify();
+ })
+ .ok();
+ }
+ }
+ })
+ .detach();
+ }
+
+ fn profile(&self, cx: &Context) -> Profile {
+ let registry = Registry::read_global(cx);
+ registry.get_person(&self.public_key, cx)
+ }
+
+ fn address(&self, cx: &Context) -> Option {
+ self.profile(cx).metadata().nip05
+ }
+
+ fn open_njump(&mut self, _window: &mut Window, cx: &mut App) {
+ let Ok(bech32) = self.public_key.to_bech32();
+ cx.open_url(&format!("https://njump.me/{bech32}"));
+ }
+
+ fn report(&mut self, window: &mut Window, cx: &mut Context) {
+ let public_key = self.public_key;
+ let task: Task> = cx.background_spawn(async move {
+ let client = nostr_client();
+ let builder = EventBuilder::report(
+ vec![Tag::public_key_report(public_key, Report::Impersonation)],
+ "scam/impersonation",
+ );
+ let _ = client.send_event_builder(builder).await?;
+
+ Ok(())
+ });
+
+ cx.spawn_in(window, async move |_, cx| {
+ if task.await.is_ok() {
+ cx.update(|window, cx| {
+ window.close_modal(cx);
+ window.push_notification(t!("screening.report_msg"), cx);
+ })
+ .ok();
+ }
+ })
+ .detach();
+ }
+}
+
+impl Render for Screening {
+ fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement {
+ let proxy = AppSettings::get_global(cx).settings.proxy_user_avatars;
+ let profile = self.profile(cx);
+ let shorten_pubkey = shorten_pubkey(profile.public_key(), 8);
+
+ v_flex()
+ .w_full()
+ .px_4()
+ .pt_8()
+ .pb_4()
+ .gap_4()
+ .child(
+ v_flex()
+ .gap_3()
+ .items_center()
+ .justify_center()
+ .text_center()
+ .child(Avatar::new(profile.avatar_url(proxy)).size(rems(4.)))
+ .child(
+ div()
+ .font_semibold()
+ .line_height(relative(1.25))
+ .child(profile.display_name()),
+ ),
+ )
+ .child(
+ h_flex()
+ .gap_1()
+ .child(
+ div()
+ .p_1()
+ .flex_1()
+ .h_7()
+ .flex()
+ .items_center()
+ .justify_center()
+ .rounded_full()
+ .bg(cx.theme().elevated_surface_background)
+ .text_sm()
+ .truncate()
+ .text_ellipsis()
+ .text_center()
+ .line_height(relative(1.))
+ .child(shorten_pubkey),
+ )
+ .child(
+ Button::new("njump")
+ .label(t!("profile.njump"))
+ .secondary()
+ .small()
+ .rounded(ButtonRounded::Full)
+ .on_click(cx.listener(move |this, _e, window, cx| {
+ this.open_njump(window, cx);
+ })),
+ )
+ .child(
+ Button::new("report")
+ .tooltip(t!("screening.report"))
+ .icon(IconName::Info)
+ .danger_alt()
+ .small()
+ .rounded(ButtonRounded::Full)
+ .on_click(cx.listener(move |this, _e, window, cx| {
+ this.report(window, cx);
+ })),
+ ),
+ )
+ .child(
+ v_flex()
+ .gap_2()
+ .when_some(self.address(cx), |this, address| {
+ this.child(h_flex().gap_2().map(|this| {
+ if self.verified {
+ this.text_sm()
+ .child(
+ Icon::new(IconName::CheckCircleFill)
+ .small()
+ .flex_shrink_0()
+ .text_color(cx.theme().icon_accent),
+ )
+ .child(div().flex_1().child(SharedString::new(t!(
+ "screening.verified",
+ address = address
+ ))))
+ } else {
+ this.text_sm()
+ .child(
+ Icon::new(IconName::CheckCircleFill)
+ .small()
+ .text_color(cx.theme().icon_muted),
+ )
+ .child(div().flex_1().child(SharedString::new(t!(
+ "screening.not_verified",
+ address = address
+ ))))
+ }
+ }))
+ })
+ .child(h_flex().gap_2().map(|this| {
+ if !self.followed {
+ this.text_sm()
+ .child(
+ Icon::new(IconName::CheckCircleFill)
+ .small()
+ .text_color(cx.theme().icon_muted),
+ )
+ .child(SharedString::new(t!("screening.not_contact")))
+ } else {
+ this.text_sm()
+ .child(
+ Icon::new(IconName::CheckCircleFill)
+ .small()
+ .text_color(cx.theme().icon_accent),
+ )
+ .child(SharedString::new(t!("screening.contact")))
+ }
+ }))
+ .child(
+ h_flex()
+ .gap_2()
+ .text_sm()
+ .child(
+ Icon::new(IconName::CheckCircleFill)
+ .small()
+ .flex_shrink_0()
+ .text_color({
+ if self.connections > 0 {
+ cx.theme().icon_accent
+ } else {
+ cx.theme().icon_muted
+ }
+ }),
+ )
+ .map(|this| {
+ if self.connections > 0 {
+ this.child(SharedString::new(t!(
+ "screening.total_connections",
+ u = self.connections
+ )))
+ } else {
+ this.child(SharedString::new(t!("screening.no_connections")))
+ }
+ }),
+ ),
+ )
+ }
+}
diff --git a/crates/coop/src/views/sidebar/element.rs b/crates/coop/src/views/sidebar/element.rs
deleted file mode 100644
index 540fea0..0000000
--- a/crates/coop/src/views/sidebar/element.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-use std::rc::Rc;
-
-use gpui::prelude::FluentBuilder;
-use gpui::{
- div, img, rems, App, ClickEvent, Div, InteractiveElement, IntoElement, ParentElement as _,
- RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window,
-};
-use settings::AppSettings;
-use theme::ActiveTheme;
-use ui::avatar::Avatar;
-use ui::StyledExt;
-
-#[derive(IntoElement)]
-pub struct DisplayRoom {
- ix: usize,
- base: Div,
- img: Option,
- label: Option,
- description: Option,
- #[allow(clippy::type_complexity)]
- handler: Rc,
-}
-
-impl DisplayRoom {
- pub fn new(ix: usize) -> Self {
- Self {
- ix,
- base: div().h_9().w_full().px_1p5(),
- img: None,
- label: None,
- description: None,
- handler: Rc::new(|_, _, _| {}),
- }
- }
-
- pub fn label(mut self, label: impl Into) -> Self {
- self.label = Some(label.into());
- self
- }
-
- pub fn description(mut self, description: impl Into) -> Self {
- self.description = Some(description.into());
- self
- }
-
- pub fn img(mut self, img: impl Into) -> Self {
- self.img = Some(img.into());
- self
- }
-
- pub fn on_click(
- mut self,
- handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
- ) -> Self {
- self.handler = Rc::new(handler);
- self
- }
-}
-
-impl RenderOnce for DisplayRoom {
- fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
- let handler = self.handler.clone();
- let hide_avatar = AppSettings::get_global(cx).settings.hide_user_avatars;
-
- self.base
- .id(self.ix)
- .flex()
- .items_center()
- .gap_2()
- .text_sm()
- .rounded(cx.theme().radius)
- .when(!hide_avatar, |this| {
- this.child(
- div()
- .flex_shrink_0()
- .size_6()
- .rounded_full()
- .overflow_hidden()
- .map(|this| {
- if let Some(path) = self.img {
- this.child(Avatar::new(path).size(rems(1.5)))
- } else {
- this.child(
- img("brand/avatar.png")
- .rounded_full()
- .size_6()
- .into_any_element(),
- )
- }
- }),
- )
- })
- .child(
- div()
- .flex_1()
- .flex()
- .items_center()
- .justify_between()
- .when_some(self.label, |this, label| {
- this.child(
- div()
- .flex_1()
- .line_clamp(1)
- .text_ellipsis()
- .font_medium()
- .child(label),
- )
- })
- .when_some(self.description, |this, description| {
- this.child(
- div()
- .flex_shrink_0()
- .text_xs()
- .text_color(cx.theme().text_placeholder)
- .child(description),
- )
- }),
- )
- .hover(|this| this.bg(cx.theme().elevated_surface_background))
- .on_click(move |ev, window, cx| handler(ev, window, cx))
- }
-}
diff --git a/crates/coop/src/views/sidebar/list_item.rs b/crates/coop/src/views/sidebar/list_item.rs
new file mode 100644
index 0000000..83acde5
--- /dev/null
+++ b/crates/coop/src/views/sidebar/list_item.rs
@@ -0,0 +1,174 @@
+use std::rc::Rc;
+
+use gpui::prelude::FluentBuilder;
+use gpui::{
+ div, img, rems, App, ClickEvent, Div, InteractiveElement, IntoElement,
+ ParentElement as _, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window,
+};
+use i18n::t;
+use nostr_sdk::prelude::*;
+use registry::room::RoomKind;
+use settings::AppSettings;
+use theme::ActiveTheme;
+use ui::actions::OpenProfile;
+use ui::avatar::Avatar;
+use ui::context_menu::ContextMenuExt;
+use ui::modal::ModalButtonProps;
+use ui::{h_flex, ContextModal, StyledExt};
+
+use crate::views::screening;
+
+#[derive(IntoElement)]
+pub struct RoomListItem {
+ ix: usize,
+ base: Div,
+ public_key: PublicKey,
+ name: Option,
+ avatar: Option,
+ created_at: Option,
+ kind: Option,
+ #[allow(clippy::type_complexity)]
+ handler: Rc,
+}
+
+impl RoomListItem {
+ pub fn new(ix: usize, public_key: PublicKey) -> Self {
+ Self {
+ ix,
+ public_key,
+ base: h_flex().h_9().w_full().px_1p5(),
+ name: None,
+ avatar: None,
+ created_at: None,
+ kind: None,
+ handler: Rc::new(|_, _, _| {}),
+ }
+ }
+
+ pub fn name(mut self, name: impl Into) -> Self {
+ self.name = Some(name.into());
+ self
+ }
+
+ pub fn created_at(mut self, created_at: impl Into) -> Self {
+ self.created_at = Some(created_at.into());
+ self
+ }
+
+ pub fn avatar(mut self, avatar: impl Into) -> Self {
+ self.avatar = Some(avatar.into());
+ self
+ }
+
+ pub fn kind(mut self, kind: RoomKind) -> Self {
+ self.kind = Some(kind);
+ self
+ }
+
+ pub fn on_click(
+ mut self,
+ handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
+ ) -> Self {
+ self.handler = Rc::new(handler);
+ self
+ }
+}
+
+impl RenderOnce for RoomListItem {
+ fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
+ let public_key = self.public_key;
+ let kind = self.kind;
+ let handler = self.handler.clone();
+ let hide_avatar = AppSettings::get_global(cx).settings.hide_user_avatars;
+ let screening = AppSettings::get_global(cx).settings.screening;
+
+ self.base
+ .id(self.ix)
+ .gap_2()
+ .text_sm()
+ .rounded(cx.theme().radius)
+ .when(!hide_avatar, |this| {
+ this.child(
+ div()
+ .flex_shrink_0()
+ .size_6()
+ .rounded_full()
+ .overflow_hidden()
+ .map(|this| {
+ if let Some(img) = self.avatar {
+ this.child(Avatar::new(img).size(rems(1.5)))
+ } else {
+ this.child(
+ img("brand/avatar.png")
+ .rounded_full()
+ .size_6()
+ .into_any_element(),
+ )
+ }
+ }),
+ )
+ })
+ .child(
+ div()
+ .flex_1()
+ .flex()
+ .items_center()
+ .justify_between()
+ .when_some(self.name, |this, name| {
+ this.child(
+ div()
+ .flex_1()
+ .line_clamp(1)
+ .text_ellipsis()
+ .truncate()
+ .font_medium()
+ .child(name),
+ )
+ })
+ .when_some(self.created_at, |this, ago| {
+ this.child(
+ div()
+ .flex_shrink_0()
+ .text_xs()
+ .text_color(cx.theme().text_placeholder)
+ .child(ago),
+ )
+ }),
+ )
+ .context_menu(move |this, _window, _cx| {
+ // TODO: add share chat room
+ this.menu(t!("profile.view"), Box::new(OpenProfile(public_key)))
+ })
+ .hover(|this| this.bg(cx.theme().elevated_surface_background))
+ .on_click(move |event, window, cx| {
+ let handler = handler.clone();
+
+ if let Some(kind) = kind {
+ if kind != RoomKind::Ongoing && screening {
+ let screening = screening::init(public_key, window, cx);
+
+ window.open_modal(cx, move |this, _window, _cx| {
+ let handler_clone = handler.clone();
+
+ this.confirm()
+ .child(screening.clone())
+ .button_props(
+ ModalButtonProps::default()
+ .cancel_text(t!("screening.ignore"))
+ .ok_text(t!("screening.response")),
+ )
+ .on_ok(move |event, window, cx| {
+ handler_clone(event, window, cx);
+ // true to close the modal
+ true
+ })
+ });
+ } else {
+ handler(event, window, cx)
+ }
+ } else {
+ handler(event, window, cx)
+ }
+ })
+ }
+}
diff --git a/crates/coop/src/views/sidebar/mod.rs b/crates/coop/src/views/sidebar/mod.rs
index b2c996a..352a081 100644
--- a/crates/coop/src/views/sidebar/mod.rs
+++ b/crates/coop/src/views/sidebar/mod.rs
@@ -5,8 +5,6 @@ use std::time::Duration;
use anyhow::{anyhow, Error};
use common::debounced_delay::DebouncedDelay;
use common::display::DisplayProfile;
-use common::nip05::nip05_verify;
-use element::DisplayRoom;
use global::constants::{BOOTSTRAP_RELAYS, DEFAULT_MODAL_WIDTH, SEARCH_RELAYS};
use global::nostr_client;
use gpui::prelude::FluentBuilder;
@@ -20,6 +18,7 @@ use gpui_tokio::Tokio;
use i18n::t;
use identity::Identity;
use itertools::Itertools;
+use list_item::RoomListItem;
use nostr_sdk::prelude::*;
use registry::room::{Room, RoomKind};
use registry::{Registry, RoomEmitter};
@@ -37,7 +36,7 @@ use ui::{ContextModal, IconName, Selectable, Sizable, StyledExt};
use crate::views::compose;
-mod element;
+mod list_item;
const FIND_DELAY: u64 = 600;
const FIND_LIMIT: usize = 10;
@@ -58,7 +57,6 @@ pub struct Sidebar {
// Rooms
indicator: Entity