This commit is contained in:
2026-05-18 08:07:59 +07:00
parent d2a17e54c4
commit eb5d64a3af
15 changed files with 524 additions and 333 deletions

View File

@@ -134,41 +134,21 @@ impl ChatRegistry {
subscriptions.push(
// Subscribe to the signer event
cx.subscribe_in(&nostr, window, |this, state, event, window, cx| {
if event == &StateEvent::SignerSet {
cx.subscribe(&nostr, |this, _state, event, cx| {
if let StateEvent::SignerSet(public_key) = event {
this.reset(cx);
this.get_contact_list(cx);
this.get_contact_list(public_key, 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();
this.get_messages(public_key, cx);
};
}),
);
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();
cx.subscribe(&device, |this, _device, event, cx| {
if let DeviceEvent::Set(public_key) = event {
this.get_messages(public_key, cx);
};
}),
);
@@ -342,17 +322,17 @@ impl ChatRegistry {
}
/// Get contact list from relays
fn get_contact_list(&mut self, cx: &mut Context<Self>) {
fn get_contact_list(&mut self, public_key: &PublicKey, cx: &mut Context<Self>) {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
let Some(public_key) = signer.public_key() else {
return;
};
let public_key = public_key.to_owned();
let write_relays = nostr.read(cx).write_relays(&public_key, cx);
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let urls = write_relays.await;
let id = SubscriptionId::new("contact-list");
let opts = SubscribeAutoCloseOptions::default()
.exit_policy(ReqExitPolicy::ExitOnEOSE)
.timeout(Some(Duration::from_secs(TIMEOUT)));
@@ -363,8 +343,13 @@ impl ChatRegistry {
.author(public_key)
.limit(1);
let target = urls
.into_iter()
.map(|relay| (relay, vec![filter.clone()]))
.collect::<Vec<_>>();
// Subscribe
client.subscribe(filter).close_on(opts).with_id(id).await?;
client.subscribe(target).close_on(opts).with_id(id).await?;
Ok(())
});
@@ -373,11 +358,11 @@ impl ChatRegistry {
}
/// Get all messages for the provided signer
fn get_messages(&mut self, signer: Arc<dyn AsyncNostrSigner>, cx: &mut Context<Self>) {
let task = self.subscribe_gift_wrap_events(signer, cx);
fn get_messages(&mut self, public_key: &PublicKey, cx: &mut Context<Self>) {
let future = self.subscribe_msg(public_key, cx);
self.tasks.push(cx.spawn(async move |this, cx| {
match task.await {
match future.await {
Ok(_) => {
this.update(cx, |this, cx| {
this.set_initializing(false, cx);
@@ -399,9 +384,12 @@ impl ChatRegistry {
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
let public_key = signer.public_key();
let write_relays = nostr.read(cx).write_relays(&public_key, cx);
cx.background_spawn(async move {
let public_key = signer.get_public_key().await?;
let id = SubscriptionId::new("inbox-relay");
let urls = write_relays.await;
// Construct filter for inbox relays
let filter = Filter::new()
@@ -409,9 +397,14 @@ impl ChatRegistry {
.author(public_key)
.limit(1);
let target = urls
.into_iter()
.map(|relay| (relay, vec![filter.clone()]))
.collect::<Vec<_>>();
// Stream events from user's write relays
let mut stream = client
.stream_events(filter)
.stream_events(target)
.with_id(id)
.timeout(Duration::from_secs(TIMEOUT))
.await?;
@@ -428,18 +421,14 @@ impl ChatRegistry {
}
/// Continuously get gift wrap events for the signer
fn subscribe_gift_wrap_events(
&self,
signer: Arc<dyn AsyncNostrSigner>,
cx: &App,
) -> Task<Result<(), Error>> {
fn subscribe_msg(&self, public_key: &PublicKey, cx: &App) -> Task<Result<(), Error>> {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let urls = self.get_messaging_relays(cx);
let public_key = public_key.to_owned();
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(format!("{}-msg", public_key.to_hex()));
@@ -468,26 +457,30 @@ 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| {
self.tasks.push(cx.spawn_in(window, async move |this, cx| {
let user_signer = signer.get().await;
let device_signer = signer.get_encryption_signer().await;
let user_pubkey = user_signer.get_public_key().await?;
this.update(cx, |this, cx| {
this.get_messages(user_signer, cx);
this.get_messages(&user_pubkey, cx);
})?;
if let Some(device_signer) = device_signer {
this.get_messages(device_signer, cx);
}
})
.ok();
})
.detach();
let device_signer = signer.get_encryption_signer().await;
if let Some(device_signer) = device_signer {
let device_pubkey = device_signer.get_public_key().await?;
this.update(cx, |this, cx| {
this.get_messages(&device_pubkey, cx);
})?;
}
Ok(())
}));
}
/// Set the initializing status of the chat registry
@@ -791,14 +784,12 @@ impl ChatRegistry {
pub fn new_message(&mut self, message: NewMessage, cx: &mut Context<Self>) {
let nostr = NostrRegistry::global(cx);
let signer = nostr.read(cx).signer();
let public_key = signer.public_key();
match self.rooms.iter().find(|e| e.read(cx).id == message.room) {
Some(room) => {
room.update(cx, |this, cx| {
if this.kind == RoomKind::Request
&& let Some(public_key) = signer.public_key()
&& message.rumor.pubkey == public_key
{
if this.kind == RoomKind::Request && message.rumor.pubkey == public_key {
this.set_ongoing(cx);
}
this.push_message(message, cx);

View File

@@ -10,7 +10,8 @@ use itertools::Itertools;
use nostr_sdk::prelude::*;
use person::{Person, PersonRegistry};
use settings::{RoomConfig, SignerKind};
use state::{CoopSigner, NostrRegistry, TIMEOUT};
use smol::lock::RwLock;
use state::{CoopSigner, Gossip, NostrRegistry, TIMEOUT};
use crate::NewMessage;
@@ -427,7 +428,7 @@ impl Room {
let nostr = NostrRegistry::global(cx);
// Get current user's public key
let sender = nostr.read(cx).signer().public_key()?;
let sender = nostr.read(cx).signer().public_key();
// Get all members, excluding the sender
let members: Vec<Person> = self
@@ -477,10 +478,11 @@ impl Room {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let gossip = nostr.read(cx).gossip();
let signer = nostr.read(cx).signer();
// Get current user's public key
let public_key = nostr.read(cx).signer().public_key()?;
let public_key = nostr.read(cx).signer().public_key();
let sender = persons.read(cx).get(&public_key, cx);
let config = self.config.clone();
@@ -529,7 +531,7 @@ impl Room {
};
// Send the gift wrap event and collect the report
match send_gift_wrap(&client, &signer, &member, &rumor, use_encryption).await {
match send(&client, &gossip, &signer, &member, &rumor, use_encryption).await {
Ok(report) => {
reports.push(report);
sents += 1;
@@ -552,7 +554,7 @@ impl Room {
SignerKind::User => false,
};
match send_gift_wrap(&client, &signer, &sender, &rumor, use_encryption).await {
match send(&client, &gossip, &signer, &sender, &rumor, use_encryption).await {
Ok(report) => reports.push(report),
Err(error) => {
let report = SendReport::new(public_key).error(error.to_string());
@@ -567,8 +569,9 @@ impl Room {
}
// Helper function to send a gift-wrapped event
async fn send_gift_wrap(
async fn send(
client: &Client,
gossip: &Arc<RwLock<Gossip>>,
signer: &Arc<CoopSigner>,
receiver: &Person,
rumor: &UnsignedEvent,
@@ -602,10 +605,15 @@ async fn send_gift_wrap(
}
};
let relays = gossip.read().await.messaging_relays(&receiver);
for url in relays.iter() {
client.add_relay(url).and_connect().await?;
}
// Send the gift wrap event and collect the report
let report = client
.send_event(&event)
.to_nip17()
.to(relays)
.ack_policy(AckPolicy::none())
.await
.map(|output| {