diff --git a/crates/coop/src/actions.rs b/crates/coop/src/actions.rs index 327525a1..74dbb4ea 100644 --- a/crates/coop/src/actions.rs +++ b/crates/coop/src/actions.rs @@ -2,7 +2,7 @@ use std::sync::Mutex; use gpui::{actions, App}; -actions!(coop, [DarkMode, Settings, Logout, Quit]); +actions!(coop, [ReloadMetadata, DarkMode, Settings, Logout, Quit]); actions!(sidebar, [Reload, RelayStatus]); pub fn load_embedded_fonts(cx: &App) { diff --git a/crates/coop/src/chatspace.rs b/crates/coop/src/chatspace.rs index 170fc2f1..5c76ca30 100644 --- a/crates/coop/src/chatspace.rs +++ b/crates/coop/src/chatspace.rs @@ -42,7 +42,7 @@ use ui::notification::Notification; use ui::popup_menu::PopupMenuExt; use ui::{h_flex, v_flex, ContextModal, Disableable, IconName, Root, Sizable, StyledExt}; -use crate::actions::{DarkMode, Logout, Settings}; +use crate::actions::{DarkMode, Logout, ReloadMetadata, Settings}; use crate::views::compose::compose_button; use crate::views::setup_relay::setup_nip17_relay; use crate::views::{ @@ -439,7 +439,10 @@ impl ChatSpace { } } Kind::Metadata => { - ingester.send(Signal::Metadata(event.into_owned())).await; + if let Ok(metadata) = Metadata::from_json(&event.content) { + let profile = Profile::new(event.pubkey, metadata); + ingester.send(Signal::Metadata(profile)).await; + } } Kind::GiftWrap => { Self::unwrap_gift_wrap(&event, pubkey_tx).await; @@ -558,9 +561,9 @@ impl ChatSpace { this.set_unwrapping_status(status, cx); }); } - Signal::Metadata(event) => { + Signal::Metadata(profile) => { registry.update(cx, |this, cx| { - this.insert_or_update_person(event, cx); + this.insert_or_update_person(profile, cx); }); } Signal::Message((gift_wrap_id, event)) => { @@ -1090,6 +1093,50 @@ impl ChatSpace { } } + fn on_reload_metadata( + &mut self, + _ev: &ReloadMetadata, + window: &mut Window, + cx: &mut Context, + ) { + let task: Task> = cx.background_spawn(async move { + let client = nostr_client(); + let css = css(); + + let filter = Filter::new().kind(Kind::PrivateDirectMessage); + + let pubkeys: Vec = client + .database() + .query(filter) + .await? + .into_iter() + .flat_map(|event| event.all_pubkeys()) + .unique() + .collect(); + + let filter = Filter::new() + .kind(Kind::Metadata) + .limit(pubkeys.len()) + .authors(pubkeys); + + client + .subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts) + .await?; + + Ok(()) + }); + + cx.spawn_in(window, async move |_, cx| { + if task.await.is_ok() { + cx.update(|window, cx| { + window.push_notification(t!("common.refreshed"), cx); + }) + .ok(); + } + }) + .detach(); + } + fn on_sign_out(&mut self, _e: &Logout, _window: &mut Window, cx: &mut Context) { cx.background_spawn(async move { let client = nostr_client(); @@ -1309,6 +1356,8 @@ impl ChatSpace { this.menu(t!("user.dark_mode"), Box::new(DarkMode)) .menu(t!("user.settings"), Box::new(Settings)) .separator() + .menu(t!("user.reload_metadata"), Box::new(ReloadMetadata)) + .separator() .menu(t!("user.sign_out"), Box::new(Logout)) }), ) @@ -1429,6 +1478,7 @@ impl Render for ChatSpace { .on_action(cx.listener(Self::on_dark_mode)) .on_action(cx.listener(Self::on_sign_out)) .on_action(cx.listener(Self::on_open_profile)) + .on_action(cx.listener(Self::on_reload_metadata)) .relative() .size_full() .child( diff --git a/crates/coop/src/views/edit_profile.rs b/crates/coop/src/views/edit_profile.rs index 1f9119a5..5c192063 100644 --- a/crates/coop/src/views/edit_profile.rs +++ b/crates/coop/src/views/edit_profile.rs @@ -164,7 +164,7 @@ impl EditProfile { .detach(); } - pub fn set_metadata(&mut self, cx: &mut Context) -> Task, Error>> { + pub fn set_metadata(&mut self, cx: &mut Context) -> Task, Error>> { let avatar = self.avatar_input.read(cx).value().to_string(); let name = self.name_input.read(cx).value().to_string(); let bio = self.bio_input.read(cx).value().to_string(); @@ -189,7 +189,14 @@ impl EditProfile { cx.background_spawn(async move { let client = nostr_client(); let output = client.set_metadata(&new_metadata).await?; - let event = client.database().event_by_id(&output.val).await?; + let event = client + .database() + .event_by_id(&output.val) + .await? + .map(|event| { + let metadata = Metadata::from_json(&event.content).unwrap_or_default(); + Profile::new(event.pubkey, metadata) + }); Ok(event) }) diff --git a/crates/coop/src/views/preferences.rs b/crates/coop/src/views/preferences.rs index 251fb839..da842d96 100644 --- a/crates/coop/src/views/preferences.rs +++ b/crates/coop/src/views/preferences.rs @@ -41,28 +41,28 @@ impl Preferences { fn open_edit_profile(&self, window: &mut Window, cx: &mut Context) { let view = edit_profile::init(window, cx); let weak_view = view.downgrade(); - let title = SharedString::new(t!("profile.title")); window.open_modal(cx, move |modal, _window, _cx| { let weak_view = weak_view.clone(); modal .confirm() - .title(title.clone()) + .title(shared_t!("profile.title")) .child(view.clone()) .button_props(ModalButtonProps::default().ok_text(t!("common.update"))) .on_ok(move |_, window, cx| { weak_view .update(cx, |this, cx| { let set_metadata = this.set_metadata(cx); + let registry = Registry::global(cx); cx.spawn_in(window, async move |_, cx| { match set_metadata.await { - Ok(event) => { - if let Some(event) = event { + Ok(profile) => { + if let Some(profile) = profile { cx.update(|_, cx| { - Registry::global(cx).update(cx, |this, cx| { - this.insert_or_update_person(event, cx); + registry.update(cx, |this, cx| { + this.insert_or_update_person(profile, cx); }); }) .ok(); diff --git a/crates/global/src/lib.rs b/crates/global/src/lib.rs index f75aeaa0..efaecec7 100644 --- a/crates/global/src/lib.rs +++ b/crates/global/src/lib.rs @@ -68,8 +68,8 @@ pub enum Signal { /// A signal to notify UI that the browser proxy service is down ProxyDown, - /// A signal to notify UI that a new metadata event has been received - Metadata(Event), + /// A signal to notify UI that a new profile has been received + Metadata(Profile), /// A signal to notify UI that a new gift wrap event has been received Message((EventId, Event)), diff --git a/crates/registry/src/lib.rs b/crates/registry/src/lib.rs index 1f9024a6..c46b287f 100644 --- a/crates/registry/src/lib.rs +++ b/crates/registry/src/lib.rs @@ -155,21 +155,19 @@ impl Registry { } /// Insert or update a person - pub fn insert_or_update_person(&mut self, event: Event, cx: &mut App) { - let public_key = event.pubkey; - let Ok(metadata) = Metadata::from_json(event.content) else { - // Invalid metadata, no need to process further. - return; - }; + pub fn insert_or_update_person(&mut self, profile: Profile, cx: &mut App) { + let public_key = profile.public_key(); - if let Some(person) = self.persons.get(&public_key) { - person.update(cx, |this, cx| { - *this = Profile::new(public_key, metadata); - cx.notify(); - }); - } else { - self.persons - .insert(public_key, cx.new(|_| Profile::new(public_key, metadata))); + match self.persons.get(&public_key) { + Some(person) => { + person.update(cx, |this, cx| { + *this = profile; + cx.notify(); + }); + } + None => { + self.persons.insert(public_key, cx.new(|_| profile)); + } } } diff --git a/locales/app.yml b/locales/app.yml index 112622c5..efb38f38 100644 --- a/locales/app.yml +++ b/locales/app.yml @@ -58,9 +58,11 @@ auto_update: user: dark_mode: - en: "Dark Mode" + en: "Dark mode" settings: en: "Settings" + reload_metadata: + en: "Reload metadata" sign_out: en: "Sign out"