96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 1 | use std::sync::Arc; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 2 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 3 | use matrix_sdk_ui::{ |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 4 | eyeball_im::VectorDiff, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 5 | timeline::{ |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 6 | EventSendState, MsgLikeKind, TimelineDetails, TimelineEventItemId, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 7 | TimelineItem as SdkTimelineItem, TimelineItemContent, TimelineItemKind, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 8 | VirtualTimelineItem, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 9 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 10 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 11 | use ruma::{ |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 12 | UserId, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 13 | events::room::message::{MessageFormat, MessageType}, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 14 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 15 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 16 | use crate::{ |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 17 | MessageMentions, Reaction, ReplyReference, SendState, ThreadSummary, TimelineDiff, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 18 | TimelineItem, TimelineItemId, TimelineMessage, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 19 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 20 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 21 | use super::media::{ |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 22 | MediaRegistration, MediaScope, media_descriptor_for_sticker, media_from_message, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 23 | media_identity, media_registration_for_item, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 24 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 25 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 26 | pub(crate) struct NormalisedTimeline { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 27 | pub(crate) items: Vec<TimelineItem>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 28 | pub(crate) media: Vec<MediaRegistration>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 29 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 30 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 31 | pub(crate) fn normalise_timeline<'a>( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 32 | items: impl Iterator<Item = &'a Arc<SdkTimelineItem>>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 33 | current_user_id: Option<&UserId>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 34 | scope: &MediaScope, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 35 | ) -> NormalisedTimeline { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 36 | let mut normalised = NormalisedTimeline { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 37 | items: Vec::new(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 38 | media: Vec::new(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 39 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 40 | for item in items { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 41 | if let Some(media) = media_registration_for_item(item, scope) { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 42 | normalised.media.push(media); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 43 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 44 | normalised |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 45 | .items |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 46 | .push(normalise_timeline_item(item, current_user_id, scope)); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 47 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 48 | normalised |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 49 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 50 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 51 | pub(crate) fn normalise_timeline_diffs( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 52 | diffs: Vec<VectorDiff<Arc<SdkTimelineItem>>>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 53 | current_user_id: Option<&UserId>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 54 | scope: &MediaScope, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 55 | ) -> NormalisedTimelineDiffs { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 56 | let mut media = Vec::new(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 57 | let diffs = diffs |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 58 | .into_iter() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 59 | .map(|diff| { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 60 | let diff = diff.map(|item| { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 61 | if let Some(registration) = media_registration_for_item(&item, scope) { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 62 | media.push(registration); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 63 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 64 | normalise_timeline_item(&item, current_user_id, scope) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 65 | }); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 66 | match diff { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 67 | VectorDiff::Append { values } => TimelineDiff::Append { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 68 | values: values.into_iter().collect(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 69 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 70 | VectorDiff::Clear => TimelineDiff::Clear, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 71 | VectorDiff::PushFront { value } => TimelineDiff::PushFront { value }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 72 | VectorDiff::PushBack { value } => TimelineDiff::PushBack { value }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 73 | VectorDiff::PopFront => TimelineDiff::PopFront, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 74 | VectorDiff::PopBack => TimelineDiff::PopBack, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 75 | VectorDiff::Insert { index, value } => TimelineDiff::Insert { index, value }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 76 | VectorDiff::Set { index, value } => TimelineDiff::Set { index, value }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 77 | VectorDiff::Remove { index } => TimelineDiff::Remove { index }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 78 | VectorDiff::Truncate { length } => TimelineDiff::Truncate { length }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 79 | VectorDiff::Reset { values } => TimelineDiff::Reset { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 80 | values: values.into_iter().collect(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 81 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 82 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 83 | }) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 84 | .collect(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 85 | NormalisedTimelineDiffs { diffs, media } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 86 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 87 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 88 | pub(crate) struct NormalisedTimelineDiffs { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 89 | pub(crate) diffs: Vec<TimelineDiff>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 90 | pub(crate) media: Vec<MediaRegistration>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 91 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 92 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 93 | fn normalise_timeline_item( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 94 | item: &SdkTimelineItem, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 95 | current_user_id: Option<&UserId>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 96 | scope: &MediaScope, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 97 | ) -> TimelineItem { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 98 | match item.kind() { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 99 | TimelineItemKind::Event(event) => TimelineItem::Message(Box::new(timeline_message( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 100 | item, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 101 | event, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 102 | current_user_id, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 103 | scope, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 104 | ))), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 105 | TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(timestamp)) => { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 106 | TimelineItem::DayDivider { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 107 | timestamp_ms: timestamp.get().into(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 108 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 109 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 110 | TimelineItemKind::Virtual(VirtualTimelineItem::ReadMarker) => TimelineItem::ReadMarker, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 111 | TimelineItemKind::Virtual(VirtualTimelineItem::TimelineStart) => { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 112 | TimelineItem::TimelineStart |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 113 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 114 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 115 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 116 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 117 | fn timeline_message( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 118 | item: &SdkTimelineItem, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 119 | event: &matrix_sdk_ui::timeline::EventTimelineItem, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 120 | current_user_id: Option<&UserId>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 121 | scope: &MediaScope, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 122 | ) -> TimelineMessage { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 123 | let (body, formatted_body, mentions, edited, unable_to_decrypt, media) = match event.content() { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 124 | TimelineItemContent::MsgLike(content) => match &content.kind { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 125 | MsgLikeKind::Message(message) => ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 126 | message.body().to_owned(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 127 | formatted_body(message.msgtype()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 128 | message.mentions().map(message_mentions), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 129 | message.is_edited(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 130 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 131 | media_from_message(&media_identity(item, scope), message.msgtype()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 132 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 133 | MsgLikeKind::Sticker(sticker) => { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 134 | let content = sticker.content(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 135 | ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 136 | content.body.clone(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 137 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 138 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 139 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 140 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 141 | Some(media_descriptor_for_sticker( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 142 | &media_identity(item, scope), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 143 | content, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 144 | )), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 145 | ) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 146 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 147 | MsgLikeKind::Redacted => ("<message redacted>".into(), None, None, false, false, None), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 148 | MsgLikeKind::UnableToDecrypt(_) => ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 149 | "<unable to decrypt message>".into(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 150 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 151 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 152 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 153 | true, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 154 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 155 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 156 | MsgLikeKind::Poll(_) => ("[poll]".into(), None, None, false, false, None), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 157 | MsgLikeKind::LiveLocation(_) => { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 158 | ("[live location]".into(), None, None, false, false, None) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 159 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 160 | MsgLikeKind::Other(other) => ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 161 | format!("[{}]", other.event_type()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 162 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 163 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 164 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 165 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 166 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 167 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 168 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 169 | other => ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 170 | format!( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 171 | "[{}]", |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 172 | other.event_type_str().unwrap_or_else(|| "event".into()) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 173 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 174 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 175 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 176 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 177 | false, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 178 | None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 179 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 180 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 181 | let reply_to = match event.content() { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 182 | TimelineItemContent::MsgLike(content) => content.in_reply_to.as_ref().map(|reply| { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 183 | let event_id = reply.event_id.to_owned(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 184 | let embedded_sender = match &reply.event { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 185 | TimelineDetails::Ready(event) => Some(( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 186 | event.sender.clone(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 187 | sender_name(&event.sender, &event.sender_profile), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 188 | )), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 189 | _ => None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 190 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 191 | ReplyReference { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 192 | event_id, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 193 | sender_id: embedded_sender.as_ref().map(|(id, _)| id.clone()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 194 | sender_name: embedded_sender.map(|(_, name)| name), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 195 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 196 | }), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 197 | _ => None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 198 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 199 | let (thread_root, thread_summary) = match event.content() { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 200 | TimelineItemContent::MsgLike(content) => ( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 201 | content.thread_root.clone(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 202 | content.thread_summary.as_ref().map(|summary| { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 203 | let latest_event = match &summary.latest_event { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 204 | TimelineDetails::Ready(event) => Some(event.as_ref()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 205 | _ => None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 206 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 207 | ThreadSummary { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 208 | reply_count: summary.num_replies, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 209 | latest_event_id: latest_event.and_then(|event| match &event.identifier { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 210 | TimelineEventItemId::EventId(event_id) => Some(event_id.clone()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 211 | TimelineEventItemId::TransactionId(_) => None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 212 | }), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 213 | latest_event_timestamp_ms: latest_event |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 214 | .map(|event| event.timestamp.get().into()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 215 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 216 | }), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 217 | ), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 218 | _ => (None, None), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 219 | }; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 220 | let reactions = event |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 221 | .content() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 222 | .reactions() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 223 | .into_iter() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 224 | .flat_map(|reactions| reactions.iter()) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 225 | .map(|(key, senders)| Reaction { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 226 | key: key.clone(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 227 | count: senders.len(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 228 | own: current_user_id.is_some_and(|user_id| senders.contains_key(user_id)), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 229 | senders: senders.keys().cloned().collect(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 230 | }) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 231 | .collect(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 232 | let mut read_by: Vec<_> = event |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 233 | .read_receipts() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 234 | .keys() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 235 | .filter(|user_id| *user_id != event.sender()) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 236 | .cloned() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 237 | .collect(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 238 | read_by.sort(); |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 239 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 240 | TimelineMessage { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 241 | item_id: TimelineItemId::new(item.unique_id().0.clone()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 242 | event_id: event.event_id().map(ToOwned::to_owned), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 243 | transaction_id: event.transaction_id().map(ToOwned::to_owned), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 244 | sender_id: event.sender().to_owned(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 245 | sender_name: sender_name(event.sender(), event.sender_profile()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 246 | body, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 247 | formatted_body, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 248 | mentions, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 249 | thread_root, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 250 | thread_summary, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 251 | timestamp_ms: event.timestamp().get().into(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 252 | own: event.is_own(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 253 | send_state: match event.send_state() { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 254 | None | Some(EventSendState::Sent { .. }) => SendState::Sent, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 255 | Some(EventSendState::NotSentYet { progress: Some(_) }) => SendState::Sending, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 256 | Some(EventSendState::NotSentYet { progress: None }) => SendState::Queued, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 257 | Some(EventSendState::SendingFailed { is_recoverable, .. }) => SendState::Failed { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 258 | retriable: *is_recoverable, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 259 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 260 | }, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 261 | edited, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 262 | unable_to_decrypt, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 263 | media, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 264 | reply_to, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 265 | reactions, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 266 | read_by, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 267 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 268 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 269 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 270 | fn sender_name( |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 271 | sender: &UserId, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 272 | sender_profile: &TimelineDetails<matrix_sdk_ui::timeline::Profile>, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 273 | ) -> String { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 274 | match sender_profile { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 275 | TimelineDetails::Ready(profile) => profile |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 276 | .display_name |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 277 | .clone() |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 278 | .unwrap_or_else(|| sender.to_string()), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 279 | _ => sender.to_string(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 280 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 281 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 282 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 283 | fn formatted_body(message: &MessageType) -> Option<String> { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 284 | let formatted = match message { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 285 | MessageType::Text(content) => content.formatted.as_ref(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 286 | MessageType::Emote(content) => content.formatted.as_ref(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 287 | MessageType::Notice(content) => content.formatted.as_ref(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 288 | MessageType::Audio(content) => content.formatted_caption(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 289 | MessageType::File(content) => content.formatted_caption(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 290 | MessageType::Image(content) => content.formatted_caption(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 291 | MessageType::Video(content) => content.formatted_caption(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 292 | _ => None, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 293 | }?; |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 294 | (formatted.format == MessageFormat::Html).then(|| formatted.body.clone()) |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 295 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 296 | |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 297 | fn message_mentions(mentions: &ruma::events::Mentions) -> MessageMentions { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 298 | MessageMentions { |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 299 | user_ids: mentions.user_ids.iter().cloned().collect(), |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 300 | room: mentions.room, |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 301 | } |
96fdf90aacd6 | atagen | 2026-09-08 08:24 UTC | 302 | } |