matrix_sdk_ui/timeline/
threaded_events_loader.rs1use std::{fmt::Formatter, sync::Mutex};
16
17use matrix_sdk::{
18 event_cache::{
19 paginator::{PaginationResult, PaginatorError},
20 PaginationToken,
21 },
22 room::{IncludeRelations, RelationsOptions},
23};
24use ruma::{api::Direction, OwnedEventId, UInt};
25
26use super::traits::RoomDataProvider;
27
28pub struct ThreadedEventsLoader<P: RoomDataProvider> {
29 room: P,
30 root_event_id: OwnedEventId,
31 token: Mutex<PaginationToken>,
32}
33
34impl<P: RoomDataProvider> ThreadedEventsLoader<P> {
35 pub fn new(room: P, root_event_id: OwnedEventId) -> Self {
37 Self { room, root_event_id, token: Mutex::new(None.into()) }
38 }
39
40 pub async fn paginate_backwards(
41 &self,
42 num_events: UInt,
43 ) -> Result<PaginationResult, PaginatorError> {
44 let token = {
45 let token = self.token.lock().unwrap();
46
47 match &*token {
48 PaginationToken::None => None,
49 PaginationToken::HasMore(token) => Some(token.clone()),
50 PaginationToken::HitEnd => {
51 return Ok(PaginationResult { events: Vec::new(), hit_end_of_timeline: true });
52 }
53 }
54 };
55
56 let options = RelationsOptions {
57 from: token,
58 dir: Direction::Backward,
59 limit: Some(num_events),
60 include_relations: IncludeRelations::AllRelations,
61 recurse: true,
62 };
63
64 let mut result = self
65 .room
66 .relations(self.root_event_id.to_owned(), options)
67 .await
68 .map_err(|error| PaginatorError::SdkError(Box::new(error)))?;
69
70 let hit_end_of_timeline = result.next_batch_token.is_none();
71
72 {
74 let mut token = self.token.lock().unwrap();
75
76 *token = match result.next_batch_token {
77 Some(val) => PaginationToken::HasMore(val),
78 None => PaginationToken::HitEnd,
79 };
80 }
81
82 if hit_end_of_timeline {
84 let root_event =
85 self.room.load_event_with_relations(&self.root_event_id, None, None).await?.0;
86
87 result.chunk.push(root_event);
88 }
89
90 Ok(PaginationResult { events: result.chunk, hit_end_of_timeline })
91 }
92}
93
94#[cfg(not(tarpaulin_include))]
95impl<P: RoomDataProvider> std::fmt::Debug for ThreadedEventsLoader<P> {
96 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
97 f.debug_struct("ThreadedEventsLoader").finish()
98 }
99}