chore: improve handling of user profiles (#146)
* resubscribe metadata for all pubkeys * .
This commit is contained in:
@@ -2,7 +2,7 @@ use std::sync::Mutex;
|
|||||||
|
|
||||||
use gpui::{actions, App};
|
use gpui::{actions, App};
|
||||||
|
|
||||||
actions!(coop, [DarkMode, Settings, Logout, Quit]);
|
actions!(coop, [ReloadMetadata, DarkMode, Settings, Logout, Quit]);
|
||||||
actions!(sidebar, [Reload, RelayStatus]);
|
actions!(sidebar, [Reload, RelayStatus]);
|
||||||
|
|
||||||
pub fn load_embedded_fonts(cx: &App) {
|
pub fn load_embedded_fonts(cx: &App) {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ use ui::notification::Notification;
|
|||||||
use ui::popup_menu::PopupMenuExt;
|
use ui::popup_menu::PopupMenuExt;
|
||||||
use ui::{h_flex, v_flex, ContextModal, Disableable, IconName, Root, Sizable, StyledExt};
|
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::compose::compose_button;
|
||||||
use crate::views::setup_relay::setup_nip17_relay;
|
use crate::views::setup_relay::setup_nip17_relay;
|
||||||
use crate::views::{
|
use crate::views::{
|
||||||
@@ -439,7 +439,10 @@ impl ChatSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Metadata => {
|
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 => {
|
Kind::GiftWrap => {
|
||||||
Self::unwrap_gift_wrap(&event, pubkey_tx).await;
|
Self::unwrap_gift_wrap(&event, pubkey_tx).await;
|
||||||
@@ -558,9 +561,9 @@ impl ChatSpace {
|
|||||||
this.set_unwrapping_status(status, cx);
|
this.set_unwrapping_status(status, cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Signal::Metadata(event) => {
|
Signal::Metadata(profile) => {
|
||||||
registry.update(cx, |this, cx| {
|
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)) => {
|
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<Self>,
|
||||||
|
) {
|
||||||
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
|
let client = nostr_client();
|
||||||
|
let css = css();
|
||||||
|
|
||||||
|
let filter = Filter::new().kind(Kind::PrivateDirectMessage);
|
||||||
|
|
||||||
|
let pubkeys: Vec<PublicKey> = 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<Self>) {
|
fn on_sign_out(&mut self, _e: &Logout, _window: &mut Window, cx: &mut Context<Self>) {
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let client = nostr_client();
|
let client = nostr_client();
|
||||||
@@ -1309,6 +1356,8 @@ impl ChatSpace {
|
|||||||
this.menu(t!("user.dark_mode"), Box::new(DarkMode))
|
this.menu(t!("user.dark_mode"), Box::new(DarkMode))
|
||||||
.menu(t!("user.settings"), Box::new(Settings))
|
.menu(t!("user.settings"), Box::new(Settings))
|
||||||
.separator()
|
.separator()
|
||||||
|
.menu(t!("user.reload_metadata"), Box::new(ReloadMetadata))
|
||||||
|
.separator()
|
||||||
.menu(t!("user.sign_out"), Box::new(Logout))
|
.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_dark_mode))
|
||||||
.on_action(cx.listener(Self::on_sign_out))
|
.on_action(cx.listener(Self::on_sign_out))
|
||||||
.on_action(cx.listener(Self::on_open_profile))
|
.on_action(cx.listener(Self::on_open_profile))
|
||||||
|
.on_action(cx.listener(Self::on_reload_metadata))
|
||||||
.relative()
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.child(
|
.child(
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ impl EditProfile {
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_metadata(&mut self, cx: &mut Context<Self>) -> Task<Result<Option<Event>, Error>> {
|
pub fn set_metadata(&mut self, cx: &mut Context<Self>) -> Task<Result<Option<Profile>, Error>> {
|
||||||
let avatar = self.avatar_input.read(cx).value().to_string();
|
let avatar = self.avatar_input.read(cx).value().to_string();
|
||||||
let name = self.name_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();
|
let bio = self.bio_input.read(cx).value().to_string();
|
||||||
@@ -189,7 +189,14 @@ impl EditProfile {
|
|||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let client = nostr_client();
|
let client = nostr_client();
|
||||||
let output = client.set_metadata(&new_metadata).await?;
|
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)
|
Ok(event)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -41,28 +41,28 @@ impl Preferences {
|
|||||||
fn open_edit_profile(&self, window: &mut Window, cx: &mut Context<Self>) {
|
fn open_edit_profile(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
let view = edit_profile::init(window, cx);
|
let view = edit_profile::init(window, cx);
|
||||||
let weak_view = view.downgrade();
|
let weak_view = view.downgrade();
|
||||||
let title = SharedString::new(t!("profile.title"));
|
|
||||||
|
|
||||||
window.open_modal(cx, move |modal, _window, _cx| {
|
window.open_modal(cx, move |modal, _window, _cx| {
|
||||||
let weak_view = weak_view.clone();
|
let weak_view = weak_view.clone();
|
||||||
|
|
||||||
modal
|
modal
|
||||||
.confirm()
|
.confirm()
|
||||||
.title(title.clone())
|
.title(shared_t!("profile.title"))
|
||||||
.child(view.clone())
|
.child(view.clone())
|
||||||
.button_props(ModalButtonProps::default().ok_text(t!("common.update")))
|
.button_props(ModalButtonProps::default().ok_text(t!("common.update")))
|
||||||
.on_ok(move |_, window, cx| {
|
.on_ok(move |_, window, cx| {
|
||||||
weak_view
|
weak_view
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
let set_metadata = this.set_metadata(cx);
|
let set_metadata = this.set_metadata(cx);
|
||||||
|
let registry = Registry::global(cx);
|
||||||
|
|
||||||
cx.spawn_in(window, async move |_, cx| {
|
cx.spawn_in(window, async move |_, cx| {
|
||||||
match set_metadata.await {
|
match set_metadata.await {
|
||||||
Ok(event) => {
|
Ok(profile) => {
|
||||||
if let Some(event) = event {
|
if let Some(profile) = profile {
|
||||||
cx.update(|_, cx| {
|
cx.update(|_, cx| {
|
||||||
Registry::global(cx).update(cx, |this, cx| {
|
registry.update(cx, |this, cx| {
|
||||||
this.insert_or_update_person(event, cx);
|
this.insert_or_update_person(profile, cx);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ pub enum Signal {
|
|||||||
/// A signal to notify UI that the browser proxy service is down
|
/// A signal to notify UI that the browser proxy service is down
|
||||||
ProxyDown,
|
ProxyDown,
|
||||||
|
|
||||||
/// A signal to notify UI that a new metadata event has been received
|
/// A signal to notify UI that a new profile has been received
|
||||||
Metadata(Event),
|
Metadata(Profile),
|
||||||
|
|
||||||
/// A signal to notify UI that a new gift wrap event has been received
|
/// A signal to notify UI that a new gift wrap event has been received
|
||||||
Message((EventId, Event)),
|
Message((EventId, Event)),
|
||||||
|
|||||||
@@ -155,21 +155,19 @@ impl Registry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Insert or update a person
|
/// Insert or update a person
|
||||||
pub fn insert_or_update_person(&mut self, event: Event, cx: &mut App) {
|
pub fn insert_or_update_person(&mut self, profile: Profile, cx: &mut App) {
|
||||||
let public_key = event.pubkey;
|
let public_key = profile.public_key();
|
||||||
let Ok(metadata) = Metadata::from_json(event.content) else {
|
|
||||||
// Invalid metadata, no need to process further.
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(person) = self.persons.get(&public_key) {
|
match self.persons.get(&public_key) {
|
||||||
|
Some(person) => {
|
||||||
person.update(cx, |this, cx| {
|
person.update(cx, |this, cx| {
|
||||||
*this = Profile::new(public_key, metadata);
|
*this = profile;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
self.persons
|
None => {
|
||||||
.insert(public_key, cx.new(|_| Profile::new(public_key, metadata)));
|
self.persons.insert(public_key, cx.new(|_| profile));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,9 +58,11 @@ auto_update:
|
|||||||
|
|
||||||
user:
|
user:
|
||||||
dark_mode:
|
dark_mode:
|
||||||
en: "Dark Mode"
|
en: "Dark mode"
|
||||||
settings:
|
settings:
|
||||||
en: "Settings"
|
en: "Settings"
|
||||||
|
reload_metadata:
|
||||||
|
en: "Reload metadata"
|
||||||
sign_out:
|
sign_out:
|
||||||
en: "Sign out"
|
en: "Sign out"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user