Skip to content

Commit

Permalink
timeline: add the ability to set a prefix for internal IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjbvr committed Apr 23, 2024
1 parent e4331ac commit d986437
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 25 deletions.
8 changes: 8 additions & 0 deletions bindings/matrix-sdk-ffi/src/room_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,9 +537,13 @@ impl RoomListItem {
/// * `event_type_filter` - An optional [`TimelineEventTypeFilter`] to be
/// used to filter timeline events besides the default timeline filter. If
/// `None` is passed, only the default timeline filter will be used.
/// * `internal_id_prefix` - An optional String that will be prepended to
/// all the timeline item's internal IDs, making it possible to
/// distinguish different timeline instances from each other.
async fn init_timeline(
&self,
event_type_filter: Option<Arc<TimelineEventTypeFilter>>,
internal_id_prefix: Option<String>,
) -> Result<(), RoomListError> {
let mut timeline_builder = self
.inner
Expand All @@ -554,6 +558,10 @@ impl RoomListItem {
});
}

if let Some(internal_id_prefix) = internal_id_prefix {
timeline_builder = timeline_builder.with_internal_id_prefix(internal_id_prefix);
}

if let Some(utd_hook) = self.utd_hook.clone() {
timeline_builder = timeline_builder.with_unable_to_decrypt_hook(utd_hook);
}
Expand Down
18 changes: 16 additions & 2 deletions crates/matrix-sdk-ui/src/timeline/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ pub struct TimelineBuilder {
/// An optional hook to call whenever we run into an unable-to-decrypt or a
/// late-decryption event.
unable_to_decrypt_hook: Option<Arc<UtdHookManager>>,

/// An optional prefix for internal IDs.
internal_id_prefix: Option<String>,
}

impl TimelineBuilder {
Expand All @@ -53,6 +56,7 @@ impl TimelineBuilder {
room: room.clone(),
settings: TimelineInnerSettings::default(),
unable_to_decrypt_hook: None,
internal_id_prefix: None,
}
}

Expand All @@ -65,6 +69,15 @@ impl TimelineBuilder {
self
}

/// Sets the internal id prefix for this timeline.
///
/// The prefix will be prepended to any internal ID using when generating
/// timeline IDs for this timeline.
pub fn with_internal_id_prefix(mut self, prefix: String) -> Self {
self.internal_id_prefix = Some(prefix);
self
}

