diff --git a/src/buffers/room.rs b/src/buffers/room.rs index d3be695..bc1ef4e 100644 --- a/src/buffers/room.rs +++ b/src/buffers/room.rs @@ -26,7 +26,8 @@ use matrix_sdk::ruma::OwnedRoomId; use matrix_sdk::Client; use matrix_sdk::Room; use matrix_sdk_ui::timeline::{ - BackPaginationStatus, PaginationOptions, RoomExt, Timeline, TimelineItem, + BackPaginationStatus, PaginationOptions, RoomExt, Timeline, TimelineItem, TimelineItemKind, + VirtualTimelineItem, }; use ratatui::text::Text; use smallvec::SmallVec; @@ -52,11 +53,153 @@ impl SingleClientRoomBuffer { } if let Some(changes) = self.stream.next().await { for change in changes { - change.map(|timeline_item| format!("{:#?}", timeline_item)).apply(&mut self.items); + change + .map(|item| self.format_timeline_item(item)) + .apply(&mut self.items); } } } + fn format_timeline_item(&self, tl_item: impl AsRef) -> String { + match tl_item.as_ref().kind() { + TimelineItemKind::Event(event) => { + use matrix_sdk_ui::timeline::TimelineItemContent::*; + let sender = event + .sender() + .as_str() + .strip_prefix("@") + .expect("missing @ prefix"); + match event.content() { + Message(message) => format!(" <{}> {}", sender, message.body().replace("\n", "\n ")), + RedactedMessage => format!("xx <{}> [redacted]", sender), + Sticker(sticker) => format!("st <{}> {}", sender, sticker.content().body), + UnableToDecrypt(_) => format!("xx <{}> [unable to decrypt]", sender), + MembershipChange(change) => { + use matrix_sdk_ui::timeline::MembershipChange::*; + if change.user_id() == event.sender() { + let Some(change_kind) = change.change() else { + return format!("--- {} made incomprehensible changes to themselves", sender); + }; + match change_kind { + None => format!("--- {} made no discernable changes to themselves", sender), + Error => format!( + "xxx {} made a change to themselves that made matrix-sdk-ui error", + sender + ), + Joined => format!("--> {} joined", sender), + Left => format!("<-- {} left", sender), + Banned => format!("-x- {} banned themselves", sender), + Unbanned => format!("-x- {} unbanned themselves", sender), + Kicked => format!(" format!("-o- {} invited themselves", sender), + KickedAndBanned => format!(" format!("-o> {} accepted an invite", sender), + InvitationRejected => format!("-ox {} rejected an invite", sender), + InvitationRevoked => format!("--x {} revoked an invite", sender), + Knocked => format!("-?> {} knocked", sender), + KnockAccepted => format!("-?o {} accepted a knock", sender), + KnockRetracted => format!("-?x {} retracted a knock", sender), + KnockDenied => format!("-?x {} denied a knock", sender), + NotImplemented => format!( + "xxx {} made a change matrix-sdk-ui does not support yet", + sender + ), + } + } else if change.user_id() == "" { + let Some(change_kind) = change.change() else { + return format!("--- {} made incomprehensible changes", sender); + }; + match change_kind { + None => format!("--- {} made no discernable changes", sender), + Error => format!("xxx {} made a change that made matrix-sdk-ui error", sender), + Joined | Left | Banned | Unbanned | Kicked | Invited | KickedAndBanned + | InvitationAccepted | InvitationRejected | InvitationRevoked | Knocked + | KnockAccepted | KnockRetracted | KnockDenied => { + format!("--> {} made a non-sensical change: {:?}", sender, change) + }, + NotImplemented => format!( + "xxx {} made a change matrix-sdk-ui does not support yet", + sender + ), + } + } else { + let target = change + .user_id() + .as_str() + .strip_prefix("@") + .expect("missing @ prefix"); + let Some(change_kind) = change.change() else { + return format!("--- {} made incomprehensible changes to {}", sender, target); + }; + match change_kind { + None => format!("--- {} made no discernable changes to {}", sender, target), + Error => format!( + "xxx {} made a change to {} that made matrix-sdk-ui error", + sender, target + ), + Joined | Left => format!( + "--> {} made a non-sensical change to {}: {:?}", + sender, target, change + ), + Banned => format!("-x- {} banned {}", sender, target), + Unbanned => format!("-x- {} unbanned {}", sender, target), + Kicked => format!(" format!("-o- {} invited {}", sender, target), + KickedAndBanned => format!(" format!("-o> {} accepted an invite to {}", sender, target), + InvitationRejected => format!("-ox {} rejected an invite to {}", sender, target), + InvitationRevoked => format!("--x {} revoked an invite to {}", sender, target), + Knocked => format!("-?> {} made {} knock", sender, target), + KnockAccepted => format!("-?o {} accepted {}'s knock", sender, target), + KnockRetracted => format!("-?x {} retracted {}'s knock", sender, target), + KnockDenied => format!("-?x {} denied {}'s knock", sender, target), + NotImplemented => format!( + "xxx {} made a change to {} that matrix-sdk-ui does not support yet", + sender, target + ), + } + } + }, + + ProfileChange(_) => format!("--- {} updated their profile", sender), + OtherState(state) => { + if state.state_key() == "" { + format!("--- {} changed the room: {:?}", sender, state.content()) + } else { + format!( + "--- {} changed {}: {:?}", + sender, + state.state_key(), + state.content() + ) + } + }, + FailedToParseMessageLike { event_type, error } => format!( + "xxx {} sent a {} message that made matrix-sdk-ui error: {:?}", + sender, event_type, error + ), + FailedToParseState { + event_type, + state_key, + error, + } => { + format!( + "xxx {} made a {} change to {} that made matrix-sdk-ui error: {:?}", + sender, event_type, state_key, error + ) + }, + Poll(_) => format!("-?- {} acted on a poll", sender), + } + }, + TimelineItemKind::Virtual(VirtualTimelineItem::ReadMarker) => { + format!("---- read marker ----") + }, + TimelineItemKind::Virtual(VirtualTimelineItem::DayDivider(day_divider)) => { + format!("---- day divider: {:?} ----", day_divider) + }, + } + } + async fn spawn_back_pagination(&self, num: u16) { let room_id = self.room_id.clone(); let timeline = self.timeline.clone();