mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-03 21:45:51 -04:00
feat(ffi): introduce a ThreadSummary type within MsgLikeContent (#4933)
…that holds information on the thread the given item is the root of - it holds the latest event content and sender at the moment but will hold more information in the future e.g. number of replies, if it's unread etc. - the field is not currently being populate but is delivered earlier so it can power shipping the UI side on the embedders
This commit is contained in:
@@ -15,13 +15,17 @@
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use matrix_sdk::crypto::types::events::UtdCause;
|
||||
use matrix_sdk_ui::timeline::TimelineDetails;
|
||||
use ruma::events::{room::MediaSource as RumaMediaSource, EventContent};
|
||||
|
||||
use super::{content::Reaction, reply::InReplyToDetails};
|
||||
use super::{
|
||||
content::{Reaction, TimelineItemContent},
|
||||
reply::InReplyToDetails,
|
||||
};
|
||||
use crate::{
|
||||
error::ClientError,
|
||||
ruma::{ImageInfo, MediaSource, MediaSourceExt, Mentions, MessageType, PollKind},
|
||||
timeline::content::ReactionSenderData,
|
||||
timeline::{content::ReactionSenderData, ProfileDetails},
|
||||
utils::Timestamp,
|
||||
};
|
||||
|
||||
@@ -56,10 +60,12 @@ pub enum MsgLikeKind {
|
||||
pub struct MsgLikeContent {
|
||||
pub kind: MsgLikeKind,
|
||||
pub reactions: Vec<Reaction>,
|
||||
/// Event ID of the thread root, if this is a threaded message.
|
||||
pub thread_root: Option<String>,
|
||||
/// The event this message is replying to, if any.
|
||||
pub in_reply_to: Option<Arc<InReplyToDetails>>,
|
||||
/// Event ID of the thread root, if this is a message in a thread.
|
||||
pub thread_root: Option<String>,
|
||||
/// Details about the thread this message is the root of.
|
||||
pub thread_summary: Option<Arc<ThreadSummary>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
@@ -95,6 +101,8 @@ impl TryFrom<matrix_sdk_ui::timeline::MsgLikeContent> for MsgLikeContent {
|
||||
|
||||
let thread_root = value.thread_root.map(|id| id.to_string());
|
||||
|
||||
let thread_summary = value.thread_summary.map(|t| Arc::new(t.into()));
|
||||
|
||||
Ok(match value.kind {
|
||||
Kind::Message(message) => {
|
||||
let msg_type = TryInto::<MessageType>::try_into(message.msgtype().clone())
|
||||
@@ -112,6 +120,7 @@ impl TryFrom<matrix_sdk_ui::timeline::MsgLikeContent> for MsgLikeContent {
|
||||
reactions,
|
||||
in_reply_to,
|
||||
thread_root,
|
||||
thread_summary,
|
||||
}
|
||||
}
|
||||
Kind::Sticker(sticker) => {
|
||||
@@ -134,6 +143,7 @@ impl TryFrom<matrix_sdk_ui::timeline::MsgLikeContent> for MsgLikeContent {
|
||||
reactions,
|
||||
in_reply_to,
|
||||
thread_root,
|
||||
thread_summary,
|
||||
}
|
||||
}
|
||||
Kind::Poll(poll_state) => {
|
||||
@@ -156,16 +166,22 @@ impl TryFrom<matrix_sdk_ui::timeline::MsgLikeContent> for MsgLikeContent {
|
||||
reactions,
|
||||
in_reply_to,
|
||||
thread_root,
|
||||
thread_summary,
|
||||
}
|
||||
}
|
||||
Kind::Redacted => {
|
||||
Self { kind: MsgLikeKind::Redacted, reactions, in_reply_to, thread_root }
|
||||
}
|
||||
Kind::Redacted => Self {
|
||||
kind: MsgLikeKind::Redacted,
|
||||
reactions,
|
||||
in_reply_to,
|
||||
thread_root,
|
||||
thread_summary,
|
||||
},
|
||||
Kind::UnableToDecrypt(msg) => Self {
|
||||
kind: MsgLikeKind::UnableToDecrypt { msg: EncryptedMessage::new(&msg) },
|
||||
reactions,
|
||||
in_reply_to,
|
||||
thread_root,
|
||||
thread_summary,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -222,3 +238,42 @@ pub struct PollAnswer {
|
||||
pub id: String,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Object)]
|
||||
pub struct ThreadSummary {
|
||||
pub latest_event: ThreadSummaryLatestEventDetails,
|
||||
}
|
||||
|
||||
#[matrix_sdk_ffi_macros::export]
|
||||
impl ThreadSummary {
|
||||
pub fn latest_event(&self) -> ThreadSummaryLatestEventDetails {
|
||||
self.latest_event.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Enum)]
|
||||
pub enum ThreadSummaryLatestEventDetails {
|
||||
Unavailable,
|
||||
Pending,
|
||||
Ready { sender: String, sender_profile: ProfileDetails, content: TimelineItemContent },
|
||||
Error { message: String },
|
||||
}
|
||||
|
||||
impl From<matrix_sdk_ui::timeline::ThreadSummary> for ThreadSummary {
|
||||
fn from(value: matrix_sdk_ui::timeline::ThreadSummary) -> Self {
|
||||
let latest_event = match value.latest_event {
|
||||
TimelineDetails::Unavailable => ThreadSummaryLatestEventDetails::Unavailable,
|
||||
TimelineDetails::Pending => ThreadSummaryLatestEventDetails::Pending,
|
||||
TimelineDetails::Ready(event) => ThreadSummaryLatestEventDetails::Ready {
|
||||
content: event.content.into(),
|
||||
sender: event.sender.to_string(),
|
||||
sender_profile: (&event.sender_profile).into(),
|
||||
},
|
||||
TimelineDetails::Error(message) => {
|
||||
ThreadSummaryLatestEventDetails::Error { message: message.to_string() }
|
||||
}
|
||||
};
|
||||
|
||||
Self { latest_event }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,6 +542,7 @@ mod tests {
|
||||
ReactionsByKeyBySender::default(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
event_kind,
|
||||
true,
|
||||
|
||||
@@ -1026,16 +1026,14 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
|
||||
};
|
||||
|
||||
// Replace the local-related state (kind) and the content state.
|
||||
let prev_reactions = prev_item.content().reactions();
|
||||
let prev_thread_root = prev_item.content().thread_root();
|
||||
let prev_in_reply_to = prev_item.content().in_reply_to();
|
||||
let new_item = TimelineItem::new(
|
||||
prev_item.with_kind(ti_kind).with_content(TimelineItemContent::message(
|
||||
content,
|
||||
None,
|
||||
prev_reactions,
|
||||
prev_thread_root,
|
||||
prev_in_reply_to,
|
||||
prev_item.content().reactions(),
|
||||
prev_item.content().thread_root(),
|
||||
prev_item.content().in_reply_to(),
|
||||
prev_item.content().thread_summary(),
|
||||
)),
|
||||
prev_item.internal_id.to_owned(),
|
||||
);
|
||||
@@ -1388,6 +1386,7 @@ impl TimelineController {
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
}) = item.content().clone()
|
||||
else {
|
||||
info!("Event is no longer a message (redacted?)");
|
||||
@@ -1408,6 +1407,7 @@ impl TimelineController {
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to: Some(InReplyToDetails { event_id: in_reply_to.event_id, event }),
|
||||
thread_summary,
|
||||
}));
|
||||
state.items.replace(index, TimelineItem::new(item, internal_id));
|
||||
|
||||
|
||||
@@ -408,6 +408,7 @@ mod observable_items_tests {
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_summary: None,
|
||||
}),
|
||||
EventTimelineItemKind::Remote(RemoteEventTimelineItem {
|
||||
event_id: event_id.parse().unwrap(),
|
||||
|
||||
@@ -418,6 +418,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_summary: None,
|
||||
}),
|
||||
None,
|
||||
);
|
||||
@@ -622,6 +623,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
Default::default(),
|
||||
thread_root,
|
||||
in_reply_to_details,
|
||||
None,
|
||||
),
|
||||
edit_json,
|
||||
);
|
||||
@@ -739,13 +741,15 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Message(msg),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
}) = item.content()
|
||||
else {
|
||||
let TimelineItemContent::MsgLike(content) = item.content() else {
|
||||
info!(
|
||||
"Edit of message event applies to {:?}, discarding",
|
||||
item.content().debug_string(),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
let MsgLikeContent { kind: MsgLikeKind::Message(msg), .. } = content else {
|
||||
info!(
|
||||
"Edit of message event applies to {:?}, discarding",
|
||||
item.content().debug_string(),
|
||||
@@ -757,12 +761,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
new_msg.apply_edit(new_content);
|
||||
|
||||
let mut new_item = item.with_content_and_latest_edit(
|
||||
TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Message(new_msg),
|
||||
reactions: reactions.clone(),
|
||||
thread_root: thread_root.clone(),
|
||||
in_reply_to: in_reply_to.clone(),
|
||||
}),
|
||||
TimelineItemContent::MsgLike(content.with_kind(MsgLikeKind::Message(new_msg))),
|
||||
edit_json,
|
||||
);
|
||||
|
||||
@@ -852,24 +851,20 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Poll(poll_state),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
}) = &item.content()
|
||||
else {
|
||||
let TimelineItemContent::MsgLike(content) = &item.content() else {
|
||||
info!("Edit of poll event applies to {}, discarding", item.content().debug_string(),);
|
||||
return None;
|
||||
};
|
||||
|
||||
let MsgLikeContent { kind: MsgLikeKind::Poll(poll_state), .. } = content else {
|
||||
info!("Edit of poll event applies to {}, discarding", item.content().debug_string(),);
|
||||
return None;
|
||||
};
|
||||
|
||||
let new_content = match poll_state.edit(replacement.new_content) {
|
||||
Some(edited_poll_state) => TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Poll(edited_poll_state),
|
||||
reactions: reactions.clone(),
|
||||
thread_root: thread_root.clone(),
|
||||
in_reply_to: in_reply_to.clone(),
|
||||
}),
|
||||
Some(edited_poll_state) => TimelineItemContent::MsgLike(
|
||||
content.with_kind(MsgLikeKind::Poll(edited_poll_state)),
|
||||
),
|
||||
None => {
|
||||
info!("Not applying edit to a poll that's already ended");
|
||||
return None;
|
||||
@@ -921,6 +916,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_summary: None,
|
||||
}),
|
||||
edit_json,
|
||||
);
|
||||
@@ -1391,19 +1387,18 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
|
||||
let Some(in_reply_to) = msglike.in_reply_to.as_ref() else { continue };
|
||||
|
||||
trace!(reply_event_id = ?event_item.identifier(), "Updating response to updated event");
|
||||
let in_reply_to = Some(InReplyToDetails {
|
||||
let in_reply_to = InReplyToDetails {
|
||||
event_id: in_reply_to.event_id.clone(),
|
||||
event: TimelineDetails::Ready(Box::new(RepliedToEvent::from_timeline_item(
|
||||
new_item,
|
||||
))),
|
||||
});
|
||||
};
|
||||
|
||||
let new_reply_content = TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Message(message.clone()),
|
||||
reactions: msglike.reactions.clone(),
|
||||
thread_root: msglike.thread_root.clone(),
|
||||
in_reply_to,
|
||||
});
|
||||
let new_reply_content = TimelineItemContent::MsgLike(
|
||||
msglike
|
||||
.with_in_reply_to(in_reply_to)
|
||||
.with_kind(MsgLikeKind::Message(message.clone())),
|
||||
);
|
||||
let new_reply_item = item.with_kind(event_item.with_content(new_reply_content));
|
||||
items.replace(timeline_item_index, new_reply_item);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ pub(in crate::timeline) use self::message::{
|
||||
};
|
||||
pub use self::{
|
||||
message::Message,
|
||||
msg_like::{MsgLikeContent, MsgLikeKind},
|
||||
msg_like::{MsgLikeContent, MsgLikeKind, ThreadSummary, ThreadSummaryLatestEvent},
|
||||
polls::{PollResult, PollState},
|
||||
reply::{InReplyToDetails, RepliedToEvent},
|
||||
};
|
||||
@@ -198,6 +198,7 @@ impl TimelineItemContent {
|
||||
let reactions = Default::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
let msglike = MsgLikeContent {
|
||||
kind: MsgLikeKind::Message(Message::from_event(
|
||||
@@ -208,6 +209,7 @@ impl TimelineItemContent {
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
};
|
||||
|
||||
TimelineItemContent::MsgLike(msglike)
|
||||
@@ -251,12 +253,14 @@ impl TimelineItemContent {
|
||||
let reactions = Default::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
let msglike = MsgLikeContent {
|
||||
kind: MsgLikeKind::Sticker(Sticker { content: event_content }),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
};
|
||||
|
||||
TimelineItemContent::MsgLike(msglike)
|
||||
@@ -292,6 +296,7 @@ impl TimelineItemContent {
|
||||
let reactions = Default::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
let msglike = MsgLikeContent {
|
||||
kind: MsgLikeKind::Poll(PollState::new(
|
||||
@@ -301,6 +306,7 @@ impl TimelineItemContent {
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
};
|
||||
|
||||
TimelineItemContent::MsgLike(msglike)
|
||||
@@ -408,6 +414,7 @@ impl TimelineItemContent {
|
||||
reactions: ReactionsByKeyBySender,
|
||||
thread_root: Option<OwnedEventId>,
|
||||
in_reply_to: Option<InReplyToDetails>,
|
||||
thread_summary: Option<ThreadSummary>,
|
||||
) -> Self {
|
||||
let remove_reply_fallback =
|
||||
if in_reply_to.is_some() { RemoveReplyFallback::Yes } else { RemoveReplyFallback::No };
|
||||
@@ -417,6 +424,7 @@ impl TimelineItemContent {
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -511,7 +519,7 @@ impl TimelineItemContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Event ID of the thread root, if this is a threaded message.
|
||||
/// Event ID of the thread root, if this is a message in a thread.
|
||||
pub fn thread_root(&self) -> Option<OwnedEventId> {
|
||||
as_variant!(self, Self::MsgLike)?.thread_root.clone()
|
||||
}
|
||||
@@ -540,6 +548,11 @@ impl TimelineItemContent {
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the thread this item is the root for.
|
||||
pub fn thread_summary(&self) -> Option<ThreadSummary> {
|
||||
as_variant!(self, Self::MsgLike)?.thread_summary.clone()
|
||||
}
|
||||
|
||||
/// Return a mutable handle to the reactions of this item.
|
||||
///
|
||||
/// See also [`Self::reactions()`] to explain the optional return type.
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
// limitations under the License.
|
||||
|
||||
use as_variant::as_variant;
|
||||
use ruma::OwnedEventId;
|
||||
use ruma::{OwnedEventId, OwnedUserId};
|
||||
|
||||
use super::{EncryptedMessage, InReplyToDetails, Message, PollState, Sticker};
|
||||
use crate::timeline::ReactionsByKeyBySender;
|
||||
use super::{EncryptedMessage, InReplyToDetails, Message, PollState, Sticker, TimelineItemContent};
|
||||
use crate::timeline::{Profile, ReactionsByKeyBySender, TimelineDetails};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MsgLikeKind {
|
||||
@@ -36,6 +36,18 @@ pub enum MsgLikeKind {
|
||||
UnableToDecrypt(EncryptedMessage),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ThreadSummary {
|
||||
pub latest_event: TimelineDetails<Box<ThreadSummaryLatestEvent>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ThreadSummaryLatestEvent {
|
||||
pub content: TimelineItemContent,
|
||||
pub sender: OwnedUserId,
|
||||
pub sender_profile: TimelineDetails<Profile>,
|
||||
}
|
||||
|
||||
/// A special kind of [`super::TimelineItemContent`] that groups together
|
||||
/// different room message types with their respective reactions and thread
|
||||
/// information.
|
||||
@@ -43,10 +55,12 @@ pub enum MsgLikeKind {
|
||||
pub struct MsgLikeContent {
|
||||
pub kind: MsgLikeKind,
|
||||
pub reactions: ReactionsByKeyBySender,
|
||||
/// Event ID of the thread root, if this is a threaded message.
|
||||
pub thread_root: Option<OwnedEventId>,
|
||||
/// The event this message is replying to, if any.
|
||||
pub in_reply_to: Option<InReplyToDetails>,
|
||||
/// Event ID of the thread root, if this is a message in a thread.
|
||||
pub thread_root: Option<OwnedEventId>,
|
||||
/// Information about the thread this message is the root of, if any.
|
||||
pub thread_summary: Option<ThreadSummary>,
|
||||
}
|
||||
|
||||
impl MsgLikeContent {
|
||||
@@ -67,6 +81,7 @@ impl MsgLikeContent {
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_summary: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +91,7 @@ impl MsgLikeContent {
|
||||
reactions: Default::default(),
|
||||
thread_root: None,
|
||||
in_reply_to: None,
|
||||
thread_summary: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +104,10 @@ impl MsgLikeContent {
|
||||
Self { in_reply_to: Some(in_reply_to), ..self.clone() }
|
||||
}
|
||||
|
||||
pub fn with_kind(&self, kind: MsgLikeKind) -> Self {
|
||||
Self { kind, ..self.clone() }
|
||||
}
|
||||
|
||||
/// If `kind` is of the [`MsgLikeKind`][MsgLikeKind::Message] variant,
|
||||
/// return the inner [`Message`].
|
||||
pub fn as_message(&self) -> Option<Message> {
|
||||
|
||||
@@ -135,11 +135,13 @@ impl RepliedToEvent {
|
||||
let content = match event.original_content() {
|
||||
Some(content) => match content {
|
||||
AnyMessageLikeEventContent::RoomMessage(c) => {
|
||||
// Assume we're not interested in reactions and thread info in this context:
|
||||
// Assume we're not interested in aggregations in this context:
|
||||
// this is information for an embedded (replied-to) event, that will usually not
|
||||
// include detailed information like reactions.
|
||||
let reactions = ReactionsByKeyBySender::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Message(Message::from_event(
|
||||
@@ -149,21 +151,25 @@ impl RepliedToEvent {
|
||||
)),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to: None,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
})
|
||||
}
|
||||
|
||||
AnyMessageLikeEventContent::Sticker(content) => {
|
||||
// Assume we're not interested in reactions or thread info in this context.
|
||||
// Assume we're not interested in aggregations in this context.
|
||||
// (See above an explanation as to why that's the case.)
|
||||
let reactions = ReactionsByKeyBySender::default();
|
||||
let reactions = Default::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
TimelineItemContent::MsgLike(MsgLikeContent {
|
||||
kind: MsgLikeKind::Sticker(Sticker { content }),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to: None,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -185,10 +191,12 @@ impl RepliedToEvent {
|
||||
AnyMessageLikeEventContent::UnstablePollStart(
|
||||
UnstablePollStartEventContent::New(content),
|
||||
) => {
|
||||
// Assume we're not interested in reactions or thread info in this context.
|
||||
// Assume we're not interested in aggregations in this context.
|
||||
// (See above an explanation as to why that's the case.)
|
||||
let reactions = ReactionsByKeyBySender::default();
|
||||
let reactions = Default::default();
|
||||
let thread_root = None;
|
||||
let in_reply_to = None;
|
||||
let thread_summary = None;
|
||||
|
||||
// TODO: could we provide the bundled edit here?
|
||||
let poll_state = PollState::new(content, None);
|
||||
@@ -196,7 +204,8 @@ impl RepliedToEvent {
|
||||
kind: MsgLikeKind::Poll(poll_state),
|
||||
reactions,
|
||||
thread_root,
|
||||
in_reply_to: None,
|
||||
in_reply_to,
|
||||
thread_summary,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ pub use self::{
|
||||
content::{
|
||||
AnyOtherFullStateEventContent, EncryptedMessage, InReplyToDetails, MemberProfileChange,
|
||||
MembershipChange, Message, MsgLikeContent, MsgLikeKind, OtherState, PollResult, PollState,
|
||||
RepliedToEvent, RoomMembershipChange, RoomPinnedEventsChange, Sticker, TimelineItemContent,
|
||||
RepliedToEvent, RoomMembershipChange, RoomPinnedEventsChange, Sticker, ThreadSummary,
|
||||
ThreadSummaryLatestEvent, TimelineItemContent,
|
||||
},
|
||||
local::EventSendState,
|
||||
};
|
||||
|
||||
@@ -83,7 +83,8 @@ pub use self::{
|
||||
EventTimelineItem, InReplyToDetails, MemberProfileChange, MembershipChange, Message,
|
||||
MsgLikeContent, MsgLikeKind, OtherState, PollResult, PollState, Profile, ReactionInfo,
|
||||
ReactionStatus, ReactionsByKeyBySender, RepliedToEvent, RoomMembershipChange,
|
||||
RoomPinnedEventsChange, Sticker, TimelineDetails, TimelineEventItemId, TimelineItemContent,
|
||||
RoomPinnedEventsChange, Sticker, ThreadSummary, ThreadSummaryLatestEvent, TimelineDetails,
|
||||
TimelineEventItemId, TimelineItemContent,
|
||||
},
|
||||
event_type_filter::TimelineEventTypeFilter,
|
||||
item::{TimelineItem, TimelineItemKind, TimelineUniqueId},
|
||||
|
||||
Reference in New Issue
Block a user