chore: follow up on nip-4e (#195)
* update deps * . * remove resend button * clean up * . * . * . * . * .
This commit is contained in:
@@ -245,7 +245,7 @@ impl Registry {
|
||||
pub fn search_by_public_key(&self, public_key: PublicKey, cx: &App) -> Vec<Entity<Room>> {
|
||||
self.rooms
|
||||
.iter()
|
||||
.filter(|room| room.read(cx).members.contains_key(&public_key))
|
||||
.filter(|room| room.read(cx).members.contains(&public_key))
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -8,20 +8,10 @@ use common::display::RenderedProfile;
|
||||
use common::event::EventUtils;
|
||||
use gpui::{App, AppContext, Context, EventEmitter, SharedString, SharedUri, Task};
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use states::app_state;
|
||||
use states::constants::SEND_RETRY;
|
||||
use states::{app_state, SignerKind, SEND_RETRY};
|
||||
|
||||
use crate::Registry;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Deserialize, Serialize)]
|
||||
pub enum SignerKind {
|
||||
Encryption,
|
||||
User,
|
||||
#[default]
|
||||
Auto,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct SendOptions {
|
||||
pub backup: bool,
|
||||
@@ -127,8 +117,6 @@ pub enum RoomKind {
|
||||
Request,
|
||||
}
|
||||
|
||||
type DevicePublicKey = PublicKey;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Room {
|
||||
pub id: u64,
|
||||
@@ -136,7 +124,7 @@ pub struct Room {
|
||||
/// Subject of the room
|
||||
pub subject: Option<String>,
|
||||
/// All members of the room
|
||||
pub members: HashMap<PublicKey, Option<DevicePublicKey>>,
|
||||
pub members: Vec<PublicKey>,
|
||||
/// Kind
|
||||
pub kind: RoomKind,
|
||||
}
|
||||
@@ -175,11 +163,7 @@ impl From<&Event> for Room {
|
||||
let created_at = val.created_at;
|
||||
|
||||
// Get the members from the event's tags and event's pubkey
|
||||
let members: HashMap<PublicKey, Option<DevicePublicKey>> = val
|
||||
.all_pubkeys()
|
||||
.into_iter()
|
||||
.map(|public_key| (public_key, None))
|
||||
.collect();
|
||||
let members = val.all_pubkeys();
|
||||
|
||||
// Get subject from tags
|
||||
let subject = val
|
||||
@@ -203,11 +187,7 @@ impl From<&UnsignedEvent> for Room {
|
||||
let created_at = val.created_at;
|
||||
|
||||
// Get the members from the event's tags and event's pubkey
|
||||
let members: HashMap<PublicKey, Option<DevicePublicKey>> = val
|
||||
.all_pubkeys()
|
||||
.into_iter()
|
||||
.map(|public_key| (public_key, None))
|
||||
.collect();
|
||||
let members = val.all_pubkeys();
|
||||
|
||||
// Get subject from tags
|
||||
let subject = val
|
||||
@@ -289,7 +269,7 @@ impl Room {
|
||||
|
||||
/// Returns the members of the room
|
||||
pub fn members(&self) -> Vec<PublicKey> {
|
||||
self.members.keys().cloned().collect()
|
||||
self.members.clone()
|
||||
}
|
||||
|
||||
/// Checks if the room has more than two members (group)
|
||||
@@ -324,9 +304,9 @@ impl Room {
|
||||
|
||||
let target_member = self
|
||||
.members
|
||||
.keys()
|
||||
.iter()
|
||||
.find(|&member| Some(member) != signer_pubkey.as_ref())
|
||||
.or_else(|| self.members.keys().next())
|
||||
.or_else(|| self.members.first())
|
||||
.expect("Room should have at least one member");
|
||||
|
||||
registry.read(cx).get_person(target_member, cx)
|
||||
@@ -339,7 +319,7 @@ impl Room {
|
||||
if self.is_group() {
|
||||
let profiles: Vec<Profile> = self
|
||||
.members
|
||||
.keys()
|
||||
.iter()
|
||||
.map(|public_key| registry.get_person(public_key, cx))
|
||||
.collect();
|
||||
|
||||
@@ -447,7 +427,7 @@ impl Room {
|
||||
// Add receivers
|
||||
//
|
||||
// NOTE: current user will be removed from the list of receivers
|
||||
for (member, _) in self.members.iter() {
|
||||
for member in self.members.iter() {
|
||||
// Get relay hint if available
|
||||
let relay_url = relay_cache
|
||||
.get(member)
|
||||
@@ -505,54 +485,75 @@ impl Room {
|
||||
opts: &SendOptions,
|
||||
cx: &App,
|
||||
) -> Task<Result<Vec<SendReport>, Error>> {
|
||||
let mut members = self.members.clone();
|
||||
let rumor = rumor.to_owned();
|
||||
let opts = opts.to_owned();
|
||||
|
||||
// Get all members
|
||||
let mut members = self.members();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let state = app_state();
|
||||
|
||||
let client = state.client();
|
||||
let signer_kind = opts.signer_kind;
|
||||
|
||||
let relay_cache = state.relay_cache.read().await;
|
||||
let device = state.device.read().await.encryption.clone();
|
||||
let announcement_cache = state.announcement_cache.read().await;
|
||||
|
||||
let encryption = state.device.read().await.encryption.clone();
|
||||
// Get the encryption public key
|
||||
let encryption_pubkey = if let Some(signer) = encryption.as_ref() {
|
||||
signer.get_public_key().await.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let user_signer = client.signer().await?;
|
||||
let user_pubkey = user_signer.get_public_key().await?;
|
||||
|
||||
// Remove the current user's public key from the list of receivers
|
||||
// Current user will be handled separately
|
||||
let (public_key, device_pubkey) = members.remove_entry(&user_pubkey).unwrap();
|
||||
// the current user will be handled separately
|
||||
members.retain(|&pk| pk != user_pubkey);
|
||||
|
||||
// Determine the signer will be used based on the provided options
|
||||
let (signer, signer_kind) =
|
||||
Self::select_signer(&opts.signer_kind, device, user_signer)?;
|
||||
let signer = Self::select_signer(&opts.signer_kind, user_signer, encryption)?;
|
||||
|
||||
// Collect the send reports
|
||||
let mut reports: Vec<SendReport> = vec![];
|
||||
|
||||
for (user, device_pubkey) in members.into_iter() {
|
||||
let urls = relay_cache.get(&user).cloned().unwrap_or_default();
|
||||
for member in members.into_iter() {
|
||||
// Get user's messaging relays
|
||||
let urls = relay_cache.get(&member).cloned().unwrap_or_default();
|
||||
|
||||
// Check if there are any relays to send the message to
|
||||
if urls.is_empty() {
|
||||
reports.push(SendReport::new(user).relays_not_found());
|
||||
reports.push(SendReport::new(member).relays_not_found());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip sending if using encryption keys but device not found
|
||||
if device_pubkey.is_none() && matches!(opts.signer_kind, SignerKind::Encryption) {
|
||||
reports.push(SendReport::new(user).device_not_found());
|
||||
// Ensure connection to the relays
|
||||
for url in urls.iter() {
|
||||
client.add_relay(url).await.ok();
|
||||
client.connect_relay(url).await.ok();
|
||||
}
|
||||
|
||||
// Get user's encryption public key if available
|
||||
let encryption = announcement_cache
|
||||
.get(&member)
|
||||
.and_then(|a| a.to_owned().map(|a| a.public_key()));
|
||||
|
||||
// Skip sending if using encryption signer but receiver's encryption keys not found
|
||||
if encryption.is_none() && matches!(signer_kind, SignerKind::Encryption) {
|
||||
reports.push(SendReport::new(member).device_not_found());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine the receiver based on the signer kind
|
||||
let receiver = Self::select_receiver(&opts.signer_kind, user, device_pubkey)?;
|
||||
let receiver = Self::select_receiver(&signer_kind, member, encryption)?;
|
||||
let rumor = rumor.clone();
|
||||
|
||||
// Construct the gift wrap event
|
||||
let rumor = rumor.clone();
|
||||
let event = EventBuilder::gift_wrap(&signer, &receiver, rumor, []).await?;
|
||||
|
||||
// Send the event to the messaging relays
|
||||
// Send the gift wrap event to the messaging relays
|
||||
match client.send_event_to(urls, &event).await {
|
||||
Ok(output) => {
|
||||
let id = output.id().to_owned();
|
||||
@@ -590,33 +591,32 @@ impl Room {
|
||||
}
|
||||
}
|
||||
|
||||
// Select a signer based on previous usage, not from the options
|
||||
let receiver = Self::select_receiver(&signer_kind, public_key, device_pubkey)?;
|
||||
|
||||
// Construct a gift wrap to back up to current user's owned messaging relays
|
||||
let receiver = Self::select_receiver(&signer_kind, user_pubkey, encryption_pubkey)?;
|
||||
let rumor = rumor.clone();
|
||||
|
||||
// Construct the gift-wrapped event
|
||||
let event = EventBuilder::gift_wrap(&signer, &receiver, rumor, []).await?;
|
||||
|
||||
// Only send a backup message to current user if sent successfully to others
|
||||
if opts.backup() && reports.iter().all(|r| r.is_sent_success()) {
|
||||
let urls = relay_cache.get(&public_key).cloned().unwrap_or_default();
|
||||
let urls = relay_cache.get(&user_pubkey).cloned().unwrap_or_default();
|
||||
|
||||
// Check if there are any relays to send the event to
|
||||
if urls.is_empty() {
|
||||
reports.push(SendReport::new(public_key).relays_not_found());
|
||||
reports.push(SendReport::new(user_pubkey).relays_not_found());
|
||||
} else {
|
||||
// Send the event to the messaging relays
|
||||
match client.send_event_to(urls, &event).await {
|
||||
Ok(output) => {
|
||||
reports.push(SendReport::new(public_key).status(output));
|
||||
reports.push(SendReport::new(user_pubkey).status(output));
|
||||
}
|
||||
Err(e) => {
|
||||
reports.push(SendReport::new(public_key).error(e.to_string()));
|
||||
reports.push(SendReport::new(user_pubkey).error(e.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reports.push(SendReport::new(public_key).on_hold(event));
|
||||
reports.push(SendReport::new(user_pubkey).on_hold(event));
|
||||
}
|
||||
|
||||
Ok(reports)
|
||||
@@ -683,37 +683,30 @@ impl Room {
|
||||
})
|
||||
}
|
||||
|
||||
fn select_signer<T>(
|
||||
kind: &SignerKind,
|
||||
device: Option<T>,
|
||||
user: T,
|
||||
) -> Result<(T, SignerKind), Error>
|
||||
fn select_signer<T>(kind: &SignerKind, user: T, encryption: Option<T>) -> Result<T, Error>
|
||||
where
|
||||
T: NostrSigner,
|
||||
{
|
||||
match kind {
|
||||
SignerKind::Auto => device
|
||||
.map(|d| (d, SignerKind::Encryption))
|
||||
.or(Some((user, SignerKind::User)))
|
||||
.ok_or_else(|| anyhow!("No signer available")),
|
||||
SignerKind::Encryption => device
|
||||
.map(|d| (d, SignerKind::Encryption))
|
||||
.ok_or_else(|| anyhow!("No encryption key found")),
|
||||
SignerKind::User => Ok((user, SignerKind::User)),
|
||||
SignerKind::Encryption => {
|
||||
Ok(encryption.ok_or_else(|| anyhow!("No encryption key found"))?)
|
||||
}
|
||||
SignerKind::User => Ok(user),
|
||||
SignerKind::Auto => Ok(encryption.unwrap_or(user)),
|
||||
}
|
||||
}
|
||||
|
||||
fn select_receiver(
|
||||
kind: &SignerKind,
|
||||
user: PublicKey,
|
||||
device: Option<PublicKey>,
|
||||
encryption: Option<PublicKey>,
|
||||
) -> Result<PublicKey, Error> {
|
||||
match kind {
|
||||
SignerKind::Encryption => {
|
||||
Ok(device.ok_or_else(|| anyhow!("Receiver's encryption key not found"))?)
|
||||
Ok(encryption.ok_or_else(|| anyhow!("Receiver's encryption key not found"))?)
|
||||
}
|
||||
SignerKind::User => Ok(user),
|
||||
SignerKind::Auto => Ok(device.unwrap_or(user)),
|
||||
SignerKind::Auto => Ok(encryption.unwrap_or(user)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user