diff --git a/src/room/buffer.rs b/src/room/buffer.rs index 5dc4014..2414d0a 100644 --- a/src/room/buffer.rs +++ b/src/room/buffer.rs @@ -109,7 +109,7 @@ impl RoomBuffer { // Our prefixes always come with a \t character, but when we // replace stuff we're able to replace the prefix and the // message separately, so trim the whitespace in the prefix. - prefix: Some(event.prefix.trim_end()), + prefix: Some(&event.prefix.trim_end_matches("\t")), message: Some(&new.message), ..Default::default() }; @@ -121,13 +121,48 @@ impl RoomBuffer { Ordering::Greater => { for line in &lines[event.content.lines.len()..] { line.set_message(""); + line.set_prefix(""); } } Ordering::Less => { + let event_id_tags: Vec = lines + .get(0) + .map(|l| { + l.tags() + .iter() + .filter_map(|t| { + if t.starts_with("matrix_id") { + Some(t.to_string()) + } else { + None + } + }) + .collect() + }) + .unwrap_or_default(); + + let event_id_tag = if let Some(event_id_tag) = + event_id_tags.first() + { + event_id_tag + } else { + Weechat::print("Error replacing event, the original event doesn't have an event id tag"); + return; + }; + for line in &event.content.lines[lines.len()..] { let message = format!("{}{}", &event.prefix, &line.message); - let tags: Vec<&str> = - line.tags.iter().map(|t| t.as_str()).collect(); + let tags: Vec<&str> = line + .tags + .iter() + .map(|t| { + if t.starts_with("matrix_id") { + event_id_tag.as_str() + } else { + t.as_str() + } + }) + .collect(); buffer.print_date_tags(date, &tags, &message) } diff --git a/src/room/mod.rs b/src/room/mod.rs index 5372524..2efda77 100644 --- a/src/room/mod.rs +++ b/src/room/mod.rs @@ -399,7 +399,8 @@ impl MatrixRoom { } pub fn cancel_verification(&self) { - todo!() + let verification = self.verification.clone(); + Weechat::spawn(async move { verification.cancel().await }).detach(); } async fn redact_event(&self, event: &SyncRedactionEvent) { @@ -831,9 +832,12 @@ impl MatrixRoom { // ourselves, the content will be in the outgoing message queue and it // may have been printed out as a local echo. if let Some(id) = &event.unsigned().transaction_id { - if let Ok(id) = Uuid::parse_str(id) { - self.handle_outgoing_message(id, event.event_id()).await; - return; + // We don't support local echo for verification events. + if !event.is_verification() { + if let Ok(id) = Uuid::parse_str(id) { + self.handle_outgoing_message(id, event.event_id()).await; + return; + } } } diff --git a/src/room/verification.rs b/src/room/verification.rs index f0db432..fee9839 100644 --- a/src/room/verification.rs +++ b/src/room/verification.rs @@ -8,12 +8,18 @@ use matrix_sdk::{ }, identifiers::UserId, }, - verification::{SasVerification, VerificationRequest}, + verification::{ + CancelInfo, SasVerification, Verification as SdkVerification, + VerificationRequest, + }, + Result, }; use crate::{ connection::Connection, - render::{Render, VerificationContext, VerificationRequestContext}, + render::{ + CancelContext, Render, VerificationContext, VerificationRequestContext, + }, }; use super::{buffer::RoomBuffer, members::Members}; @@ -40,6 +46,20 @@ impl ActiveVerification { ActiveVerification::Sas(v) => v.is_done(), } } + + fn cancel_info(&self) -> Option { + match self { + ActiveVerification::Request(v) => v.cancel_info(), + ActiveVerification::Sas(v) => v.cancel_info(), + } + } + + async fn cancel(&self) -> Result<()> { + match self { + ActiveVerification::Request(v) => v.cancel().await, + ActiveVerification::Sas(v) => v.cancel().await, + } + } } impl From for ActiveVerification { @@ -83,6 +103,17 @@ impl Verification { } } + pub async fn cancel(&self) { + let connection = self.connection.borrow().clone(); + + if let Some(c) = connection { + if let Some(verification) = self.inner.borrow().clone() { + let ret = + c.spawn(async move { verification.cancel().await }).await; + } + } + } + pub async fn accept(&self) { let connection = self.connection.borrow().clone(); let verification = self.inner.borrow().clone(); @@ -166,9 +197,6 @@ impl Verification { } } } - AnySyncMessageEvent::KeyVerificationCancel(_) => { - self.inner.borrow_mut().take(); - } AnySyncMessageEvent::KeyVerificationAccept(_) => {} AnySyncMessageEvent::KeyVerificationKey(e) => { let flow_id = &e.content.relates_to.event_id; @@ -198,6 +226,47 @@ impl Verification { todo!("Print done"); } } + AnySyncMessageEvent::KeyVerificationCancel(e) => { + let flow_id = &e.content.relates_to.event_id; + + let cancelled = self + .inner + .borrow() + .as_ref() + .map(|v| v.cancel_info()) + .unwrap_or_default(); + + if let Some(cancel_info) = cancelled { + let verification = + if let Some(v) = self.inner.borrow_mut().take() { + v + } else { + return; + }; + + let member = if cancel_info.cancelled_by_us() { + own_member.clone() + } else { + sender.clone() + }; + + let verification = match verification { + ActiveVerification::Request(r) => r.into(), + ActiveVerification::Sas(v) => { + SdkVerification::from(v).into() + } + }; + + let context = CancelContext::Room(member, verification); + let rendered = cancel_info.render_with_prefix( + send_time, + &e.event_id, + &sender.clone(), + &context, + ); + self.buffer.replace_verification_event(flow_id, rendered); + } + } AnySyncMessageEvent::RoomMessage(e) => { if let MessageType::VerificationRequest(content) = &e.content.msgtype