From 8c211be11ad959bc54dbd82b20ae15b310bdf265 Mon Sep 17 00:00:00 2001
From: reya <123083837+reyamir@users.noreply.github.com>
Date: Fri, 2 May 2025 17:03:49 +0700
Subject: [PATCH] feat: add search and refactor modal (#19)
* add find button to sidebar
* update
* improve search
* add error msg
---
Cargo.lock | 72 ++---
Packager.toml | 18 --
assets/icons/search-fill.svg | 3 +
assets/icons/search.svg | 2 +-
crates/coop/src/chatspace.rs | 21 +-
crates/coop/src/main.rs | 11 +-
crates/coop/src/views/compose.rs | 28 +-
crates/coop/src/views/contacts.rs | 173 ------------
crates/coop/src/views/mod.rs | 2 +-
crates/coop/src/views/search.rs | 357 ++++++++++++++++++++++++
crates/coop/src/views/sidebar/button.rs | 8 +-
crates/coop/src/views/sidebar/mod.rs | 18 +-
crates/global/src/constants.rs | 6 +-
crates/ui/src/button.rs | 2 +-
crates/ui/src/icon.rs | 2 +
crates/ui/src/modal.rs | 99 +++----
16 files changed, 511 insertions(+), 311 deletions(-)
delete mode 100644 Packager.toml
create mode 100644 assets/icons/search-fill.svg
delete mode 100644 crates/coop/src/views/contacts.rs
create mode 100644 crates/coop/src/views/search.rs
diff --git a/Cargo.lock b/Cargo.lock
index 512449f..68c82ab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1136,7 +1136,7 @@ dependencies = [
[[package]]
name = "collections"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"indexmap",
"rustc-hash 2.1.1",
@@ -1525,7 +1525,7 @@ dependencies = [
[[package]]
name = "derive_refineable"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"proc-macro2",
"quote",
@@ -2316,7 +2316,7 @@ dependencies = [
[[package]]
name = "gpui"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"as-raw-xcb-connection",
@@ -2408,7 +2408,7 @@ dependencies = [
[[package]]
name = "gpui_macros"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"proc-macro2",
"quote",
@@ -2459,9 +2459,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
-version = "0.15.2"
+version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
[[package]]
name = "heck"
@@ -2632,7 +2632,7 @@ dependencies = [
[[package]]
name = "http_client"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"bytes",
@@ -2649,7 +2649,7 @@ dependencies = [
[[package]]
name = "http_client_tls"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"rustls",
"rustls-platform-verifier",
@@ -2952,7 +2952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
- "hashbrown 0.15.2",
+ "hashbrown 0.15.3",
"serde",
]
@@ -3390,7 +3390,7 @@ dependencies = [
[[package]]
name = "media"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"bindgen 0.71.1",
@@ -3582,7 +3582,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "nostr"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"aes",
"base64",
@@ -3607,7 +3607,7 @@ dependencies = [
[[package]]
name = "nostr-connect"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"async-utility",
"nostr",
@@ -3619,7 +3619,7 @@ dependencies = [
[[package]]
name = "nostr-database"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"flatbuffers",
"lru",
@@ -3630,7 +3630,7 @@ dependencies = [
[[package]]
name = "nostr-lmdb"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"async-utility",
"heed",
@@ -3643,7 +3643,7 @@ dependencies = [
[[package]]
name = "nostr-relay-pool"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"async-utility",
"async-wsocket",
@@ -3659,7 +3659,7 @@ dependencies = [
[[package]]
name = "nostr-sdk"
version = "0.41.0"
-source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
+source = "git+https://github.com/rust-nostr/nostr#5a2e66874c6e6cb0f5b8bcb50c1d37aecd7a5d90"
dependencies = [
"async-utility",
"nostr",
@@ -4150,9 +4150,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
-version = "0.9.107"
+version = "0.9.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
+checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
dependencies = [
"cc",
"libc",
@@ -4586,9 +4586,9 @@ dependencies = [
[[package]]
name = "quinn-udp"
-version = "0.5.11"
+version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5"
+checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842"
dependencies = [
"cfg_aliases 0.2.1",
"libc",
@@ -4816,7 +4816,7 @@ dependencies = [
[[package]]
name = "refineable"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"derive_refineable",
"workspace-hack",
@@ -4955,7 +4955,7 @@ dependencies = [
[[package]]
name = "reqwest_client"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"bytes",
@@ -5091,9 +5091,9 @@ dependencies = [
[[package]]
name = "rustix"
-version = "1.0.5"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
+checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
dependencies = [
"bitflags 2.9.0",
"errno",
@@ -5425,7 +5425,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
[[package]]
name = "semantic_version"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"serde",
@@ -5542,9 +5542,9 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
[[package]]
name = "sha2"
-version = "0.10.8"
+version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -5748,7 +5748,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "sum_tree"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"arrayvec",
"log",
@@ -5903,9 +5903,9 @@ dependencies = [
[[package]]
name = "synstructure"
-version = "0.13.1"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
@@ -6015,7 +6015,7 @@ dependencies = [
"fastrand 2.3.0",
"getrandom 0.3.2",
"once_cell",
- "rustix 1.0.5",
+ "rustix 1.0.7",
"windows-sys 0.59.0",
]
@@ -6658,7 +6658,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "util"
version = "0.1.0"
-source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
+source = "git+https://github.com/zed-industries/zed#afeb3d4fd94fae5cfc635e8a4f6eb56c8aae67fd"
dependencies = [
"anyhow",
"async-fs",
@@ -7021,18 +7021,18 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
-version = "0.26.9"
+version = "0.26.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180d2741b6115c3d906577e6533ad89472d48d96df00270fccb78233073d77f7"
+checksum = "c99403924bc5f23afefc319b8ac67ed0e50669f6e52a413314cccb1fdbc93ba0"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webpki-roots"
-version = "0.26.9"
+version = "0.26.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29aad86cec885cafd03e8305fd727c418e970a521322c91688414d5b8efba16b"
+checksum = "37493cadf42a2a939ed404698ded7fb378bf301b5011f973361779a3a74f8c93"
dependencies = [
"rustls-pki-types",
]
diff --git a/Packager.toml b/Packager.toml
deleted file mode 100644
index 5b62e35..0000000
--- a/Packager.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-name = "coop"
-description = "Coop is a cross-platform Nostr client designed for secure communication focus on simplicity and customizability."
-product-name = "Coop"
-version = "0.1.5"
-category = "SocialNetworking"
-identifier = "su.reya.coop"
-resources = ["assets/*/*", "Cargo.toml", "./LICENSE", "./README.md"]
-binaries = [ { path = "coop", main = true } ]
-before-packaging-command = "cargo build --release"
-out-dir = "./target/release"
-icons = [
- "crates/coop/resources/32x32.png",
- "crates/coop/resources/128x128.png",
- "crates/coop/resources/128x128@2x.png",
- "crates/coop/resources/app-icon.icns",
- "crates/coop/resources/app-icon.png",
- "crates/coop/resources/app-icon.ico",
-]
diff --git a/assets/icons/search-fill.svg b/assets/icons/search-fill.svg
new file mode 100644
index 0000000..3e8bb4e
--- /dev/null
+++ b/assets/icons/search-fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/search.svg b/assets/icons/search.svg
index 2ad28af..5207a79 100644
--- a/assets/icons/search.svg
+++ b/assets/icons/search.svg
@@ -1,3 +1,3 @@
diff --git a/crates/coop/src/chatspace.rs b/crates/coop/src/chatspace.rs
index 9f61a95..7c22cc3 100644
--- a/crates/coop/src/chatspace.rs
+++ b/crates/coop/src/chatspace.rs
@@ -20,7 +20,7 @@ use ui::{
use crate::{
lru_cache::cache_provider,
views::{
- chat, compose, contacts, login, new_account, onboarding, profile, relays, sidebar, welcome,
+ chat, compose, login, new_account, onboarding, profile, relays, search, sidebar, welcome,
},
};
@@ -52,8 +52,9 @@ pub enum PanelKind {
pub enum ModalKind {
Profile,
Compose,
- Contact,
+ Search,
Relay,
+ Onboarding,
SetupRelay,
}
@@ -239,14 +240,15 @@ impl ChatSpace {
.child(compose.clone())
})
}
- ModalKind::Contact => {
- let contacts = contacts::init(window, cx);
+ ModalKind::Search => {
+ let search = search::init(window, cx);
- window.open_modal(cx, move |this, _window, _cx| {
- this.width(px(MODAL_WIDTH))
- .title("Contacts")
- .child(contacts.clone())
- });
+ window.open_modal(cx, move |modal, _, _| {
+ modal
+ .closable(false)
+ .width(px(MODAL_WIDTH))
+ .child(search.clone())
+ })
}
ModalKind::Relay => {
let relays = relays::init(window, cx);
@@ -266,6 +268,7 @@ impl ChatSpace {
.child(relays.clone())
});
}
+ _ => {}
};
}
diff --git a/crates/coop/src/main.rs b/crates/coop/src/main.rs
index d58db3a..cfa000a 100644
--- a/crates/coop/src/main.rs
+++ b/crates/coop/src/main.rs
@@ -6,7 +6,10 @@ use futures::{select, FutureExt};
#[cfg(not(target_os = "linux"))]
use global::constants::APP_NAME;
use global::{
- constants::{ALL_MESSAGES_SUB_ID, APP_ID, APP_PUBKEY, BOOTSTRAP_RELAYS, NEW_MESSAGE_SUB_ID},
+ constants::{
+ ALL_MESSAGES_SUB_ID, APP_ID, APP_PUBKEY, BOOTSTRAP_RELAYS, NEW_MESSAGE_SUB_ID,
+ SEARCH_RELAYS,
+ },
get_client,
};
use gpui::{
@@ -72,6 +75,12 @@ fn main() {
}
}
+ for relay in SEARCH_RELAYS.into_iter() {
+ if let Err(e) = client.add_relay(relay).await {
+ log::error!("Failed to add relay {}: {}", relay, e);
+ }
+ }
+
// Establish connection to bootstrap relays
client.connect().await;
diff --git a/crates/coop/src/views/compose.rs b/crates/coop/src/views/compose.rs
index 513cdc1..9c63351 100644
--- a/crates/coop/src/views/compose.rs
+++ b/crates/coop/src/views/compose.rs
@@ -68,7 +68,6 @@ impl Compose {
let user_input = cx.new(|cx| {
TextInput::new(window, cx)
.text_size(ui::Size::Small)
- .small()
.placeholder("npub1...")
});
@@ -116,10 +115,10 @@ impl Compose {
contacts,
selected,
error_message,
+ subscriptions,
is_loading: false,
is_submitting: false,
focus_handle: cx.focus_handle(),
- subscriptions,
}
}
@@ -180,9 +179,10 @@ impl Compose {
window.close_modal(cx);
}
Err(e) => {
- _ = this.update(cx, |this, cx| {
+ this.update(cx, |this, cx| {
this.set_error(Some(e.to_string().into()), cx);
- });
+ })
+ .ok();
}
}
});
@@ -341,6 +341,7 @@ impl Render for Compose {
.gap_1()
.child(
div()
+ .px_3()
.text_sm()
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
.child(DESCRIPTION),
@@ -348,13 +349,14 @@ impl Render for Compose {
.when_some(self.error_message.read(cx).as_ref(), |this, msg| {
this.child(
div()
+ .px_3()
.text_xs()
.text_color(cx.theme().danger)
.child(msg.clone()),
)
})
.child(
- div().flex().flex_col().child(
+ div().px_3().flex().flex_col().child(
div()
.h_10()
.border_b_1()
@@ -372,8 +374,15 @@ impl Render for Compose {
.flex_col()
.gap_2()
.mt_1()
- .child(div().text_sm().font_semibold().child("To:"))
- .child(self.user_input.clone())
+ .child(
+ div()
+ .px_3()
+ .flex()
+ .flex_col()
+ .gap_2()
+ .child(div().text_sm().font_semibold().child("To:"))
+ .child(self.user_input.clone()),
+ )
.map(|this| {
let contacts = self.contacts.read(cx).clone();
let view = cx.entity();
@@ -423,11 +432,10 @@ impl Render for Compose {
.id(ix)
.w_full()
.h_10()
- .px_2()
+ .px_3()
.flex()
.items_center()
.justify_between()
- .rounded(px(cx.theme().radius))
.child(
div()
.flex()
@@ -480,7 +488,7 @@ impl Render for Compose {
}),
)
.child(
- div().mt_2().child(
+ div().p_3().child(
Button::new("create_dm_btn")
.label(label)
.primary()
diff --git a/crates/coop/src/views/contacts.rs b/crates/coop/src/views/contacts.rs
deleted file mode 100644
index 380a7aa..0000000
--- a/crates/coop/src/views/contacts.rs
+++ /dev/null
@@ -1,173 +0,0 @@
-use std::collections::BTreeSet;
-
-use anyhow::Error;
-use common::profile::SharedProfile;
-use global::get_client;
-use gpui::{
- div, img, prelude::FluentBuilder, px, uniform_list, AnyElement, App, AppContext, Context,
- Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement,
- Render, SharedString, Styled, Task, Window,
-};
-use itertools::Itertools;
-use nostr_sdk::prelude::*;
-use ui::{
- button::Button,
- dock_area::panel::{Panel, PanelEvent},
- indicator::Indicator,
- popup_menu::PopupMenu,
- theme::{scale::ColorScaleStep, ActiveTheme},
- Sizable,
-};
-
-const MIN_HEIGHT: f32 = 280.;
-
-pub fn init(window: &mut Window, cx: &mut App) -> Entity {
- Contacts::new(window, cx)
-}
-
-pub struct Contacts {
- contacts: Option>,
- // Panel
- name: SharedString,
- closable: bool,
- zoomable: bool,
- focus_handle: FocusHandle,
-}
-
-impl Contacts {
- pub fn new(window: &mut Window, cx: &mut App) -> Entity {
- cx.new(|cx| Self::view(window, cx))
- }
-
- fn view(_window: &mut Window, cx: &mut Context) -> Self {
- cx.spawn(async move |this, cx| {
- let client = get_client();
-
- let task: Task, Error>> = cx.background_spawn(async move {
- let signer = client.signer().await?;
- let public_key = signer.get_public_key().await?;
- let profiles = client.database().contacts(public_key).await?;
-
- Ok(profiles)
- });
-
- if let Ok(contacts) = task.await {
- cx.update(|cx| {
- this.update(cx, |this, cx| {
- this.contacts = Some(contacts.into_iter().collect_vec());
- cx.notify();
- })
- .ok();
- })
- .ok();
- }
- })
- .detach();
-
- Self {
- contacts: None,
- name: "Contacts".into(),
- closable: true,
- zoomable: true,
- focus_handle: cx.focus_handle(),
- }
- }
-}
-
-impl Panel for Contacts {
- fn panel_id(&self) -> SharedString {
- "ContactPanel".into()
- }
-
- fn title(&self, _cx: &App) -> AnyElement {
- self.name.clone().into_any_element()
- }
-
- fn closable(&self, _cx: &App) -> bool {
- self.closable
- }
-
- fn zoomable(&self, _cx: &App) -> bool {
- self.zoomable
- }
-
- fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
- menu.track_focus(&self.focus_handle)
- }
-
- fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec