add relay states to ui
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m33s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m31s

This commit is contained in:
2026-02-11 17:46:10 +07:00
parent 9380288fc1
commit 836d9a99e1
10 changed files with 102 additions and 26 deletions

1
Cargo.lock generated
View File

@@ -4651,6 +4651,7 @@ version = "0.3.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"common", "common",
"device",
"flume", "flume",
"gpui", "gpui",
"log", "log",

View File

@@ -287,7 +287,7 @@ impl Room {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
if profiles.len() > 2 { if profiles.len() > 3 {
name = format!("{}, +{}", name, profiles.len() - 2); name = format!("{}, +{}", name, profiles.len() - 2);
} }

View File

@@ -23,7 +23,9 @@ use ui::divider::Divider;
use ui::indicator::Indicator; use ui::indicator::Indicator;
use ui::input::{InputEvent, InputState, TextInput}; use ui::input::{InputEvent, InputState, TextInput};
use ui::notification::Notification; 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; mod entry;
@@ -635,10 +637,12 @@ impl Render for Sidebar {
.border_b_1() .border_b_1()
.border_color(cx.theme().border_variant) .border_color(cx.theme().border_variant)
.child( .child(
div() h_flex()
.gap_0p5()
.text_xs() .text_xs()
.font_semibold() .font_semibold()
.text_color(cx.theme().text_muted) .text_color(cx.theme().text_muted)
.child(Icon::new(IconName::ChevronDown))
.child(SharedString::from("Results")), .child(SharedString::from("Results")),
) )
.child( .child(
@@ -660,10 +664,12 @@ impl Render for Sidebar {
.gap_1() .gap_1()
.flex_1() .flex_1()
.child( .child(
div() h_flex()
.gap_0p5()
.text_xs() .text_xs()
.font_semibold() .font_semibold()
.text_color(cx.theme().text_muted) .text_color(cx.theme().text_muted)
.child(Icon::new(IconName::ChevronDown))
.child(SharedString::from("Suggestions")), .child(SharedString::from("Suggestions")),
) )
.child( .child(

View File

@@ -12,8 +12,8 @@ use gpui::{
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use person::PersonRegistry; use person::PersonRegistry;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use state::NostrRegistry; use state::{NostrRegistry, RelayState};
use theme::{SIDEBAR_WIDTH, TITLEBAR_HEIGHT}; use theme::{ActiveTheme, SIDEBAR_WIDTH, TITLEBAR_HEIGHT};
use titlebar::TitleBar; use titlebar::TitleBar;
use ui::avatar::Avatar; use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants}; use ui::button::{Button, ButtonVariants};
@@ -102,7 +102,7 @@ impl Workspace {
subscriptions.push( subscriptions.push(
// Observe the NIP-65 state // Observe the NIP-65 state
cx.observe(&nip65_state, move |this, state, cx| { 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); this.get_current_user(cx);
} }
}), }),
@@ -202,9 +202,12 @@ impl Workspace {
} }
fn titlebar_left(&mut self, _window: &mut Window, cx: &Context<Self>) -> impl IntoElement { fn titlebar_left(&mut self, _window: &mut Window, cx: &Context<Self>) -> impl IntoElement {
let nostr = NostrRegistry::global(cx);
let nip65 = nostr.read(cx).nip65_state();
let nip17 = nostr.read(cx).nip17_state();
h_flex() h_flex()
.h(TITLEBAR_HEIGHT) .h(TITLEBAR_HEIGHT)
.w(SIDEBAR_WIDTH)
.flex_shrink_0() .flex_shrink_0()
.justify_between() .justify_between()
.gap_2() .gap_2()
@@ -229,14 +232,51 @@ impl Workspace {
}), }),
) )
}) })
.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(
fn titlebar_center(&mut self, _window: &mut Window, _cx: &Context<Self>) -> impl IntoElement { h_flex()
h_flex().h(TITLEBAR_HEIGHT).flex_1() .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<Self>) -> impl IntoElement { fn titlebar_right(&mut self, _window: &mut Window, _cx: &Context<Self>) -> 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 // Titlebar elements
let left = self.titlebar_left(window, cx).into_any_element(); 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(); let right = self.titlebar_right(window, cx).into_any_element();
// Update title bar children // Update title bar children
self.titlebar.update(cx, |this, _cx| { self.titlebar.update(cx, |this, _cx| {
this.set_children(vec![left, center, right]); this.set_children(vec![left, right]);
}); });
div() div()

View File

@@ -9,6 +9,20 @@ pub enum DeviceState {
Set, 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 /// Announcement
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Announcement { pub struct Announcement {

View File

@@ -30,12 +30,12 @@ pub struct DeviceRegistry {
/// Device signer /// Device signer
pub device_signer: Entity<Option<Arc<dyn NostrSigner>>>, pub device_signer: Entity<Option<Arc<dyn NostrSigner>>>,
/// Device state
pub state: DeviceState,
/// Device requests /// Device requests
requests: Entity<HashSet<Event>>, requests: Entity<HashSet<Event>>,
/// Device state
state: DeviceState,
/// Async tasks /// Async tasks
tasks: Vec<Task<Result<(), Error>>>, tasks: Vec<Task<Result<(), Error>>>,

View File

@@ -7,6 +7,7 @@ publish.workspace = true
[dependencies] [dependencies]
common = { path = "../common" } common = { path = "../common" }
state = { path = "../state" } state = { path = "../state" }
device = { path = "../device" }
gpui.workspace = true gpui.workspace = true
nostr-sdk.workspace = true nostr-sdk.workspace = true

View File

@@ -5,11 +5,12 @@ use std::time::Duration;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use common::EventUtils; use common::EventUtils;
use device::Announcement;
use gpui::{App, AppContext, Context, Entity, Global, Task}; use gpui::{App, AppContext, Context, Entity, Global, Task};
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
pub use person::*; pub use person::*;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use state::{Announcement, NostrRegistry, BOOTSTRAP_RELAYS, TIMEOUT}; use state::{NostrRegistry, BOOTSTRAP_RELAYS, TIMEOUT};
mod person; mod person;

View File

@@ -1,9 +1,9 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use device::Announcement;
use gpui::SharedString; use gpui::SharedString;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use state::Announcement;
const IMAGE_RESIZER: &str = "https://wsrv.nl"; const IMAGE_RESIZER: &str = "https://wsrv.nl";

View File

@@ -12,13 +12,11 @@ use nostr_lmdb::NostrLmdb;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
mod constants; mod constants;
mod device;
mod event; mod event;
mod nip05; mod nip05;
mod signer; mod signer;
pub use constants::*; pub use constants::*;
pub use device::*;
pub use event::*; pub use event::*;
pub use nip05::*; pub use nip05::*;
pub use signer::*; pub use signer::*;
@@ -154,13 +152,13 @@ impl NostrRegistry {
let client = self.client(); let client = self.client();
self.tasks.push(cx.background_spawn(async move { self.tasks.push(cx.background_spawn(async move {
// Add bootstrap relay to the relay pool // Add search relay to the relay pool
for url in BOOTSTRAP_RELAYS.into_iter() { for url in SEARCH_RELAYS.into_iter() {
client.add_relay(url).await?; client.add_relay(url).await?;
} }
// Add search relay to the relay pool // Add bootstrap relay to the relay pool
for url in SEARCH_RELAYS.into_iter() { for url in BOOTSTRAP_RELAYS.into_iter() {
client.add_relay(url).await?; client.add_relay(url).await?;
} }
@@ -404,6 +402,12 @@ impl NostrRegistry {
let client = self.client(); let client = self.client();
let nip65 = self.nip65.downgrade(); let nip65 = self.nip65.downgrade();
// Set state to checking
self.nip65.update(cx, |this, cx| {
*this = RelayState::Checking;
cx.notify();
});
let task: Task<Result<RelayState, Error>> = cx.background_spawn(async move { let task: Task<Result<RelayState, Error>> = cx.background_spawn(async move {
let signer = client.signer().context("Signer not found")?; let signer = client.signer().context("Signer not found")?;
let public_key = signer.get_public_key().await?; let public_key = signer.get_public_key().await?;
@@ -479,6 +483,12 @@ impl NostrRegistry {
let client = self.client(); let client = self.client();
let nip17 = self.nip17.downgrade(); let nip17 = self.nip17.downgrade();
// Set state to checking
self.nip17.update(cx, |this, cx| {
*this = RelayState::Checking;
cx.notify();
});
let task: Task<Result<RelayState, Error>> = cx.background_spawn(async move { let task: Task<Result<RelayState, Error>> = cx.background_spawn(async move {
let signer = client.signer().context("Signer not found")?; let signer = client.signer().context("Signer not found")?;
let public_key = signer.get_public_key().await?; let public_key = signer.get_public_key().await?;
@@ -966,6 +976,10 @@ impl RelayState {
matches!(self, RelayState::Idle) matches!(self, RelayState::Idle)
} }
pub fn checking(&self) -> bool {
matches!(self, RelayState::Checking)
}
pub fn not_configured(&self) -> bool { pub fn not_configured(&self) -> bool {
matches!(self, RelayState::NotConfigured) matches!(self, RelayState::NotConfigured)
} }