.
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m48s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m49s

This commit is contained in:
2026-01-29 14:45:51 +07:00
parent a87111e138
commit 04287cae3a
4 changed files with 31 additions and 106 deletions

View File

@@ -16,7 +16,7 @@ use gpui::{
};
use nostr_sdk::prelude::*;
use smallvec::{smallvec, SmallVec};
use state::{tracker, NostrRegistry, RelayState, GIFTWRAP_SUBSCRIPTION};
use state::{tracker, NostrRegistry, RelayState, DEVICE_GIFTWRAP, USER_GIFTWRAP};
mod message;
mod room;
@@ -189,7 +189,8 @@ impl ChatRegistry {
self.notifications = Some(cx.background_spawn(async move {
let initialized_at = Timestamp::now();
let subscription_id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION);
let sub_id1 = SubscriptionId::new(DEVICE_GIFTWRAP);
let sub_id2 = SubscriptionId::new(USER_GIFTWRAP);
let mut notifications = client.notifications();
let mut processed_events = HashSet::new();
@@ -240,7 +241,7 @@ impl ChatRegistry {
}
}
RelayMessage::EndOfStoredEvents(id) => {
if id.as_ref() == &subscription_id {
if id.as_ref() == &sub_id1 || id.as_ref() == &sub_id2 {
tx.send_async(NostrEvent::Eose).await.ok();
}
}

View File

@@ -8,23 +8,22 @@ use dock::panel::{Panel, PanelEvent};
use gpui::prelude::FluentBuilder;
use gpui::{
deferred, div, rems, uniform_list, App, AppContext, Context, Entity, EventEmitter, FocusHandle,
Focusable, InteractiveElement, IntoElement, ParentElement, Render, RetainAllImageCache,
SharedString, Styled, Subscription, Task, Window,
Focusable, IntoElement, ParentElement, Render, RetainAllImageCache, SharedString, Styled,
Subscription, Task, Window,
};
use gpui_tokio::Tokio;
use list_item::RoomListItem;
use nostr_sdk::prelude::*;
use person::PersonRegistry;
use smallvec::{smallvec, SmallVec};
use state::{NostrRegistry, GIFTWRAP_SUBSCRIPTION};
use state::NostrRegistry;
use theme::{ActiveTheme, TITLEBAR_HEIGHT};
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
use ui::indicator::Indicator;
use ui::input::{InputEvent, InputState, TextInput};
use ui::{h_flex, v_flex, Icon, IconName, Sizable, StyledExt, WindowExtension};
use ui::{h_flex, v_flex, IconName, Sizable, StyledExt, WindowExtension};
use crate::actions::{RelayStatus, Reload};
use crate::dialogs::compose::compose_button;
mod list_item;
@@ -434,90 +433,6 @@ impl Sidebar {
}
}
fn on_reload(&mut self, _ev: &Reload, window: &mut Window, cx: &mut Context<Self>) {
ChatRegistry::global(cx).update(cx, |this, cx| {
this.get_rooms(cx);
});
window.push_notification("Reload", cx);
}
fn on_manage(&mut self, _ev: &RelayStatus, window: &mut Window, cx: &mut Context<Self>) {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let task: Task<Result<Vec<Relay>, Error>> = cx.background_spawn(async move {
let id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION);
let subscription = client.subscription(&id).await;
let mut relays: Vec<Relay> = vec![];
for (url, _filter) in subscription.into_iter() {
relays.push(client.pool().relay(url).await?);
}
Ok(relays)
});
cx.spawn_in(window, async move |this, cx| {
if let Ok(relays) = task.await {
this.update_in(cx, |this, window, cx| {
this.manage_relays(relays, window, cx);
})
.ok();
}
})
.detach();
}
fn manage_relays(&mut self, relays: Vec<Relay>, window: &mut Window, cx: &mut Context<Self>) {
window.open_modal(cx, move |this, _window, cx| {
this.show_close(true)
.overlay_closable(true)
.keyboard(true)
.title(SharedString::from("Messaging Relay Status"))
.child(v_flex().pb_4().gap_2().children({
let mut items = Vec::with_capacity(relays.len());
for relay in relays.clone().into_iter() {
let url = relay.url().to_string();
let time = relay.stats().connected_at().to_ago();
let connected = relay.is_connected();
items.push(
h_flex()
.h_8()
.px_2()
.justify_between()
.text_xs()
.bg(cx.theme().elevated_surface_background)
.rounded(cx.theme().radius)
.child(
h_flex()
.gap_1()
.font_semibold()
.child(
Icon::new(IconName::Relay)
.small()
.text_color(cx.theme().danger_active)
.when(connected, |this| {
this.text_color(gpui::green().alpha(0.75))
}),
)
.child(url),
)
.child(
div().text_right().text_color(cx.theme().text_muted).child(
SharedString::from(format!("Last activity: {}", time)),
),
),
);
}
items
}))
});
}
fn render_list_items(
&self,
range: Range<usize>,
@@ -592,8 +507,6 @@ impl Render for Sidebar {
};
v_flex()
.on_action(cx.listener(Self::on_reload))
.on_action(cx.listener(Self::on_manage))
.image_cache(self.image_cache.clone())
.size_full()
.relative()

View File

@@ -8,7 +8,7 @@ pub use device::*;
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task};
use nostr_sdk::prelude::*;
use smallvec::{smallvec, SmallVec};
use state::{NostrRegistry, RelayState, GIFTWRAP_SUBSCRIPTION, TIMEOUT};
use state::{NostrRegistry, RelayState, DEVICE_GIFTWRAP, TIMEOUT, USER_GIFTWRAP};
mod device;
@@ -271,20 +271,30 @@ impl DeviceRegistry {
cx.background_spawn(async move {
let urls = messaging_relays.await;
let id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION);
let mut filters = vec![];
// Construct a filter to get user messages
filters.push(Filter::new().kind(Kind::GiftWrap).pubkey(public_key));
// Construct a filter to get dekey messages if available
// Get messages with dekey
if let Some(signer) = device_signer.as_ref() {
if let Ok(pkey) = signer.get_public_key().await {
filters.push(Filter::new().kind(Kind::GiftWrap).pubkey(pkey));
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(pkey);
let id = SubscriptionId::new(DEVICE_GIFTWRAP);
if let Err(e) = client
.subscribe_with_id_to(&urls, id, vec![filter], None)
.await
{
log::error!("Failed to subscribe to gift wrap events: {e}");
}
}
}
if let Err(e) = client.subscribe_with_id_to(urls, id, filters, None).await {
// Get messages with user key
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
let id = SubscriptionId::new(USER_GIFTWRAP);
if let Err(e) = client
.subscribe_with_id_to(urls, id, vec![filter], None)
.await
{
log::error!("Failed to subscribe to gift wrap events: {e}");
}
})

View File

@@ -31,9 +31,10 @@ pub const TIMEOUT: u64 = 3;
pub const NOSTR_CONNECT_TIMEOUT: u64 = 200;
/// Default Nostr Connect relay
pub const NOSTR_CONNECT_RELAY: &str = "wss://relay.nsec.app";
/// Default subscription id for gift wrap events
pub const GIFTWRAP_SUBSCRIPTION: &str = "giftwrap-events";
/// Default subscription id for device gift wrap events
pub const DEVICE_GIFTWRAP: &str = "device-gift-wraps";
/// Default subscription id for user gift wrap events
pub const USER_GIFTWRAP: &str = "user-gift-wraps";
struct GlobalNostrRegistry(Entity<NostrRegistry>);