Skip to content

Commit 9c381c1

Browse files
committed
feat(ffi): expose a generic message_filtered_timeline that can be configured to only include RoomMessage type events and filter those further based on their message type.
Virtual timeline items will still be provided and the `default_event_filter` will be applied before everything else. Instances of these timelines will be used to power the 2 different tabs shown on the new media browser. The client will be responsible for interacting with it similar to a normal timeline and transforming its data into something renderable e.g. section by date separators (which will be made configurable in a follow up PR)
1 parent 9002f82 commit 9c381c1

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

bindings/matrix-sdk-ffi/src/event.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use matrix_sdk::IdParseError;
33
use matrix_sdk_ui::timeline::TimelineEventItemId;
44
use ruma::{
55
events::{
6-
room::{message::Relation, redaction::SyncRoomRedactionEvent},
6+
room::{
7+
message::{MessageType as RumaMessageType, Relation},
8+
redaction::SyncRoomRedactionEvent,
9+
},
710
AnySyncMessageLikeEvent, AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent,
811
MessageLikeEventContent as RumaMessageLikeEventContent, RedactContent,
912
RedactedStateEventContent, StaticStateEventContent, SyncMessageLikeEvent, SyncStateEvent,
@@ -356,6 +359,39 @@ impl From<MessageLikeEventType> for ruma::events::MessageLikeEventType {
356359
}
357360
}
358361

362+
#[derive(Debug, PartialEq, Clone, uniffi::Enum)]
363+
pub enum RoomMessageEventMessageType {
364+
Audio,
365+
Emote,
366+
File,
367+
Image,
368+
Location,
369+
Notice,
370+
ServerNotice,
371+
Text,
372+
Video,
373+
VerificationRequest,
374+
Other,
375+
}
376+
377+
impl From<RumaMessageType> for RoomMessageEventMessageType {
378+
fn from(val: ruma::events::room::message::MessageType) -> Self {
379+
match val {
380+
RumaMessageType::Audio { .. } => Self::Audio,
381+
RumaMessageType::Emote { .. } => Self::Emote,
382+
RumaMessageType::File { .. } => Self::File,
383+
RumaMessageType::Image { .. } => Self::Image,
384+
RumaMessageType::Location { .. } => Self::Location,
385+
RumaMessageType::Notice { .. } => Self::Notice,
386+
RumaMessageType::ServerNotice { .. } => Self::ServerNotice,
387+
RumaMessageType::Text { .. } => Self::Text,
388+
RumaMessageType::Video { .. } => Self::Video,
389+
RumaMessageType::VerificationRequest { .. } => Self::VerificationRequest,
390+
_ => Self::Other,
391+
}
392+
}
393+
}
394+
359395
/// Contains the 2 possible identifiers of an event, either it has a remote
360396
/// event id or a local transaction id, never both or none.
361397
#[derive(Clone, uniffi::Enum)]

bindings/matrix-sdk-ffi/src/room.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use matrix_sdk::{
1111
ComposerDraft as SdkComposerDraft, ComposerDraftType as SdkComposerDraftType,
1212
RoomHero as SdkRoomHero, RoomMemberships, RoomState,
1313
};
14-
use matrix_sdk_ui::timeline::{PaginationError, RoomExt, TimelineFocus};
14+
use matrix_sdk_ui::timeline::{default_event_filter, PaginationError, RoomExt, TimelineFocus};
1515
use mime::Mime;
1616
use ruma::{
1717
api::client::room::report_content,
@@ -23,7 +23,7 @@ use ruma::{
2323
message::RoomMessageEventContentWithoutRelation,
2424
power_levels::RoomPowerLevels as RumaPowerLevels, MediaSource,
2525
},
26-
TimelineEventType,
26+
AnyMessageLikeEventContent, AnySyncTimelineEvent, TimelineEventType,
2727
},
2828
EventId, Int, OwnedDeviceId, OwnedUserId, RoomAliasId, UserId,
2929
};
@@ -34,7 +34,7 @@ use super::RUNTIME;
3434
use crate::{
3535
chunk_iterator::ChunkIterator,
3636
error::{ClientError, MediaInfoError, RoomError},
37-
event::{MessageLikeEventType, StateEventType},
37+
event::{MessageLikeEventType, RoomMessageEventMessageType, StateEventType},
3838
identity_status_change::IdentityStatusChange,
3939
room_info::RoomInfo,
4040
room_member::RoomMember,
@@ -260,6 +260,48 @@ impl Room {
260260
Ok(Timeline::new(timeline))
261261
}
262262

263+
/// A timeline instance that can be configured to only include RoomMessage
264+
/// type events and filter those further based on their message type.
265+
///
266+
/// Virtual timeline items will still be provided and the
267+
/// `default_event_filter` will be applied before everything else.
268+
///
269+
/// # Arguments
270+
///
271+
/// * `internal_id_prefix` - An optional String that will be prepended to
272+
/// all the timeline item's internal IDs, making it possible to
273+
/// distinguish different timeline instances from each other.
274+
///
275+
/// * `allowed_message_types` - A list of `RoomMessageEventMessageType` that
276+
/// will be allowed to appear in the timeline
277+
pub async fn message_filtered_timeline(
278+
&self,
279+
internal_id_prefix: Option<String>,
280+
allowed_message_types: Vec<RoomMessageEventMessageType>,
281+
) -> Result<Arc<Timeline>, ClientError> {
282+
let mut builder = matrix_sdk_ui::timeline::Timeline::builder(&self.inner);
283+
284+
if let Some(internal_id_prefix) = internal_id_prefix {
285+
builder = builder.with_internal_id_prefix(internal_id_prefix);
286+
}
287+
288+
builder = builder.event_filter(move |event, room_version_id| {
289+
default_event_filter(event, room_version_id)
290+
&& match event {
291+
AnySyncTimelineEvent::MessageLike(msg) => match msg.original_content() {
292+
Some(AnyMessageLikeEventContent::RoomMessage(content)) => {
293+
allowed_message_types.contains(&content.msgtype.into())
294+
}
295+
_ => false,
296+
},
297+
_ => false,
298+
}
299+
});
300+
301+
let timeline = builder.build().await?;
302+
Ok(Timeline::new(timeline))
303+
}
304+
263305
pub fn is_encrypted(&self) -> Result<bool, ClientError> {
264306
Ok(RUNTIME.block_on(self.inner.is_encrypted())?)
265307
}

0 commit comments

Comments
 (0)