From 0fc7d2f6d1ece62e7105f1db949fdf70b9dfda01 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Sat, 14 Mar 2026 09:10:23 +0700 Subject: [PATCH] . --- crates/coop/src/workspace.rs | 27 +++++++++++++++++++-------- crates/device/src/lib.rs | 21 ++++++++++++++++++--- crates/relay_auth/src/lib.rs | 5 +++-- crates/state/src/lib.rs | 7 ++++++- crates/ui/src/notification.rs | 15 +++++++++++++-- 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/crates/coop/src/workspace.rs b/crates/coop/src/workspace.rs index 099bde9..6f82f8f 100644 --- a/crates/coop/src/workspace.rs +++ b/crates/coop/src/workspace.rs @@ -27,9 +27,9 @@ use crate::dialogs::{accounts, settings}; use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list}; use crate::sidebar; +const PREPARE_MSG: &str = "Coop is preparing a new identity for you. This may take a moment..."; const ENC_MSG: &str = "Encryption Key is a special key that used to encrypt and decrypt your messages. \ - Your identity is completely decoupled from all encryption processes to protect your privacy."; - + Your identity is completely decoupled from all encryption processes to protect your privacy."; const ENC_WARN: &str = "By resetting your encryption key, you will lose access to \ all your encrypted messages before. This action cannot be undone."; @@ -37,6 +37,7 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity { cx.new(|cx| Workspace::new(window, cx)) } +struct SignerNotifcation; struct RelayNotifcation; #[derive(Action, Clone, PartialEq, Eq, Deserialize)] @@ -107,21 +108,29 @@ impl Workspace { // Subscribe to the signer events cx.subscribe_in(&nostr, window, move |this, _state, event, window, cx| { match event { + StateEvent::Creating => { + let note = Notification::new() + .id::() + .title("Preparing a new identity") + .message(PREPARE_MSG) + .autohide(false) + .with_kind(NotificationKind::Info); + + window.push_notification(note, cx); + } StateEvent::Connecting => { let note = Notification::new() .id::() - .message("Connecting to the bootstrap relay...") - .with_kind(NotificationKind::Info) - .icon(IconName::Relay); + .message("Connecting to the bootstrap relays...") + .with_kind(NotificationKind::Info); window.push_notification(note, cx); } StateEvent::Connected => { let note = Notification::new() .id::() - .message("Connected to the bootstrap relay") - .with_kind(NotificationKind::Success) - .icon(IconName::Relay); + .message("Connected to the bootstrap relays") + .with_kind(NotificationKind::Success); window.push_notification(note, cx); } @@ -136,6 +145,8 @@ impl Workspace { this.set_center_layout(window, cx); this.set_relay_connected(false, cx); this.set_inbox_connected(false, cx); + // Clear the signer notification + window.clear_notification::(cx); } _ => {} }; diff --git a/crates/device/src/lib.rs b/crates/device/src/lib.rs index 61dc1b3..684b413 100644 --- a/crates/device/src/lib.rs +++ b/crates/device/src/lib.rs @@ -6,11 +6,13 @@ use std::time::Duration; use anyhow::{Context as AnyhowContext, Error, anyhow}; use gpui::{ App, AppContext, Context, Entity, EventEmitter, Global, IntoElement, ParentElement, - SharedString, Styled, Task, Window, div, relative, + SharedString, Styled, Subscription, Task, Window, div, relative, }; use nostr_sdk::prelude::*; use person::PersonRegistry; -use state::{Announcement, DEVICE_GIFTWRAP, DeviceState, NostrRegistry, TIMEOUT, app_name}; +use state::{ + Announcement, DEVICE_GIFTWRAP, DeviceState, NostrRegistry, StateEvent, TIMEOUT, app_name, +}; use theme::ActiveTheme; use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; @@ -48,6 +50,9 @@ pub struct DeviceRegistry { /// Async tasks tasks: Vec>>, + + /// Event subscription + _subscription: Option, } impl EventEmitter for DeviceRegistry {} @@ -65,16 +70,26 @@ impl DeviceRegistry { /// Create a new device registry instance fn new(window: &mut Window, cx: &mut Context) -> Self { + let nostr = NostrRegistry::global(cx); let state = DeviceState::default(); + let subscription = + Some( + cx.subscribe_in(&nostr, window, |this, _state, ev, _window, cx| { + if let StateEvent::SignerSet = ev { + this.get_announcement(cx); + } + }), + ); + cx.defer_in(window, |this, window, cx| { this.handle_notifications(window, cx); - this.get_announcement(cx); }); Self { state, tasks: vec![], + _subscription: subscription, } } diff --git a/crates/relay_auth/src/lib.rs b/crates/relay_auth/src/lib.rs index b14e8e5..710d0d2 100644 --- a/crates/relay_auth/src/lib.rs +++ b/crates/relay_auth/src/lib.rs @@ -17,7 +17,7 @@ use state::NostrRegistry; use theme::ActiveTheme; use ui::button::{Button, ButtonVariants}; use ui::notification::Notification; -use ui::{Disableable, IconName, Sizable, WindowExtension, v_flex}; +use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, v_flex}; const AUTH_MESSAGE: &str = "Approve the authentication request to allow Coop to continue sending or receiving events."; @@ -344,8 +344,9 @@ impl RelayAuth { .px_1p5() .rounded_sm() .text_xs() + .font_semibold() .bg(cx.theme().elevated_surface_background) - .text_color(cx.theme().text_accent) + .text_color(cx.theme().text) .child(url.clone()), ) .into_any_element() diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index e7f5d60..5a7d322 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -44,6 +44,8 @@ impl Global for GlobalNostrRegistry {} /// Signer event. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum StateEvent { + /// Creating the signer + Creating, /// Connecting to the bootstrapping relay Connecting, /// Connected to the bootstrapping relay @@ -289,6 +291,9 @@ impl NostrRegistry { // Create a write credential task let write_credential = cx.write_credentials(&username, &username, &secret); + // Emit creating event + cx.emit(StateEvent::Creating); + // Run async tasks in background let task: Task> = cx.background_spawn(async move { let signer = async_keys.into_nostr_signer(); @@ -301,7 +306,7 @@ impl NostrRegistry { client .send_event(&event) .to(BOOTSTRAP_RELAYS) - .ok_timeout(Duration::from_secs(TIMEOUT)) + .ack_policy(AckPolicy::none()) .await?; // Construct the default metadata diff --git a/crates/ui/src/notification.rs b/crates/ui/src/notification.rs index aa88753..ab75a87 100644 --- a/crates/ui/src/notification.rs +++ b/crates/ui/src/notification.rs @@ -330,7 +330,12 @@ impl Render for Notification { .items_start() .refine_style(&self.style) .when_some(icon, |this, icon| { - this.child(div().flex_shrink_0().child(icon)) + this.child( + div() + .flex_shrink_0() + .when(self.message.is_some(), |this| this.pt_0p5()) + .child(icon), + ) }) .child( v_flex() @@ -340,7 +345,13 @@ impl Render for Notification { this.child(div().text_sm().font_semibold().child(title)) }) .when_some(self.message.clone(), |this, message| { - this.child(div().text_sm().line_height(relative(1.25)).child(message)) + this.child( + div() + .text_sm() + .text_color(cx.theme().text_muted) + .line_height(relative(1.3)) + .child(message), + ) }) .when_some(content, |this, content| this.child(content)) .when_some(action, |this, action| {