feat(sdk): Add TimelineStart virtual timeline item

This commit is contained in:
Jonas Platte
2023-01-06 13:39:22 +01:00
committed by Jonas Platte
parent 237edcd747
commit 9b3bf5a4fa
6 changed files with 60 additions and 6 deletions
+7
View File
@@ -160,6 +160,7 @@ impl TimelineItem {
}
Item::Virtual(VItem::ReadMarker) => Some(VirtualTimelineItem::ReadMarker),
Item::Virtual(VItem::LoadingIndicator) => Some(VirtualTimelineItem::LoadingIndicator),
Item::Virtual(VItem::TimelineStart) => Some(VirtualTimelineItem::TimelineStart),
Item::Event(_) => None,
}
}
@@ -596,6 +597,12 @@ pub enum VirtualTimelineItem {
/// A loading indicator for a pagination request.
LoadingIndicator,
/// The beginning of the visible timeline.
///
/// There might be earlier events the user is not allowed to see due to
/// history visibility.
TimelineStart,
}
#[extension_trait]
@@ -525,7 +525,10 @@ impl<'a, 'i> TimelineEventHandler<'a, 'i> {
// divider at position 1 and the new event at 2 rather than 0 and 1.
let offset =
match self.timeline_items.first().and_then(|item| item.as_virtual()) {
Some(VirtualTimelineItem::LoadingIndicator) => 1,
Some(
VirtualTimelineItem::LoadingIndicator
| VirtualTimelineItem::TimelineStart,
) => 1,
_ => 0,
};
+7 -3
View File
@@ -156,15 +156,19 @@ impl TimelineInner {
lock.insert_cloned(0, Arc::new(TimelineItem::loading_indicator()));
}
#[instrument(skip_all)]
pub(super) fn remove_loading_indicator(&self) {
#[instrument(skip(self))]
pub(super) fn remove_loading_indicator(&self, more_messages: bool) {
let mut lock = self.items.lock_mut();
if !lock.first().map_or(false, |item| item.is_loading_indicator()) {
warn!("There is no loading indicator");
return;
}
lock.remove(0);
if more_messages {
lock.remove(0);
} else {
lock.set_cloned(0, Arc::new(TimelineItem::timeline_start()))
}
}
pub(super) async fn handle_fully_read(&self, raw: Raw<FullyReadEvent>) {
+7 -2
View File
@@ -182,8 +182,9 @@ impl Timeline {
num_updates += self.inner.handle_back_paginated_event(room_ev, own_user_id).await;
}
self.inner.remove_loading_indicator();
let outcome = PaginationOutcome { more_messages: messages.end.is_some(), num_updates };
let more_messages = messages.end.is_some();
self.inner.remove_loading_indicator(more_messages);
let outcome = PaginationOutcome { more_messages, num_updates };
*start_lock = messages.end;
Ok(outcome)
@@ -343,6 +344,10 @@ impl TimelineItem {
Self::Virtual(VirtualTimelineItem::LoadingIndicator)
}
fn timeline_start() -> Self {
Self::Virtual(VirtualTimelineItem::TimelineStart)
}
fn is_read_marker(&self) -> bool {
matches!(self, Self::Virtual(VirtualTimelineItem::ReadMarker))
}
@@ -34,4 +34,10 @@ pub enum VirtualTimelineItem {
/// A loading indicator for a pagination request.
LoadingIndicator,
/// The beginning of the visible timeline.
///
/// There might be earlier events the user is not allowed to see due to
/// history visibility.
TimelineStart,
}
@@ -260,6 +260,7 @@ async fn back_pagination() {
.await;
timeline.paginate_backwards(uint!(10)).await.unwrap();
server.reset().await;
let loading = assert_matches!(
timeline_stream.next().await,
@@ -297,6 +298,34 @@ async fn back_pagination() {
// Removal of the loading indicator
assert_matches!(timeline_stream.next().await, Some(VecDiff::RemoveAt { index: 0 }));
Mock::given(method("GET"))
.and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$"))
.and(header("authorization", "Bearer 1234"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
// Usually there would be a few events here, but we just want to test
// that the timeline start item is added when there is no end token
"chunk": [],
"start": "t47409-4357353_219380_26003_2269"
})))
.expect(1)
.named("messages_batch_1")
.mount(&server)
.await;
timeline.paginate_backwards(uint!(10)).await.unwrap();
let loading = assert_matches!(
timeline_stream.next().await,
Some(VecDiff::InsertAt { index: 0, value }) => value
);
assert_matches!(loading.as_virtual().unwrap(), VirtualTimelineItem::LoadingIndicator);
let loading = assert_matches!(
timeline_stream.next().await,
Some(VecDiff::UpdateAt { index: 0, value }) => value
);
assert_matches!(loading.as_virtual().unwrap(), VirtualTimelineItem::TimelineStart);
}
#[async_test]