From d9b16aea9a43ad5b01420079e17a63cd852ba5ec Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Wed, 1 Apr 2026 02:53:49 +0000 Subject: [PATCH] feat: add tracking for which signer encrypted the message (#27) Reviewed-on: https://git.reya.su/reya/coop/pulls/27 Co-authored-by: Ren Amamiya Co-committed-by: Ren Amamiya --- crates/chat/src/lib.rs | 31 +++++++++++++++++++++++++------ crates/chat_ui/src/lib.rs | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/chat/src/lib.rs b/crates/chat/src/lib.rs index cd89cd0..bdf59ec 100644 --- a/crates/chat/src/lib.rs +++ b/crates/chat/src/lib.rs @@ -75,6 +75,9 @@ impl Signal { } } +type Dekey = bool; +type GiftWrapId = EventId; + /// Chat Registry #[derive(Debug)] pub struct ChatRegistry { @@ -88,7 +91,7 @@ pub struct ChatRegistry { seens: Arc>>>, /// Mapping of unwrapped event ids to their gift wrap event ids - event_map: Arc>>, + event_map: Arc>>, /// Tracking the status of unwrapping gift wrap events. tracking_flag: Arc, @@ -191,7 +194,10 @@ impl ChatRegistry { }; match *message { - RelayMessage::Event { event, .. } => { + RelayMessage::Event { + event, + subscription_id, + } => { // Keep track of which relays have seen this event { let mut seens = seens.write().await; @@ -214,7 +220,8 @@ impl ChatRegistry { // Map the rumor id to the gift wrap event id for later lookup { let mut event_map = event_map.write().await; - event_map.insert(rumor.id.unwrap(), event.id); + let dekey = subscription_id.as_ref() == &sub_id1; + event_map.insert(rumor.id.unwrap(), (event.id, dekey)); } // Check if the rumor has a recipient @@ -222,8 +229,6 @@ impl ChatRegistry { let signal = Signal::error(event.as_ref(), "Recipient is missing"); tx.send_async(signal).await?; - - continue; } // Check if the rumor was created after the chat was initialized (for detecting new messages) @@ -231,6 +236,7 @@ impl ChatRegistry { let signal = Signal::message(event.id, rumor); tx.send_async(signal).await?; } else { + // Mark the chat still processing new messages status.store(true, Ordering::Release); } } @@ -473,7 +479,7 @@ impl ChatRegistry { self.event_map .read_blocking() .get(id) - .map(|id| self.seen_on(id)) + .map(|(id, _dekey)| self.seen_on(id)) } /// Get the relays that have seen a given gift wrap id. @@ -485,6 +491,15 @@ impl ChatRegistry { .unwrap_or_default() } + /// Check if a given rumor was encrypted by the dekey. + pub fn encrypted_by_dekey(&self, id: &EventId) -> bool { + self.event_map + .read_blocking() + .get(id) + .map(|(_, dekey)| *dekey) + .unwrap_or(false) + } + /// Add a new room to the start of list. pub fn add_room(&mut self, room: I, cx: &mut Context) where @@ -563,6 +578,10 @@ impl ChatRegistry { /// Reset the registry. pub fn reset(&mut self, cx: &mut Context) { self.rooms.clear(); + self.trashes.update(cx, |this, cx| { + this.clear(); + cx.notify(); + }); cx.notify(); } diff --git a/crates/chat_ui/src/lib.rs b/crates/chat_ui/src/lib.rs index e81de04..15c374d 100644 --- a/crates/chat_ui/src/lib.rs +++ b/crates/chat_ui/src/lib.rs @@ -471,6 +471,12 @@ impl ChatPanel { self.reports_by_id.read(cx).get(id).is_some() } + /// Check if a message was encrypted by the dekey + fn encrypted_by_dekey(&self, id: &EventId, cx: &App) -> bool { + let chat = ChatRegistry::global(cx); + chat.read(cx).encrypted_by_dekey(id) + } + /// Get all sent reports for a message by its ID fn sent_reports(&self, id: &EventId, cx: &App) -> Option> { self.reports_by_id.read(cx).get(id).cloned() @@ -843,6 +849,7 @@ impl ChatPanel { let replies = message.replies_to.as_slice(); let has_replies = !replies.is_empty(); let has_reports = self.has_reports(&id, cx); + let encrypted_by_dekey = self.encrypted_by_dekey(&id, cx); // Hide avatar setting let hide_avatar = AppSettings::get_hide_avatar(cx); @@ -888,6 +895,17 @@ impl ChatPanel { .text_color(cx.theme().text) .child(author.name()), ) + .when(encrypted_by_dekey, |this| { + this.child( + Button::new(format!("dekey-{ix}")) + .icon(IconName::Shield) + .ghost() + .xsmall() + .px_4() + .tooltip("Encrypted by Dekey") + .disabled(true), + ) + }) .child(message.created_at.to_human_time()) .when(has_reports, |this| { this.child(deferred(self.render_sent_reports(&id, cx)))