From 836d9a99e17549e82990b9722ccd3a19ea3e2a94 Mon Sep 17 00:00:00 2001 From: reya Date: Wed, 11 Feb 2026 17:46:10 +0700 Subject: [PATCH] add relay states to ui --- Cargo.lock | 1 + crates/chat/src/room.rs | 2 +- crates/coop/src/sidebar/mod.rs | 12 +++++-- crates/coop/src/workspace.rs | 61 ++++++++++++++++++++++++++++------ crates/device/src/device.rs | 14 ++++++++ crates/device/src/lib.rs | 6 ++-- crates/person/Cargo.toml | 1 + crates/person/src/lib.rs | 3 +- crates/person/src/person.rs | 2 +- crates/state/src/lib.rs | 26 +++++++++++---- 10 files changed, 102 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d14b4c6..17071ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4651,6 +4651,7 @@ version = "0.3.0" dependencies = [ "anyhow", "common", + "device", "flume", "gpui", "log", diff --git a/crates/chat/src/room.rs b/crates/chat/src/room.rs index f83cced..a09cfea 100644 --- a/crates/chat/src/room.rs +++ b/crates/chat/src/room.rs @@ -287,7 +287,7 @@ impl Room { .collect::>() .join(", "); - if profiles.len() > 2 { + if profiles.len() > 3 { name = format!("{}, +{}", name, profiles.len() - 2); } diff --git a/crates/coop/src/sidebar/mod.rs b/crates/coop/src/sidebar/mod.rs index 942ef6d..fa8d81c 100644 --- a/crates/coop/src/sidebar/mod.rs +++ b/crates/coop/src/sidebar/mod.rs @@ -23,7 +23,9 @@ use ui::divider::Divider; use ui::indicator::Indicator; use ui::input::{InputEvent, InputState, TextInput}; use ui::notification::Notification; -use ui::{h_flex, v_flex, Disableable, IconName, Selectable, Sizable, StyledExt, WindowExtension}; +use ui::{ + h_flex, v_flex, Disableable, Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, +}; mod entry; @@ -635,10 +637,12 @@ impl Render for Sidebar { .border_b_1() .border_color(cx.theme().border_variant) .child( - div() + h_flex() + .gap_0p5() .text_xs() .font_semibold() .text_color(cx.theme().text_muted) + .child(Icon::new(IconName::ChevronDown)) .child(SharedString::from("Results")), ) .child( @@ -660,10 +664,12 @@ impl Render for Sidebar { .gap_1() .flex_1() .child( - div() + h_flex() + .gap_0p5() .text_xs() .font_semibold() .text_color(cx.theme().text_muted) + .child(Icon::new(IconName::ChevronDown)) .child(SharedString::from("Suggestions")), ) .child( diff --git a/crates/coop/src/workspace.rs b/crates/coop/src/workspace.rs index 4d82554..272c9cf 100644 --- a/crates/coop/src/workspace.rs +++ b/crates/coop/src/workspace.rs @@ -12,8 +12,8 @@ use gpui::{ use nostr_sdk::prelude::*; use person::PersonRegistry; use smallvec::{smallvec, SmallVec}; -use state::NostrRegistry; -use theme::{SIDEBAR_WIDTH, TITLEBAR_HEIGHT}; +use state::{NostrRegistry, RelayState}; +use theme::{ActiveTheme, SIDEBAR_WIDTH, TITLEBAR_HEIGHT}; use titlebar::TitleBar; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; @@ -102,7 +102,7 @@ impl Workspace { subscriptions.push( // Observe the NIP-65 state cx.observe(&nip65_state, move |this, state, cx| { - if state.read(cx).idle() { + if state.read(cx).idle() || state.read(cx).checking() { this.get_current_user(cx); } }), @@ -202,9 +202,12 @@ impl Workspace { } fn titlebar_left(&mut self, _window: &mut Window, cx: &Context) -> impl IntoElement { + let nostr = NostrRegistry::global(cx); + let nip65 = nostr.read(cx).nip65_state(); + let nip17 = nostr.read(cx).nip17_state(); + h_flex() .h(TITLEBAR_HEIGHT) - .w(SIDEBAR_WIDTH) .flex_shrink_0() .justify_between() .gap_2() @@ -229,14 +232,51 @@ impl Workspace { }), ) }) - } - - fn titlebar_center(&mut self, _window: &mut Window, _cx: &Context) -> impl IntoElement { - h_flex().h(TITLEBAR_HEIGHT).flex_1() + .map(|this| match nip65.read(cx) { + RelayState::Checking => this.child( + div() + .text_xs() + .text_color(cx.theme().text_muted) + .child(SharedString::from("Fetching user's relay list...")), + ), + RelayState::NotConfigured => this.child( + h_flex() + .h_6() + .w_full() + .px_1() + .text_xs() + .text_color(cx.theme().warning_foreground) + .bg(cx.theme().warning_background) + .rounded_xs() + .child(SharedString::from("User hasn't configured a relay list")), + ), + _ => this, + }) + .map(|this| match nip17.read(cx) { + RelayState::Checking => { + this.child(div().text_xs().text_color(cx.theme().text_muted).child( + SharedString::from("Fetching user's messaging relay list..."), + )) + } + RelayState::NotConfigured => this.child( + h_flex() + .h_6() + .w_full() + .px_1() + .text_xs() + .text_color(cx.theme().warning_foreground) + .bg(cx.theme().warning_background) + .rounded_xs() + .child(SharedString::from( + "User hasn't configured a messaging relay list", + )), + ), + _ => this, + }) } fn titlebar_right(&mut self, _window: &mut Window, _cx: &Context) -> impl IntoElement { - h_flex().h(TITLEBAR_HEIGHT).w(SIDEBAR_WIDTH).flex_shrink_0() + h_flex().h(TITLEBAR_HEIGHT).flex_shrink_0() } } @@ -247,12 +287,11 @@ impl Render for Workspace { // Titlebar elements let left = self.titlebar_left(window, cx).into_any_element(); - let center = self.titlebar_center(window, cx).into_any_element(); let right = self.titlebar_right(window, cx).into_any_element(); // Update title bar children self.titlebar.update(cx, |this, _cx| { - this.set_children(vec![left, center, right]); + this.set_children(vec![left, right]); }); div() diff --git a/crates/device/src/device.rs b/crates/device/src/device.rs index 156be81..2f3b0d8 100644 --- a/crates/device/src/device.rs +++ b/crates/device/src/device.rs @@ -9,6 +9,20 @@ pub enum DeviceState { Set, } +impl DeviceState { + pub fn initial(&self) -> bool { + matches!(self, DeviceState::Initial) + } + + pub fn requesting(&self) -> bool { + matches!(self, DeviceState::Requesting) + } + + pub fn set(&self) -> bool { + matches!(self, DeviceState::Set) + } +} + /// Announcement #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Announcement { diff --git a/crates/device/src/lib.rs b/crates/device/src/lib.rs index 3aefe87..199ff94 100644 --- a/crates/device/src/lib.rs +++ b/crates/device/src/lib.rs @@ -30,12 +30,12 @@ pub struct DeviceRegistry { /// Device signer pub device_signer: Entity>>, + /// Device state + pub state: DeviceState, + /// Device requests requests: Entity>, - /// Device state - state: DeviceState, - /// Async tasks tasks: Vec>>, diff --git a/crates/person/Cargo.toml b/crates/person/Cargo.toml index f0239bf..9d59298 100644 --- a/crates/person/Cargo.toml +++ b/crates/person/Cargo.toml @@ -7,6 +7,7 @@ publish.workspace = true [dependencies] common = { path = "../common" } state = { path = "../state" } +device = { path = "../device" } gpui.workspace = true nostr-sdk.workspace = true diff --git a/crates/person/src/lib.rs b/crates/person/src/lib.rs index 3d15c38..624efe8 100644 --- a/crates/person/src/lib.rs +++ b/crates/person/src/lib.rs @@ -5,11 +5,12 @@ use std::time::Duration; use anyhow::{anyhow, Error}; use common::EventUtils; +use device::Announcement; use gpui::{App, AppContext, Context, Entity, Global, Task}; use nostr_sdk::prelude::*; pub use person::*; use smallvec::{smallvec, SmallVec}; -use state::{Announcement, NostrRegistry, BOOTSTRAP_RELAYS, TIMEOUT}; +use state::{NostrRegistry, BOOTSTRAP_RELAYS, TIMEOUT}; mod person; diff --git a/crates/person/src/person.rs b/crates/person/src/person.rs index cd6a2a8..f37fffd 100644 --- a/crates/person/src/person.rs +++ b/crates/person/src/person.rs @@ -1,9 +1,9 @@ use std::cmp::Ordering; use std::hash::{Hash, Hasher}; +use device::Announcement; use gpui::SharedString; use nostr_sdk::prelude::*; -use state::Announcement; const IMAGE_RESIZER: &str = "https://wsrv.nl"; diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index cf3b9e9..553f86d 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -12,13 +12,11 @@ use nostr_lmdb::NostrLmdb; use nostr_sdk::prelude::*; mod constants; -mod device; mod event; mod nip05; mod signer; pub use constants::*; -pub use device::*; pub use event::*; pub use nip05::*; pub use signer::*; @@ -154,13 +152,13 @@ impl NostrRegistry { let client = self.client(); self.tasks.push(cx.background_spawn(async move { - // Add bootstrap relay to the relay pool - for url in BOOTSTRAP_RELAYS.into_iter() { + // Add search relay to the relay pool + for url in SEARCH_RELAYS.into_iter() { client.add_relay(url).await?; } - // Add search relay to the relay pool - for url in SEARCH_RELAYS.into_iter() { + // Add bootstrap relay to the relay pool + for url in BOOTSTRAP_RELAYS.into_iter() { client.add_relay(url).await?; } @@ -404,6 +402,12 @@ impl NostrRegistry { let client = self.client(); let nip65 = self.nip65.downgrade(); + // Set state to checking + self.nip65.update(cx, |this, cx| { + *this = RelayState::Checking; + cx.notify(); + }); + let task: Task> = cx.background_spawn(async move { let signer = client.signer().context("Signer not found")?; let public_key = signer.get_public_key().await?; @@ -479,6 +483,12 @@ impl NostrRegistry { let client = self.client(); let nip17 = self.nip17.downgrade(); + // Set state to checking + self.nip17.update(cx, |this, cx| { + *this = RelayState::Checking; + cx.notify(); + }); + let task: Task> = cx.background_spawn(async move { let signer = client.signer().context("Signer not found")?; let public_key = signer.get_public_key().await?; @@ -966,6 +976,10 @@ impl RelayState { matches!(self, RelayState::Idle) } + pub fn checking(&self) -> bool { + matches!(self, RelayState::Checking) + } + pub fn not_configured(&self) -> bool { matches!(self, RelayState::NotConfigured) }