/// Enable tracking of the fully-read marker and the read receipts on the
/// timeline.
pub fn track_read_marker_and_receipts(mut self) -> Self {
Expand Down Expand Up @@ -122,7 +135,7 @@ impl TimelineBuilder {
)
)]
pub async fn build(self) -> event_cache::Result<Timeline> {
let Self { room, settings, unable_to_decrypt_hook } = self;
let Self { room, settings, unable_to_decrypt_hook, internal_id_prefix } = self;

let client = room.client();
let event_cache = client.event_cache();
Expand All @@ -135,7 +148,8 @@ impl TimelineBuilder {

let has_events = !events.is_empty();

let inner = TimelineInner::new(room, unable_to_decrypt_hook).with_settings(settings);
let inner = TimelineInner::new(room, internal_id_prefix, unable_to_decrypt_hook)
.with_settings(settings);

inner.replace_with_initial_events(events).await;

Expand Down
4 changes: 2 additions & 2 deletions crates/matrix-sdk-ui/src/timeline/day_dividers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ mod tests {
let mut items = ObservableVector::new();
let mut txn = items.transaction();

let mut meta = TimelineInnerMetadata::new(ruma::RoomVersionId::V11, None);
let mut meta = TimelineInnerMetadata::new(ruma::RoomVersionId::V11, None, None);

let timestamp = MilliSecondsSinceUnixEpoch(uint!(42));
let timestamp_next_day =
Expand Down Expand Up @@ -607,7 +607,7 @@ mod tests {
let mut items = ObservableVector::new();
let mut txn = items.transaction();

let mut meta = TimelineInnerMetadata::new(ruma::RoomVersionId::V11, None);
let mut meta = TimelineInnerMetadata::new(ruma::RoomVersionId::V11, None, None);

let timestamp = MilliSecondsSinceUnixEpoch(uint!(42));
let timestamp_next_day =
Expand Down
8 changes: 6 additions & 2 deletions crates/matrix-sdk-ui/src/timeline/inner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,14 @@ pub fn default_event_filter(event: &AnySyncTimelineEvent, room_version: &RoomVer
impl<P: RoomDataProvider> TimelineInner<P> {
pub(super) fn new(
room_data_provider: P,
internal_id_prefix: Option<String>,
unable_to_decrypt_hook: Option<Arc<UtdHookManager>>,
) -> Self {
let state =
TimelineInnerState::new(room_data_provider.room_version(), unable_to_decrypt_hook);
let state = TimelineInnerState::new(
room_data_provider.room_version(),
internal_id_prefix,
unable_to_decrypt_hook,
);
Self {
state: Arc::new(RwLock::new(state)),
room_data_provider,
Expand Down
16 changes: 14 additions & 2 deletions crates/matrix-sdk-ui/src/timeline/inner/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,19 @@ pub(in crate::timeline) struct TimelineInnerState {
impl TimelineInnerState {
pub(super) fn new(
room_version: RoomVersionId,
internal_id_prefix: Option<String>,
unable_to_decrypt_hook: Option<Arc<UtdHookManager>>,
) -> Self {
Self {
// Upstream default capacity is currently 16, which is making
// sliding-sync tests with 20 events lag. This should still be
// small enough.
items: ObservableVector::with_capacity(32),
meta: TimelineInnerMetadata::new(room_version, unable_to_decrypt_hook),
meta: TimelineInnerMetadata::new(
room_version,
internal_id_prefix,
unable_to_decrypt_hook,
),
}
}

Expand Down Expand Up @@ -678,6 +683,10 @@ pub(in crate::timeline) struct TimelineInnerMetadata {
/// remote echoes.
next_internal_id: u64,

/// An optional prefix for internal IDs, defined during construction of the
/// timeline.
internal_id_prefix: Option<String>,

pub reactions: Reactions,
pub poll_pending_events: PollPendingEvents,
pub fully_read_event: Option<OwnedEventId>,
Expand Down Expand Up @@ -707,6 +716,7 @@ pub(in crate::timeline) struct TimelineInnerMetadata {
impl TimelineInnerMetadata {
pub(crate) fn new(
room_version: RoomVersionId,
internal_id_prefix: Option<String>,
unable_to_decrypt_hook: Option<Arc<UtdHookManager>>,
) -> Self {
Self {
Expand All @@ -723,6 +733,7 @@ impl TimelineInnerMetadata {
in_flight_reaction: Default::default(),
room_version,
unable_to_decrypt_hook,
internal_id_prefix,
}
}

Expand Down Expand Up @@ -760,7 +771,8 @@ impl TimelineInnerMetadata {
pub fn next_internal_id(&mut self) -> String {
let val = self.next_internal_id;
self.next_internal_id += 1;
format!("{val}")
let prefix = self.internal_id_prefix.as_deref().unwrap_or("");
format!("{prefix}{val}")
}

/// Returns a new timeline item with a fresh internal id.
Expand Down
52 changes: 37 additions & 15 deletions crates/matrix-sdk-ui/src/timeline/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,21 +268,10 @@ async fn test_dedup_pagination() {
async fn test_dedup_initial() {
let timeline = TestTimeline::new();

let event_a = SyncTimelineEvent::new(
timeline
.event_builder
.make_sync_message_event(*ALICE, RoomMessageEventContent::text_plain("A")),
);
let event_b = SyncTimelineEvent::new(
timeline
.event_builder
.make_sync_message_event(*BOB, RoomMessageEventContent::text_plain("B")),
);
let event_c = SyncTimelineEvent::new(
timeline
.event_builder
.make_sync_message_event(*CAROL, RoomMessageEventContent::text_plain("C")),
);
let factory = EventFactory::new();
let event_a = factory.text_msg("A").sender(*ALICE).into_sync();
let event_b = factory.text_msg("B").sender(*BOB).into_sync();
let event_c = factory.text_msg("C").sender(*CAROL).into_sync();

timeline
.inner
Expand Down Expand Up @@ -322,6 +311,39 @@ async fn test_dedup_initial() {
assert_eq!(timeline_items[0].unique_id(), "3");
}

#[async_test]
async fn test_internal_id_prefix() {
let timeline = TestTimeline::with_internal_id_prefix("le_prefix_".to_owned());

let factory = EventFactory::new();
let ev_a = factory.text_msg("A").sender(*ALICE).into_sync();
let ev_b = factory.text_msg("B").sender(*BOB).into_sync();
let ev_c = factory.text_msg("C").sender(*CAROL).into_sync();

timeline
.inner
.add_events_at(vec![ev_a, ev_b, ev_c], TimelineEnd::Back { from_cache: false })
.await;

let timeline_items = timeline.inner.items().await;
assert_eq!(timeline_items.len(), 4);

assert!(timeline_items[0].is_day_divider());
assert_eq!(timeline_items[0].unique_id(), "le_prefix_3");

let event1 = &timeline_items[1];
assert_eq!(event1.as_event().unwrap().sender(), *ALICE);
assert_eq!(event1.unique_id(), "le_prefix_0");

let event2 = &timeline_items[2];
assert_eq!(event2.as_event().unwrap().sender(), *BOB);
assert_eq!(event2.unique_id(), "le_prefix_1");

let event3 = &timeline_items[3];
assert_eq!(event3.as_event().unwrap().sender(), *CAROL);
assert_eq!(event3.unique_id(), "le_prefix_2");
}

#[async_test]
async fn test_sanitized() {
let timeline = TestTimeline::new();
Expand Down
11 changes: 9 additions & 2 deletions crates/matrix-sdk-ui/src/timeline/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,23 @@ impl TestTimeline {
Self::with_room_data_provider(TestRoomDataProvider::default())
}

fn with_internal_id_prefix(prefix: String) -> Self {
Self {
inner: TimelineInner::new(TestRoomDataProvider::default(), Some(prefix), None),
event_builder: EventBuilder::new(),
}
}

fn with_room_data_provider(room_data_provider: TestRoomDataProvider) -> Self {
Self {
inner: TimelineInner::new(room_data_provider, None),
inner: TimelineInner::new(room_data_provider, None, None),
event_builder: EventBuilder::new(),
}
}

fn with_unable_to_decrypt_hook(hook: Arc<UtdHookManager>) -> Self {
Self {
inner: TimelineInner::new(TestRoomDataProvider::default(), Some(hook)),
inner: TimelineInner::new(TestRoomDataProvider::default(), None, Some(hook)),
event_builder: EventBuilder::new(),
}
}
Expand Down

0 comments on commit d986437

Please sign in to comment.