mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Support redacting messages (#5)
This commit is contained in:
parent
d13d4b9f7f
commit
56ec90523c
6 changed files with 132 additions and 8 deletions
|
@ -63,6 +63,7 @@ pub enum VerifyAction {
|
|||
pub enum MessageAction {
|
||||
Cancel,
|
||||
Download(Option<String>, bool),
|
||||
Redact(Option<String>),
|
||||
Reply,
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,19 @@ fn iamb_cancel(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
|||
return Ok(step);
|
||||
}
|
||||
|
||||
fn iamb_redact(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||
let args = desc.arg.strings()?;
|
||||
|
||||
if args.len() > 1 {
|
||||
return Result::Err(CommandError::InvalidArgument);
|
||||
}
|
||||
|
||||
let ract = IambAction::from(MessageAction::Redact(args.into_iter().next()));
|
||||
let step = CommandStep::Continue(ract.into(), ctx.context.take());
|
||||
|
||||
return Ok(step);
|
||||
}
|
||||
|
||||
fn iamb_reply(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||
if !desc.arg.text.is_empty() {
|
||||
return Result::Err(CommandError::InvalidArgument);
|
||||
|
@ -259,6 +272,7 @@ fn add_iamb_commands(cmds: &mut ProgramCommands) {
|
|||
cmds.add_command(ProgramCommand { names: vec!["invite".into()], f: iamb_invite });
|
||||
cmds.add_command(ProgramCommand { names: vec!["join".into()], f: iamb_join });
|
||||
cmds.add_command(ProgramCommand { names: vec!["members".into()], f: iamb_members });
|
||||
cmds.add_command(ProgramCommand { names: vec!["redact".into()], f: iamb_redact });
|
||||
cmds.add_command(ProgramCommand { names: vec!["reply".into()], f: iamb_reply });
|
||||
cmds.add_command(ProgramCommand { names: vec!["rooms".into()], f: iamb_rooms });
|
||||
cmds.add_command(ProgramCommand { names: vec!["set".into()], f: iamb_set });
|
||||
|
@ -429,4 +443,25 @@ mod tests {
|
|||
let res = cmds.input_cmd("invite @user:example.com", ctx.clone());
|
||||
assert_eq!(res, Err(CommandError::InvalidArgument));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmd_redact() {
|
||||
let mut cmds = setup_commands();
|
||||
let ctx = ProgramContext::default();
|
||||
|
||||
let res = cmds.input_cmd("redact", ctx.clone()).unwrap();
|
||||
let act = IambAction::Message(MessageAction::Redact(None));
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
|
||||
let res = cmds.input_cmd("redact Removed", ctx.clone()).unwrap();
|
||||
let act = IambAction::Message(MessageAction::Redact(Some("Removed".into())));
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
|
||||
let res = cmds.input_cmd("redact \"Removed\"", ctx.clone()).unwrap();
|
||||
let act = IambAction::Message(MessageAction::Redact(Some("Removed".into())));
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
|
||||
let res = cmds.input_cmd("redact Removed Removed", ctx.clone());
|
||||
assert_eq!(res, Err(CommandError::InvalidArgument));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,16 +11,23 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use matrix_sdk::ruma::{
|
||||
events::room::message::{
|
||||
MessageType,
|
||||
OriginalRoomMessageEvent,
|
||||
RedactedRoomMessageEvent,
|
||||
RoomMessageEvent,
|
||||
RoomMessageEventContent,
|
||||
events::{
|
||||
room::{
|
||||
message::{
|
||||
MessageType,
|
||||
OriginalRoomMessageEvent,
|
||||
RedactedRoomMessageEvent,
|
||||
RoomMessageEvent,
|
||||
RoomMessageEventContent,
|
||||
},
|
||||
redaction::SyncRoomRedactionEvent,
|
||||
},
|
||||
Redact,
|
||||
},
|
||||
MilliSecondsSinceUnixEpoch,
|
||||
OwnedEventId,
|
||||
OwnedUserId,
|
||||
RoomVersionId,
|
||||
UInt,
|
||||
};
|
||||
|
||||
|
@ -323,10 +330,34 @@ impl MessageEvent {
|
|||
pub fn show(&self) -> Cow<'_, str> {
|
||||
match self {
|
||||
MessageEvent::Original(ev) => show_room_content(&ev.content),
|
||||
MessageEvent::Redacted(_) => Cow::Borrowed("[redacted]"),
|
||||
MessageEvent::Redacted(ev) => {
|
||||
let reason = ev
|
||||
.unsigned
|
||||
.redacted_because
|
||||
.as_ref()
|
||||
.and_then(|e| e.as_original())
|
||||
.and_then(|r| r.content.reason.as_ref());
|
||||
|
||||
if let Some(r) = reason {
|
||||
Cow::Owned(format!("[Redacted: {:?}]", r))
|
||||
} else {
|
||||
Cow::Borrowed("[Redacted]")
|
||||
}
|
||||
},
|
||||
MessageEvent::Local(content) => show_room_content(content),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn redact(&mut self, redaction: SyncRoomRedactionEvent, version: &RoomVersionId) {
|
||||
match self {
|
||||
MessageEvent::Redacted(_) => return,
|
||||
MessageEvent::Local(_) => return,
|
||||
MessageEvent::Original(ev) => {
|
||||
let redacted = ev.clone().redact(redaction, version);
|
||||
*self = MessageEvent::Redacted(Box::new(redacted));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show_room_content(content: &RoomMessageEventContent) -> Cow<'_, str> {
|
||||
|
|
|
@ -224,6 +224,33 @@ impl ChatState {
|
|||
|
||||
Err(IambError::NoAttachment.into())
|
||||
},
|
||||
MessageAction::Redact(reason) => {
|
||||
let room = store
|
||||
.application
|
||||
.worker
|
||||
.client
|
||||
.get_joined_room(self.id())
|
||||
.ok_or(IambError::NotJoined)?;
|
||||
|
||||
let event_id = match &msg.event {
|
||||
MessageEvent::Original(ev) => ev.event_id.clone(),
|
||||
MessageEvent::Local(_) => {
|
||||
self.scrollback.get_key(info).ok_or(IambError::NoSelectedMessage)?.1
|
||||
},
|
||||
MessageEvent::Redacted(_) => {
|
||||
let msg = "";
|
||||
let err = UIError::Failure(msg.into());
|
||||
|
||||
return Err(err);
|
||||
},
|
||||
};
|
||||
|
||||
let event_id = event_id.as_ref();
|
||||
let reason = reason.as_deref();
|
||||
let _ = room.redact(event_id, reason, None).await.map_err(IambError::from)?;
|
||||
|
||||
Ok(None)
|
||||
},
|
||||
MessageAction::Reply => {
|
||||
self.reply_to = self.scrollback.get_key(info);
|
||||
self.focus = RoomFocus::MessageBar;
|
||||
|
|
|
@ -35,6 +35,7 @@ use matrix_sdk::{
|
|||
room::{
|
||||
message::{MessageType, RoomMessageEventContent},
|
||||
name::RoomNameEventContent,
|
||||
redaction::{OriginalSyncRoomRedactionEvent, SyncRoomRedactionEvent},
|
||||
topic::RoomTopicEventContent,
|
||||
},
|
||||
typing::SyncTypingEvent,
|
||||
|
@ -46,6 +47,7 @@ use matrix_sdk::{
|
|||
OwnedRoomId,
|
||||
OwnedRoomOrAliasId,
|
||||
OwnedUserId,
|
||||
RoomVersionId,
|
||||
},
|
||||
Client,
|
||||
DisplayName,
|
||||
|
@ -547,6 +549,34 @@ impl ClientWorker {
|
|||
},
|
||||
);
|
||||
|
||||
let _ = self.client.add_event_handler(
|
||||
|ev: OriginalSyncRoomRedactionEvent,
|
||||
room: MatrixRoom,
|
||||
store: Ctx<AsyncProgramStore>| {
|
||||
async move {
|
||||
let room_id = room.room_id();
|
||||
let room_info = room.clone_info();
|
||||
let room_version = room_info.room_version().unwrap_or(&RoomVersionId::V1);
|
||||
|
||||
let mut locked = store.lock().await;
|
||||
let info = locked.application.get_room_info(room_id.to_owned());
|
||||
|
||||
// XXX: need to store a mapping of EventId -> MessageKey somewhere
|
||||
// to avoid having to iterate over the messages here.
|
||||
for ((_, id), msg) in info.messages.iter_mut().rev() {
|
||||
if id != &ev.redacts {
|
||||
continue;
|
||||
}
|
||||
|
||||
let ev = SyncRoomRedactionEvent::Original(ev);
|
||||
msg.event.redact(ev, room_version);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let _ = self.client.add_event_handler(
|
||||
|ev: OriginalSyncKeyVerificationStartEvent,
|
||||
client: Client,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue