diff --git a/src/windows/mod.rs b/src/windows/mod.rs index e5e5df2..493bb17 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -1,4 +1,5 @@ use std::cmp::{Ord, Ordering, PartialOrd}; +use std::time::{Duration, Instant}; use matrix_sdk::{ encryption::verification::{format_emojis, SasVerification}, @@ -77,6 +78,8 @@ use self::{room::RoomState, welcome::WelcomeState}; pub mod room; pub mod welcome; +const MEMBER_FETCH_DEBOUNCE: Duration = Duration::from_secs(5); + #[inline] fn bold_style() -> Style { Style::default().add_modifier(StyleModifier::BOLD) @@ -211,7 +214,7 @@ macro_rules! delegate { match $s { IambWindow::Room($id) => $e, IambWindow::DirectList($id) => $e, - IambWindow::MemberList($id, _) => $e, + IambWindow::MemberList($id, _, _) => $e, IambWindow::RoomList($id) => $e, IambWindow::SpaceList($id) => $e, IambWindow::VerifyList($id) => $e, @@ -222,7 +225,7 @@ macro_rules! delegate { pub enum IambWindow { DirectList(DirectListState), - MemberList(MemberListState, OwnedRoomId), + MemberList(MemberListState, OwnedRoomId, Option), Room(RoomState), VerifyList(VerifyListState), RoomList(RoomListState), @@ -392,10 +395,18 @@ impl WindowOps for IambWindow { .focus(focused) .render(area, buf, state); }, - IambWindow::MemberList(state, room_id) => { - if let Ok(mems) = store.application.worker.members(room_id.clone()) { - let items = mems.into_iter().map(MemberItem::new); - state.set(items.collect()); + IambWindow::MemberList(state, room_id, last_fetch) => { + let need_fetch = match last_fetch { + Some(i) => i.elapsed() >= MEMBER_FETCH_DEBOUNCE, + None => true, + }; + + if need_fetch { + if let Ok(mems) = store.application.worker.members(room_id.clone()) { + let items = mems.into_iter().map(MemberItem::new); + state.set(items.collect()); + *last_fetch = Some(Instant::now()); + } } List::new(store) @@ -456,8 +467,8 @@ impl WindowOps for IambWindow { match self { IambWindow::Room(w) => w.dup(store).into(), IambWindow::DirectList(w) => w.dup(store).into(), - IambWindow::MemberList(w, room_id) => { - IambWindow::MemberList(w.dup(store), room_id.clone()) + IambWindow::MemberList(w, room_id, last_fetch) => { + IambWindow::MemberList(w.dup(store), room_id.clone(), *last_fetch) }, IambWindow::RoomList(w) => w.dup(store).into(), IambWindow::SpaceList(w) => w.dup(store).into(), @@ -497,7 +508,7 @@ impl Window for IambWindow { match self { IambWindow::Room(room) => IambId::Room(room.id().to_owned()), IambWindow::DirectList(_) => IambId::DirectList, - IambWindow::MemberList(_, room_id) => IambId::MemberList(room_id.clone()), + IambWindow::MemberList(_, room_id, _) => IambId::MemberList(room_id.clone()), IambWindow::RoomList(_) => IambId::RoomList, IambWindow::SpaceList(_) => IambId::SpaceList, IambWindow::VerifyList(_) => IambId::VerifyList, @@ -518,7 +529,7 @@ impl Window for IambWindow { Spans::from(title) }, - IambWindow::MemberList(_, room_id) => { + IambWindow::MemberList(_, room_id, _) => { let title = store.application.get_room_title(room_id.as_ref()); Spans(vec![bold_span("Room Members: "), title.into()]) @@ -535,7 +546,7 @@ impl Window for IambWindow { IambWindow::Welcome(_) => bold_spans("Welcome to iamb"), IambWindow::Room(w) => w.get_title(store), - IambWindow::MemberList(_, room_id) => { + IambWindow::MemberList(_, room_id, _) => { let title = store.application.get_room_title(room_id.as_ref()); Spans(vec![bold_span("Room Members: "), title.into()]) @@ -559,7 +570,7 @@ impl Window for IambWindow { IambId::MemberList(room_id) => { let id = IambBufferId::MemberList(room_id.clone()); let list = MemberListState::new(id, vec![]); - let win = IambWindow::MemberList(list, room_id); + let win = IambWindow::MemberList(list, room_id, None); return Ok(win); }, diff --git a/src/worker.rs b/src/worker.rs index c840293..f7f6cc5 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -14,13 +14,14 @@ use tokio::task::JoinHandle; use tracing::{error, warn}; use matrix_sdk::{ - config::{RequestConfig, StoreConfig, SyncSettings}, + config::{RequestConfig, SyncSettings}, encryption::verification::{SasVerification, Verification}, event_handler::Ctx, reqwest, room::{Invited, Messages, MessagesOptions, Room as MatrixRoom, RoomMember}, ruma::{ api::client::{ + filter::{FilterDefinition, LazyLoadOptions, RoomEventFilter, RoomFilter}, room::create_room::v3::{CreationContent, Request as CreateRoomRequest, RoomPreset}, room::Visibility, space::get_hierarchy::v1::Request as SpaceHierarchyRequest, @@ -557,7 +558,6 @@ impl ClientWorker { let client = Client::builder() .http_client(Arc::new(http)) .homeserver_url(account.url.clone()) - .store_config(StoreConfig::default()) .sled_store(settings.matrix_dir.as_path(), None) .expect("Failed to setup up sled store for Matrix SDK") .request_config(req_config) @@ -967,10 +967,19 @@ impl ClientWorker { self.sync_handle = Some(handle); - self.client - .sync_once(SyncSettings::default()) - .await - .map_err(IambError::from)?; + // Perform an initial, lazily-loaded sync. + let mut room = RoomEventFilter::default(); + room.lazy_load_options = LazyLoadOptions::Enabled { include_redundant_members: false }; + + let mut room_ev = RoomFilter::default(); + room_ev.state = room; + + let mut filter = FilterDefinition::default(); + filter.room = room_ev; + + let settings = SyncSettings::new().filter(filter.into()); + + self.client.sync_once(settings).await.map_err(IambError::from)?; Ok(Some(InfoMessage::from("Successfully logged in!"))) }