matrix_sdk/sliding_sync/list/
builder.rs1use std::{
4 convert::identity,
5 fmt,
6 sync::{Arc, RwLock as StdRwLock},
7};
8
9use eyeball::{Observable, SharedObservable};
10use matrix_sdk_base::sliding_sync::http;
11use ruma::events::StateEventType;
12use tokio::sync::broadcast::Sender;
13
14use super::{
15 super::SlidingSyncInternalMessage, Bound, SlidingSyncList, SlidingSyncListCachePolicy,
16 SlidingSyncListInner, SlidingSyncListLoadingState, SlidingSyncListRequestGenerator,
17 SlidingSyncListStickyParameters, SlidingSyncMode,
18};
19use crate::{
20 sliding_sync::{cache::restore_sliding_sync_list, sticky_parameters::SlidingSyncStickyManager},
21 Client,
22};
23
24#[derive(Clone)]
26struct SlidingSyncListCachedData {
27 maximum_number_of_rooms: Option<u32>,
31}
32
33#[derive(Clone)]
35pub struct SlidingSyncListBuilder {
36 sync_mode: SlidingSyncMode,
37 required_state: Vec<(StateEventType, String)>,
38 include_heroes: Option<bool>,
39 filters: Option<http::request::ListFilters>,
40 timeline_limit: Bound,
41 pub(crate) name: String,
42
43 cache_policy: SlidingSyncListCachePolicy,
45
46 reloaded_cached_data: Option<SlidingSyncListCachedData>,
49
50 once_built: Arc<Box<dyn Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync>>,
51}
52
53#[cfg(not(tarpaulin_include))]
54impl fmt::Debug for SlidingSyncListBuilder {
55 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56 formatter
58 .debug_struct("SlidingSyncListBuilder")
59 .field("sync_mode", &self.sync_mode)
60 .field("required_state", &self.required_state)
61 .field("include_heroes", &self.include_heroes)
62 .field("filters", &self.filters)
63 .field("timeline_limit", &self.timeline_limit)
64 .field("name", &self.name)
65 .finish_non_exhaustive()
66 }
67}
68
69impl SlidingSyncListBuilder {
70 pub(super) fn new(name: impl Into<String>) -> Self {
71 Self {
72 sync_mode: SlidingSyncMode::default(),
73 required_state: vec![
74 (StateEventType::RoomEncryption, "".to_owned()),
75 (StateEventType::RoomTombstone, "".to_owned()),
76 ],
77 include_heroes: None,
78 filters: None,
79 timeline_limit: 1,
80 name: name.into(),
81 reloaded_cached_data: None,
82 cache_policy: SlidingSyncListCachePolicy::Disabled,
83 once_built: Arc::new(Box::new(identity)),
84 }
85 }
86
87 pub fn once_built<C>(mut self, callback: C) -> Self
93 where
94 C: Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync + 'static,
95 {
96 self.once_built = Arc::new(Box::new(callback));
97 self
98 }
99
100 pub fn sync_mode(mut self, value: impl Into<SlidingSyncMode>) -> Self {
102 self.sync_mode = value.into();
103 self
104 }
105
106 pub fn required_state(mut self, value: Vec<(StateEventType, String)>) -> Self {
108 self.required_state = value;
109 self
110 }
111
112 pub fn include_heroes(mut self, value: Option<bool>) -> Self {
114 self.include_heroes = value;
115 self
116 }
117
118 pub fn filters(mut self, value: Option<http::request::ListFilters>) -> Self {
120 self.filters = value;
121 self
122 }
123
124 pub fn timeline_limit(mut self, timeline_limit: Bound) -> Self {
126 self.timeline_limit = timeline_limit;
127 self
128 }
129
130 pub fn no_timeline_limit(mut self) -> Self {
132 self.timeline_limit = 0;
133 self
134 }
135
136 pub(in super::super) async fn set_cached_and_reload(
142 &mut self,
143 client: &Client,
144 storage_key: &str,
145 ) -> crate::Result<()> {
146 self.cache_policy = SlidingSyncListCachePolicy::Enabled;
147
148 if let Some(frozen_list) =
149 restore_sliding_sync_list(client.store(), storage_key, &self.name).await?
150 {
151 assert!(
152 self.reloaded_cached_data.is_none(),
153 "can't call `set_cached_and_reload` twice"
154 );
155 self.reloaded_cached_data = Some(SlidingSyncListCachedData {
156 maximum_number_of_rooms: frozen_list.maximum_number_of_rooms,
157 });
158 Ok(())
159 } else {
160 Ok(())
161 }
162 }
163
164 pub(in super::super) fn build(
166 self,
167 sliding_sync_internal_channel_sender: Sender<SlidingSyncInternalMessage>,
168 ) -> SlidingSyncList {
169 let list = SlidingSyncList {
170 inner: Arc::new(SlidingSyncListInner {
171 #[cfg(any(test, feature = "testing"))]
172 sync_mode: StdRwLock::new(self.sync_mode.clone()),
173
174 sticky: StdRwLock::new(SlidingSyncStickyManager::new(
176 SlidingSyncListStickyParameters::new(
177 self.required_state,
178 self.include_heroes,
179 self.filters,
180 ),
181 )),
182 timeline_limit: StdRwLock::new(self.timeline_limit),
183 name: self.name,
184 cache_policy: self.cache_policy,
185
186 request_generator: StdRwLock::new(SlidingSyncListRequestGenerator::new(
188 self.sync_mode,
189 )),
190
191 state: StdRwLock::new(Observable::new(Default::default())),
194 maximum_number_of_rooms: SharedObservable::new(None),
195
196 sliding_sync_internal_channel_sender,
198 }),
199 };
200
201 let once_built = self.once_built;
202
203 let list = once_built(list);
204
205 if let Some(SlidingSyncListCachedData { maximum_number_of_rooms }) =
213 self.reloaded_cached_data
214 {
215 Observable::set(
217 &mut list.inner.state.write().unwrap(),
218 SlidingSyncListLoadingState::Preloaded,
219 );
220
221 list.inner.maximum_number_of_rooms.set(maximum_number_of_rooms);
223 }
224
225 list
226 }
227}