matrix-rust-sdk/crates/matrix-sdk/src/sliding_sync/list/builder.rs

216 lines
7.1 KiB
Rust

//! Builder for [`SlidingSyncList`].
use std::{
convert::identity,
fmt,
sync::{Arc, RwLock as StdRwLock},
};
use eyeball::unique::Observable;
use eyeball_im::ObservableVector;
use ruma::{api::client::sync::sync_events::v4, events::StateEventType, UInt};
use tokio::sync::mpsc::Sender;
use super::{
super::SlidingSyncInternalMessage, SlidingSyncList, SlidingSyncListInner,
SlidingSyncListRequestGenerator, SlidingSyncMode, SlidingSyncState,
};
/// The default name for the full sync list.
pub const FULL_SYNC_LIST_NAME: &str = "full-sync";
/// Builder for [`SlidingSyncList`].
#[derive(Clone)]
pub struct SlidingSyncListBuilder {
sync_mode: SlidingSyncMode,
sort: Vec<String>,
required_state: Vec<(StateEventType, String)>,
full_sync_batch_size: u32,
full_sync_maximum_number_of_rooms_to_fetch: Option<u32>,
filters: Option<v4::SyncRequestListFilters>,
timeline_limit: Option<UInt>,
name: String,
ranges: Vec<(UInt, UInt)>,
once_built: Arc<Box<dyn Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync>>,
}
// Print debug values for the builder, except `once_built` which is ignored.
impl fmt::Debug for SlidingSyncListBuilder {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("SlidingSyncListBuilder")
.field("sync_mode", &self.sync_mode)
.field("sort", &self.sort)
.field("required_state", &self.required_state)
.field("full_sync_batch_size", &self.full_sync_batch_size)
.field(
"full_sync_maximum_number_of_rooms_to_fetch",
&self.full_sync_maximum_number_of_rooms_to_fetch,
)
.field("filters", &self.filters)
.field("timeline_limit", &self.timeline_limit)
.field("name", &self.name)
.field("ranges", &self.ranges)
.finish_non_exhaustive()
}
}
impl SlidingSyncListBuilder {
pub(super) fn new(name: impl Into<String>) -> Self {
Self {
sync_mode: SlidingSyncMode::default(),
sort: vec!["by_recency".to_owned(), "by_name".to_owned()],
required_state: vec![
(StateEventType::RoomEncryption, "".to_owned()),
(StateEventType::RoomTombstone, "".to_owned()),
],
full_sync_batch_size: 20,
full_sync_maximum_number_of_rooms_to_fetch: None,
filters: None,
timeline_limit: None,
name: name.into(),
ranges: Vec::new(),
once_built: Arc::new(Box::new(identity)),
}
}
/// foo
pub fn once_built<C>(mut self, callback: C) -> Self
where
C: Fn(SlidingSyncList) -> SlidingSyncList + Send + Sync + 'static,
{
self.once_built = Arc::new(Box::new(callback));
self
}
/// Create a Builder set up for full sync.
pub fn default_with_fullsync() -> Self {
Self::new(FULL_SYNC_LIST_NAME).sync_mode(SlidingSyncMode::Paging)
}
/// Which SlidingSyncMode to start this list under.
pub fn sync_mode(mut self, value: SlidingSyncMode) -> Self {
self.sync_mode = value;
self
}
/// Sort the room list by this.
pub fn sort(mut self, value: Vec<String>) -> Self {
self.sort = value;
self
}
/// Required states to return per room.
pub fn required_state(mut self, value: Vec<(StateEventType, String)>) -> Self {
self.required_state = value;
self
}
/// When doing a full-sync, this method defines the value by which ranges of
/// rooms will be extended.
pub fn full_sync_batch_size(mut self, value: u32) -> Self {
self.full_sync_batch_size = value;
self
}
/// When doing a full-sync, this method defines the total limit of rooms to
/// load (it can be useful for gigantic accounts).
pub fn full_sync_maximum_number_of_rooms_to_fetch(
mut self,
value: impl Into<Option<u32>>,
) -> Self {
self.full_sync_maximum_number_of_rooms_to_fetch = value.into();
self
}
/// Any filters to apply to the query.
pub fn filters(mut self, value: Option<v4::SyncRequestListFilters>) -> Self {
self.filters = value;
self
}
/// Set the limit of regular events to fetch for the timeline.
pub fn timeline_limit<U: Into<UInt>>(mut self, timeline_limit: U) -> Self {
self.timeline_limit = Some(timeline_limit.into());
self
}
/// Reset the limit of regular events to fetch for the timeline. It is left
/// to the server to decide how many to send back
pub fn no_timeline_limit(mut self) -> Self {
self.timeline_limit = Default::default();
self
}
/// Set the ranges to fetch.
pub fn ranges<U: Into<UInt>>(mut self, range: Vec<(U, U)>) -> Self {
self.ranges = range.into_iter().map(|(a, b)| (a.into(), b.into())).collect();
self
}
/// Set a single range fetch.
pub fn set_range<U: Into<UInt>>(mut self, from: U, to: U) -> Self {
self.ranges = vec![(from.into(), to.into())];
self
}
/// Set the ranges to fetch.
pub fn add_range<U: Into<UInt>>(mut self, from: U, to: U) -> Self {
self.ranges.push((from.into(), to.into()));
self
}
/// Set the ranges to fetch.
pub fn reset_ranges(mut self) -> Self {
self.ranges.clear();
self
}
/// Build the list.
pub(in super::super) fn build(
self,
sliding_sync_internal_channel_sender: Sender<SlidingSyncInternalMessage>,
) -> SlidingSyncList {
let request_generator = match &self.sync_mode {
SlidingSyncMode::Paging => SlidingSyncListRequestGenerator::new_paging(
self.full_sync_batch_size,
self.full_sync_maximum_number_of_rooms_to_fetch,
),
SlidingSyncMode::Growing => SlidingSyncListRequestGenerator::new_growing(
self.full_sync_batch_size,
self.full_sync_maximum_number_of_rooms_to_fetch,
),
SlidingSyncMode::Selective => SlidingSyncListRequestGenerator::new_selective(),
};
let list = SlidingSyncList {
inner: Arc::new(SlidingSyncListInner {
// From the builder
sync_mode: self.sync_mode,
sort: self.sort,
required_state: self.required_state,
filters: self.filters,
timeline_limit: StdRwLock::new(Observable::new(self.timeline_limit)),
name: self.name,
ranges: StdRwLock::new(Observable::new(self.ranges)),
// Computed from the builder.
request_generator: StdRwLock::new(request_generator),
// Default values for the type we are building.
state: StdRwLock::new(Observable::new(SlidingSyncState::default())),
maximum_number_of_rooms: StdRwLock::new(Observable::new(None)),
room_list: StdRwLock::new(ObservableVector::new()),
sliding_sync_internal_channel_sender,
}),
};
let once_built = self.once_built;
once_built(list)
}
}