refactor
This commit is contained in:
@@ -7,6 +7,7 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error, anyhow};
|
||||
use common::EventUtils;
|
||||
use device::{DeviceEvent, DeviceRegistry};
|
||||
use fuzzy_matcher::FuzzyMatcher;
|
||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
||||
use gpui::{
|
||||
@@ -104,7 +105,7 @@ pub struct ChatRegistry {
|
||||
tasks: SmallVec<[Task<Result<(), Error>>; 2]>,
|
||||
|
||||
/// Subscriptions
|
||||
_subscriptions: SmallVec<[Subscription; 1]>,
|
||||
_subscriptions: SmallVec<[Subscription; 2]>,
|
||||
}
|
||||
|
||||
impl EventEmitter<ChatEvent> for ChatRegistry {}
|
||||
@@ -123,17 +124,48 @@ impl ChatRegistry {
|
||||
/// Create a new chat registry instance
|
||||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let device = DeviceRegistry::global(cx);
|
||||
|
||||
let (tx, rx) = flume::unbounded::<Signal>();
|
||||
let mut subscriptions = smallvec![];
|
||||
|
||||
subscriptions.push(
|
||||
// Subscribe to the signer event
|
||||
cx.subscribe(&nostr, |this, _state, event, cx| {
|
||||
cx.subscribe_in(&nostr, window, |this, state, event, window, cx| {
|
||||
if event == &StateEvent::SignerSet {
|
||||
this.reset(cx);
|
||||
this.get_contact_list(cx);
|
||||
this.get_messages(cx);
|
||||
this.get_rooms(cx);
|
||||
|
||||
let signer = state.read(cx).signer();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let user_signer = signer.get().await;
|
||||
this.update(cx, |this, cx| {
|
||||
this.get_messages(user_signer, cx);
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
subscriptions.push(
|
||||
// Subscribe to the device event
|
||||
cx.subscribe_in(&device, window, |_this, _s, event, window, cx| {
|
||||
if event == &DeviceEvent::Set {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if let Some(device_signer) = signer.get_encryption_signer().await {
|
||||
this.update(cx, |this, cx| {
|
||||
this.get_messages(device_signer, cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
};
|
||||
}),
|
||||
);
|
||||
@@ -297,7 +329,7 @@ impl ChatRegistry {
|
||||
}
|
||||
|
||||
/// Get contact list from relays
|
||||
pub fn get_contact_list(&mut self, cx: &mut Context<Self>) {
|
||||
fn get_contact_list(&mut self, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
@@ -327,9 +359,12 @@ impl ChatRegistry {
|
||||
self.tasks.push(task);
|
||||
}
|
||||
|
||||
/// Get all messages for current user
|
||||
pub fn get_messages(&mut self, cx: &mut Context<Self>) {
|
||||
let task = self.subscribe_gift_wrap_events(cx);
|
||||
/// Get all messages for the provided signer
|
||||
fn get_messages<T>(&mut self, signer: T, cx: &mut Context<Self>)
|
||||
where
|
||||
T: NostrSigner + 'static,
|
||||
{
|
||||
let task = self.subscribe_gift_wrap_events(signer, cx);
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
match task.await {
|
||||
@@ -382,18 +417,20 @@ impl ChatRegistry {
|
||||
})
|
||||
}
|
||||
|
||||
/// Continuously get gift wrap events for the current user in their messaging relays
|
||||
fn subscribe_gift_wrap_events(&self, cx: &App) -> Task<Result<(), Error>> {
|
||||
/// Continuously get gift wrap events for the signer
|
||||
fn subscribe_gift_wrap_events<T>(&self, signer: T, cx: &App) -> Task<Result<(), Error>>
|
||||
where
|
||||
T: NostrSigner + 'static,
|
||||
{
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
let urls = self.get_messaging_relays(cx);
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let urls = urls.await?;
|
||||
let public_key = signer.get_public_key().await?;
|
||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||
let id = SubscriptionId::new(USER_GIFTWRAP);
|
||||
let id = SubscriptionId::new(format!("{}-msg", public_key.to_hex()));
|
||||
|
||||
// Ensure relay connections
|
||||
for url in urls.iter() {
|
||||
@@ -417,6 +454,31 @@ impl ChatRegistry {
|
||||
})
|
||||
}
|
||||
|
||||
/// Refresh the chat registry, fetching messages and contact list from relays.
|
||||
pub fn refresh(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.reset(cx);
|
||||
self.get_contact_list(cx);
|
||||
self.get_rooms(cx);
|
||||
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let user_signer = signer.get().await;
|
||||
let device_signer = signer.get_encryption_signer().await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.get_messages(user_signer, cx);
|
||||
|
||||
if let Some(device_signer) = device_signer {
|
||||
this.get_messages(device_signer, cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
/// Set the initializing status of the chat registry
|
||||
fn set_initializing(&mut self, initializing: bool, cx: &mut Context<Self>) {
|
||||
self.initializing = initializing;
|
||||
|
||||
@@ -92,14 +92,14 @@ fn main() {
|
||||
// Initialize relay auth registry
|
||||
relay_auth::init(window, cx);
|
||||
|
||||
// Initialize app registry
|
||||
chat::init(window, cx);
|
||||
|
||||
// Initialize device signer
|
||||
//
|
||||
// NIP-4e: https://github.com/nostr-protocol/nips/blob/per-device-keys/4e.md
|
||||
device::init(window, cx);
|
||||
|
||||
// Initialize app registry
|
||||
chat::init(window, cx);
|
||||
|
||||
// Initialize auto update
|
||||
auto_update::init(window, cx);
|
||||
|
||||
|
||||
@@ -354,8 +354,9 @@ impl Workspace {
|
||||
}
|
||||
Command::RefreshMessagingRelays => {
|
||||
let chat = ChatRegistry::global(cx);
|
||||
// Trigger a refresh of the chat registry
|
||||
chat.update(cx, |this, cx| {
|
||||
this.get_messages(cx);
|
||||
this.refresh(window, cx);
|
||||
});
|
||||
}
|
||||
Command::ShowRelayList => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::cell::Cell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
@@ -11,7 +11,7 @@ use gpui::{
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use state::{Announcement, DEVICE_GIFTWRAP, NostrRegistry, StateEvent, TIMEOUT, app_name};
|
||||
use state::{Announcement, NostrRegistry, StateEvent, TIMEOUT, app_name};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
@@ -213,76 +213,14 @@ impl DeviceRegistry {
|
||||
|
||||
// Update state
|
||||
this.update(cx, |this, cx| {
|
||||
this.set_initializing(false, cx);
|
||||
cx.emit(DeviceEvent::Set);
|
||||
this.get_messages(cx);
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
|
||||
/// Get all messages for encryption keys
|
||||
fn get_messages(&mut self, cx: &mut Context<Self>) {
|
||||
let task = self.subscribe_gift_wrap_events(cx);
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
if let Err(e) = task.await {
|
||||
this.update(cx, |_this, cx| {
|
||||
cx.emit(DeviceEvent::error(e.to_string()));
|
||||
})?;
|
||||
} else {
|
||||
this.update(cx, |this, cx| {
|
||||
this.set_initializing(false, cx);
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
|
||||
/// Continuously get gift wrap events for the current user in their messaging relays
|
||||
fn subscribe_gift_wrap_events(&self, cx: &App) -> Task<Result<(), Error>> {
|
||||
let persons = PersonRegistry::global(cx);
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
|
||||
let Some(user) = signer.public_key() else {
|
||||
return Task::ready(Err(anyhow!("User not found")));
|
||||
};
|
||||
|
||||
let profile = persons.read(cx).get(&user, cx);
|
||||
let relays = profile.messaging_relays().clone();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let encryption = signer.get_encryption_signer().await.context("not found")?;
|
||||
let public_key = encryption.get_public_key().await?;
|
||||
|
||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||
let id = SubscriptionId::new(DEVICE_GIFTWRAP);
|
||||
|
||||
// Ensure user has relays configured
|
||||
if relays.is_empty() {
|
||||
return Err(anyhow!("No messaging relays found"));
|
||||
}
|
||||
|
||||
// Ensure relays are connected
|
||||
for url in relays.iter() {
|
||||
client.add_relay(url).and_connect().await?;
|
||||
}
|
||||
|
||||
// Construct target for subscription
|
||||
let target: HashMap<RelayUrl, Filter> = relays
|
||||
.into_iter()
|
||||
.map(|relay| (relay, filter.clone()))
|
||||
.collect();
|
||||
|
||||
// Subscribe
|
||||
client.subscribe(target).with_id(id).await?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Backup the encryption's secret key to a file
|
||||
pub fn backup(&self, path: PathBuf, cx: &App) -> Task<Result<(), Error>> {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
|
||||
Reference in New Issue
Block a user