matrix_sdk/sliding_sync/list/
builder.rs1use std::{
4 convert::identity,
5 fmt,
6 sync::{Arc, RwLock as StdRwLock},
7};
8
9use eyeball::SharedObservable;
10use ruma::{api::client::sync::sync_events::v5 as http, events::StateEventType};
11use tokio::sync::broadcast::Sender;
12
13use super::{
14 super::{SlidingSyncInternalMessage, cache::restore_sliding_sync_list},
15 Bound, PollTimeout, SlidingSyncList, SlidingSyncListCachePolicy, SlidingSyncListInner,
16 SlidingSyncListLoadingState, SlidingSyncListRequestGenerator, SlidingSyncMode,
17};
18use crate::Client;
19
20#[derive(Clone)]
22struct SlidingSyncListCachedData {
23 maximum_number_of_rooms: Option<u32>,
27}
28
29#[derive(Clone)]
31pub struct SlidingSyncListBuilder {
32 sync_mode: SlidingSyncMode,
33 #[cfg(not(target_family = "wasm"))]
34 requires_timeout: Arc<dyn Fn(&SlidingSyncListRequestGenerator) -> PollTimeout + Send + Sync>,
35 #[cfg(target_family = "wasm")]
36 requires_timeout: Arc<dyn Fn(&SlidingSyncListRequestGenerator) -> PollTimeout>,
37 required_state: Vec<(StateEventType, String)>,
38 filters: Option<http::request::ListFilters>,
39 timeline_limit: Bound,
40 pub(crate) name: String,
41
42 cache_policy: SlidingSyncListCachePolicy,
44
45 reloaded_cached_data: Option<SlidingSyncListCachedData>,
48
49 #[cfg(not(target_family = "wasm"))]
50 once_built: Arc<Box<dyn Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync>>,
51 #[cfg(target_family = "wasm")]
52 once_built: Arc<Box<dyn Fn(SlidingSyncList) -> SlidingSyncList>>,
53}
54
55#[cfg(not(tarpaulin_include))]
56impl fmt::Debug for SlidingSyncListBuilder {
57 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58 formatter
60 .debug_struct("SlidingSyncListBuilder")
61 .field("sync_mode", &self.sync_mode)
62 .field("required_state", &self.required_state)
63 .field("filters", &self.filters)
64 .field("timeline_limit", &self.timeline_limit)
65 .field("name", &self.name)
66 .finish_non_exhaustive()
67 }
68}
69
70impl SlidingSyncListBuilder {
71 pub(super) fn new(name: impl Into<String>) -> Self {
72 Self {
73 sync_mode: SlidingSyncMode::default(),
74 requires_timeout: Arc::new(|request_generator| {
75 if request_generator.is_fully_loaded() {
76 PollTimeout::Default
77 } else {
78 PollTimeout::None
79 }
80 }),
81 required_state: vec![
82 (StateEventType::RoomEncryption, "".to_owned()),
83 (StateEventType::RoomTombstone, "".to_owned()),
84 ],
85 filters: None,
86 timeline_limit: 1,
87 name: name.into(),
88 reloaded_cached_data: None,
89 cache_policy: SlidingSyncListCachePolicy::Disabled,
90 once_built: Arc::new(Box::new(identity)),
91 }
92 }
93
94 #[cfg(not(target_family = "wasm"))]
100 pub fn once_built<C>(mut self, callback: C) -> Self
101 where
102 C: Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync + 'static,
103 {
104 self.once_built = Arc::new(Box::new(callback));
105 self
106 }
107
108 #[cfg(target_family = "wasm")]
114 pub fn once_built<C>(mut self, callback: C) -> Self
115 where
116 C: Fn(SlidingSyncList) -> SlidingSyncList + 'static,
117 {
118 self.once_built = Arc::new(Box::new(callback));
119 self
120 }
121
122 pub fn sync_mode(mut self, value: impl Into<SlidingSyncMode>) -> Self {
124 self.sync_mode = value.into();
125 self
126 }
127
128 #[cfg(not(target_family = "wasm"))]
134 pub fn requires_timeout<F>(mut self, f: F) -> Self
135 where
136 F: Fn(&SlidingSyncListRequestGenerator) -> PollTimeout + Send + Sync + 'static,
137 {
138 self.requires_timeout = Arc::new(f);
139 self
140 }
141
142 #[cfg(target_family = "wasm")]
148 pub fn requires_timeout<F>(mut self, f: F) -> Self
149 where
150 F: Fn(&SlidingSyncListRequestGenerator) -> PollTimeout + 'static,
151 {
152 self.requires_timeout = Arc::new(f);
153 self
154 }
155
156 pub fn required_state(mut self, value: Vec<(StateEventType, String)>) -> Self {
158 self.required_state = value;
159 self
160 }
161
162 pub fn filters(mut self, value: Option<http::request::ListFilters>) -> Self {
164 self.filters = value;
165 self
166 }
167
168 pub fn timeline_limit(mut self, timeline_limit: Bound) -> Self {
170 self.timeline_limit = timeline_limit;
171 self
172 }
173
174 pub fn no_timeline_limit(mut self) -> Self {
176 self.timeline_limit = 0;
177 self
178 }
179
180 pub(in super::super) async fn set_cached_and_reload(
186 &mut self,
187 client: &Client,
188 storage_key: &str,
189 ) -> crate::Result<()> {
190 self.cache_policy = SlidingSyncListCachePolicy::Enabled;
191
192 if let Some(frozen_list) =
193 restore_sliding_sync_list(client.state_store(), storage_key, &self.name).await?
194 {
195 assert!(
196 self.reloaded_cached_data.is_none(),
197 "can't call `set_cached_and_reload` twice"
198 );
199 self.reloaded_cached_data = Some(SlidingSyncListCachedData {
200 maximum_number_of_rooms: frozen_list.maximum_number_of_rooms,
201 });
202 Ok(())
203 } else {
204 Ok(())
205 }
206 }
207
208 pub(in super::super) fn build(
210 self,
211 sliding_sync_internal_channel_sender: Sender<SlidingSyncInternalMessage>,
212 ) -> SlidingSyncList {
213 let list = SlidingSyncList {
214 inner: Arc::new(SlidingSyncListInner {
215 #[cfg(any(test, feature = "testing"))]
216 sync_mode: StdRwLock::new(self.sync_mode.clone()),
217
218 filters: self.filters,
220 required_state: self.required_state,
221 timeline_limit: StdRwLock::new(self.timeline_limit),
222 name: self.name,
223 cache_policy: self.cache_policy,
224 requires_timeout: self.requires_timeout,
225
226 request_generator: StdRwLock::new(SlidingSyncListRequestGenerator::new(
228 self.sync_mode,
229 )),
230
231 state: SharedObservable::new(Default::default()),
234 maximum_number_of_rooms: SharedObservable::new(None),
235
236 sliding_sync_internal_channel_sender,
238 }),
239 };
240
241 let once_built = self.once_built;
242
243 let list = once_built(list);
244
245 if let Some(SlidingSyncListCachedData { maximum_number_of_rooms }) =
253 self.reloaded_cached_data
254 {
255 list.inner.state.set(SlidingSyncListLoadingState::Preloaded);
257
258 list.inner.maximum_number_of_rooms.set(maximum_number_of_rooms);
260 }
261
262 list
263 }
264}