wip
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m25s

This commit is contained in:
2026-02-15 16:52:35 +07:00
parent a1aaa30a48
commit 452253bece
13 changed files with 610 additions and 569 deletions

View File

@@ -97,12 +97,10 @@ impl ChatRegistry {
/// Create a new chat registry instance
fn new(cx: &mut Context<Self>) -> Self {
let device = DeviceRegistry::global(cx);
let nostr = NostrRegistry::global(cx);
let nip17_state = nostr.read(cx).nip17_state();
let device = DeviceRegistry::global(cx);
let device_signer = device.read(cx).device_signer.clone();
// A flag to indicate if the registry is loading
let tracking_flag = Arc::new(AtomicBool::new(false));
@@ -128,8 +126,8 @@ impl ChatRegistry {
subscriptions.push(
// Observe the device signer state
cx.observe(&device_signer, |this, state, cx| {
if state.read(cx).is_some() {
cx.observe(&device, |this, state, cx| {
if state.read(cx).state().set() {
this.handle_notifications(cx);
}
}),
@@ -180,9 +178,7 @@ impl ChatRegistry {
fn handle_notifications(&mut self, cx: &mut Context<Self>) {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let device = DeviceRegistry::global(cx);
let device_signer = device.read(cx).signer(cx);
let signer = nostr.read(cx).signer();
let status = self.tracking_flag.clone();
let tx = self.sender.clone();
@@ -191,6 +187,7 @@ impl ChatRegistry {
let initialized_at = Timestamp::now();
let sub_id1 = SubscriptionId::new(DEVICE_GIFTWRAP);
let sub_id2 = SubscriptionId::new(USER_GIFTWRAP);
let device_signer = signer.get_encryption_signer().await;
let mut notifications = client.notifications();
let mut processed_events = HashSet::new();

View File

@@ -6,8 +6,8 @@ use nostr_sdk::prelude::*;
/// New message.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct NewMessage {
pub gift_wrap: EventId,
pub room: u64,
pub gift_wrap: EventId,
pub rumor: UnsignedEvent,
}
@@ -16,8 +16,8 @@ impl NewMessage {
let room = rumor.uniq_id();
Self {
gift_wrap,
room,
gift_wrap,
rumor,
}
}

View File

@@ -1,5 +1,4 @@
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::time::Duration;
@@ -9,72 +8,47 @@ use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
use itertools::Itertools;
use nostr_sdk::prelude::*;
use person::{Person, PersonRegistry};
use state::{tracker, NostrRegistry};
use settings::{RoomConfig, SignerKind};
use state::{NostrRegistry, TIMEOUT};
use crate::{ChatRegistry, NewMessage};
const SEND_RETRY: usize = 10;
#[derive(Debug, Clone)]
pub struct SendReport {
pub receiver: PublicKey,
pub status: Option<Output<EventId>>,
pub error: Option<SharedString>,
pub on_hold: Option<Event>,
pub encryption: bool,
pub relays_not_found: bool,
pub device_not_found: bool,
pub output: Option<Output<EventId>>,
}
impl SendReport {
pub fn new(receiver: PublicKey) -> Self {
Self {
receiver,
status: None,
error: None,
on_hold: None,
encryption: false,
relays_not_found: false,
device_not_found: false,
output: None,
}
}
pub fn status(mut self, output: Output<EventId>) -> Self {
self.status = Some(output);
pub fn output(mut self, output: Output<EventId>) -> Self {
self.output = Some(output);
self
}
pub fn error(mut self, error: impl Into<SharedString>) -> Self {
pub fn error<T>(mut self, error: T) -> Self
where
T: Into<SharedString>,
{
self.error = Some(error.into());
self
}
pub fn on_hold(mut self, event: Event) -> Self {
self.on_hold = Some(event);
self
}
pub fn encryption(mut self) -> Self {
self.encryption = true;
self
}
pub fn relays_not_found(mut self) -> Self {
self.relays_not_found = true;
self
}
pub fn device_not_found(mut self) -> Self {
self.device_not_found = true;
self
}
pub fn is_relay_error(&self) -> bool {
self.error.is_some() || self.relays_not_found
self.error.is_some()
}
pub fn is_sent_success(&self) -> bool {
if let Some(output) = self.status.as_ref() {
if let Some(output) = self.output.as_ref() {
!output.success.is_empty()
} else {
false
@@ -115,6 +89,9 @@ pub struct Room {
/// Kind
pub kind: RoomKind,
/// Configuration
config: RoomConfig,
}
impl Ord for Room {
@@ -161,6 +138,7 @@ impl From<&UnsignedEvent> for Room {
subject,
members,
kind: RoomKind::default(),
config: RoomConfig::default(),
}
}
}
@@ -320,21 +298,17 @@ impl Room {
}
/// Get gossip relays for each member
pub fn connect(&self, cx: &App) -> Task<Result<(), Error>> {
pub fn early_connect(&self, cx: &App) -> Task<Result<(), Error>> {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let members = self.members();
let id = SubscriptionId::new(format!("room-{}", self.id));
let subscription_id = SubscriptionId::new(format!("room-{}", self.id));
cx.background_spawn(async move {
let signer = client.signer().context("Signer not found")?;
let public_key = signer.get_public_key().await?;
// Subscription options
let opts = SubscribeAutoCloseOptions::default()
.timeout(Some(Duration::from_secs(2)))
.exit_policy(ReqExitPolicy::ExitOnEOSE);
for member in members.into_iter() {
if member == public_key {
continue;
@@ -346,8 +320,12 @@ impl Room {
// Subscribe to get member's gossip relays
client
.subscribe(filter)
.close_on(opts)
.with_id(id.clone())
.with_id(subscription_id.clone())
.close_on(
SubscribeAutoCloseOptions::default()
.timeout(Some(Duration::from_secs(TIMEOUT)))
.exit_policy(ReqExitPolicy::ExitOnEOSE),
)
.await?;
}
@@ -379,7 +357,138 @@ impl Room {
})
}
/// Create a new unsigned message event
/// Construct extra tags for a message
fn extra_tags(&self, sender: PublicKey, members: &[Person], replies: &[EventId]) -> Vec<Tag> {
let mut extra_tags = vec![];
// Add subject tag if present
if let Some(value) = self.subject.as_ref() {
extra_tags.push(Tag::from_standardized_without_cell(TagStandard::Subject(
value.to_string(),
)));
}
// Add all reply tags
for id in replies {
extra_tags.push(Tag::event(*id))
}
// Add all receiver tags
for member in members.iter() {
// Skip current user
if member.public_key() == sender {
continue;
}
extra_tags.push(Tag::from_standardized_without_cell(
TagStandard::PublicKey {
public_key: member.public_key(),
relay_url: member.messaging_relay_hint(),
alias: None,
uppercase: false,
},
));
}
extra_tags
}
pub fn send<S, I>(&self, content: S, replies: I, cx: &App) -> Option<Task<Vec<SendReport>>>
where
S: Into<String>,
I: IntoIterator<Item = EventId>,
{
let persons = PersonRegistry::global(cx);
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
let content: String = content.into();
let replies: Vec<EventId> = replies.into_iter().collect();
// Get current user's public key
let sender = nostr.read(cx).signer().public_key()?;
// get room's config
let config = self.config.clone();
// Get all members
let members: Vec<Person> = self
.members
.iter()
.filter(|public_key| public_key != &&sender)
.map(|member| persons.read(cx).get(member, cx))
.collect();
// Get extra tags
let extra_tags = self.extra_tags(sender, &members, &replies);
Some(cx.background_spawn(async move {
let signer_kind = config.signer_kind();
let backup = config.backup();
// Get all available signers
let user_signer = signer.get().await;
let encryption_signer = signer.get_encryption_signer().await;
let mut reports: Vec<SendReport> = vec![];
for member in members.into_iter() {
// Skip if member has no messaging relays
if member.messaging_relays().is_empty() {
let report = SendReport::new(member.public_key()).error("No messaging relays");
reports.push(report);
continue;
}
// When the room is forced to use an encryption signer,
// skip if the receiver has not set up an encryption signer.
if signer_kind.encryption() && member.announcement().is_none() {
let report = SendReport::new(member.public_key()).error("Encryption not found");
reports.push(report);
continue;
}
let (receiver, signer) = match signer_kind {
SignerKind::Auto => {
if let Some(announcement) = member.announcement() {
if let Some(enc_signer) = encryption_signer.as_ref() {
(announcement.public_key(), enc_signer.clone())
} else {
(member.public_key(), user_signer.clone())
}
} else {
(member.public_key(), user_signer.clone())
}
}
SignerKind::Encryption => {
let Some(encryption_signer) = encryption_signer.as_ref() else {
let report =
SendReport::new(member.public_key()).error("Encryption not found");
reports.push(report);
continue;
};
let Some(announcement) = member.announcement() else {
let report = SendReport::new(member.public_key())
.error("Announcement not found");
reports.push(report);
continue;
};
(announcement.public_key(), encryption_signer.clone())
}
SignerKind::User => (member.public_key(), user_signer.clone()),
};
}
reports
}))
}
/*
* /// Create a new unsigned message event
pub fn create_message(
&self,
content: &str,
@@ -444,7 +553,7 @@ impl Room {
// WARNING: never sign and send this event to relays
let mut event = EventBuilder::new(Kind::PrivateDirectMessage, content)
.tags(tags)
.build(Keys::generate().public_key());
.build(public_key);
// Ensure the event ID has been generated
event.ensure_id();
@@ -594,4 +703,5 @@ impl Room {
Ok(resend_reports)
})
}
*/
}