Redesign for the v1 stable release #3
@@ -16,7 +16,7 @@ use gpui::{
|
|||||||
};
|
};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use state::{tracker, NostrRegistry, RelayState, GIFTWRAP_SUBSCRIPTION};
|
use state::{tracker, NostrRegistry, RelayState, DEVICE_GIFTWRAP, USER_GIFTWRAP};
|
||||||
|
|
||||||
mod message;
|
mod message;
|
||||||
mod room;
|
mod room;
|
||||||
@@ -189,7 +189,8 @@ impl ChatRegistry {
|
|||||||
|
|
||||||
self.notifications = Some(cx.background_spawn(async move {
|
self.notifications = Some(cx.background_spawn(async move {
|
||||||
let initialized_at = Timestamp::now();
|
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 notifications = client.notifications();
|
||||||
let mut processed_events = HashSet::new();
|
let mut processed_events = HashSet::new();
|
||||||
@@ -240,7 +241,7 @@ impl ChatRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RelayMessage::EndOfStoredEvents(id) => {
|
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();
|
tx.send_async(NostrEvent::Eose).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,23 +8,22 @@ use dock::panel::{Panel, PanelEvent};
|
|||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
deferred, div, rems, uniform_list, App, AppContext, Context, Entity, EventEmitter, FocusHandle,
|
deferred, div, rems, uniform_list, App, AppContext, Context, Entity, EventEmitter, FocusHandle,
|
||||||
Focusable, InteractiveElement, IntoElement, ParentElement, Render, RetainAllImageCache,
|
Focusable, IntoElement, ParentElement, Render, RetainAllImageCache, SharedString, Styled,
|
||||||
SharedString, Styled, Subscription, Task, Window,
|
Subscription, Task, Window,
|
||||||
};
|
};
|
||||||
use gpui_tokio::Tokio;
|
use gpui_tokio::Tokio;
|
||||||
use list_item::RoomListItem;
|
use list_item::RoomListItem;
|
||||||
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, GIFTWRAP_SUBSCRIPTION};
|
use state::NostrRegistry;
|
||||||
use theme::{ActiveTheme, TITLEBAR_HEIGHT};
|
use theme::{ActiveTheme, TITLEBAR_HEIGHT};
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::indicator::Indicator;
|
use ui::indicator::Indicator;
|
||||||
use ui::input::{InputEvent, InputState, TextInput};
|
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;
|
use crate::dialogs::compose::compose_button;
|
||||||
|
|
||||||
mod list_item;
|
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(
|
fn render_list_items(
|
||||||
&self,
|
&self,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
@@ -592,8 +507,6 @@ impl Render for Sidebar {
|
|||||||
};
|
};
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.on_action(cx.listener(Self::on_reload))
|
|
||||||
.on_action(cx.listener(Self::on_manage))
|
|
||||||
.image_cache(self.image_cache.clone())
|
.image_cache(self.image_cache.clone())
|
||||||
.size_full()
|
.size_full()
|
||||||
.relative()
|
.relative()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub use device::*;
|
|||||||
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task};
|
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use state::{NostrRegistry, RelayState, GIFTWRAP_SUBSCRIPTION, TIMEOUT};
|
use state::{NostrRegistry, RelayState, DEVICE_GIFTWRAP, TIMEOUT, USER_GIFTWRAP};
|
||||||
|
|
||||||
mod device;
|
mod device;
|
||||||
|
|
||||||
@@ -271,20 +271,30 @@ impl DeviceRegistry {
|
|||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let urls = messaging_relays.await;
|
let urls = messaging_relays.await;
|
||||||
let id = SubscriptionId::new(GIFTWRAP_SUBSCRIPTION);
|
|
||||||
let mut filters = vec![];
|
|
||||||
|
|
||||||
// Construct a filter to get user messages
|
// Get messages with dekey
|
||||||
filters.push(Filter::new().kind(Kind::GiftWrap).pubkey(public_key));
|
|
||||||
|
|
||||||
// Construct a filter to get dekey messages if available
|
|
||||||
if let Some(signer) = device_signer.as_ref() {
|
if let Some(signer) = device_signer.as_ref() {
|
||||||
if let Ok(pkey) = signer.get_public_key().await {
|
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}");
|
log::error!("Failed to subscribe to gift wrap events: {e}");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ pub const TIMEOUT: u64 = 3;
|
|||||||
pub const NOSTR_CONNECT_TIMEOUT: u64 = 200;
|
pub const NOSTR_CONNECT_TIMEOUT: u64 = 200;
|
||||||
/// Default Nostr Connect relay
|
/// Default Nostr Connect relay
|
||||||
pub const NOSTR_CONNECT_RELAY: &str = "wss://relay.nsec.app";
|
pub const NOSTR_CONNECT_RELAY: &str = "wss://relay.nsec.app";
|
||||||
|
/// Default subscription id for device gift wrap events
|
||||||
/// Default subscription id for gift wrap events
|
pub const DEVICE_GIFTWRAP: &str = "device-gift-wraps";
|
||||||
pub const GIFTWRAP_SUBSCRIPTION: &str = "giftwrap-events";
|
/// Default subscription id for user gift wrap events
|
||||||
|
pub const USER_GIFTWRAP: &str = "user-gift-wraps";
|
||||||
|
|
||||||
struct GlobalNostrRegistry(Entity<NostrRegistry>);
|
struct GlobalNostrRegistry(Entity<NostrRegistry>);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user