From 057ab12f60b2d1f77f85c18c5d3677c0ceb10eee Mon Sep 17 00:00:00 2001 From: alanpoon Date: Mon, 7 Oct 2024 13:43:04 +0800 Subject: [PATCH 1/4] render under people header --- src/home/rooms_list.rs | 18 ++++++++-- src/home/rooms_sidebar.rs | 9 ++++- src/sliding_sync.rs | 72 ++++++++++++++++++++++++--------------- 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/src/home/rooms_list.rs b/src/home/rooms_list.rs index 90669931..996c6318 100644 --- a/src/home/rooms_list.rs +++ b/src/home/rooms_list.rs @@ -103,11 +103,16 @@ pub enum RoomsListUpdate { } static PENDING_ROOM_UPDATES: SegQueue = SegQueue::new(); +static PENDING_IS_DIRECT_ROOM_UPDATES: SegQueue = SegQueue::new(); /// Enqueue a new room update for the list of all rooms /// and signals the UI that a new update is available to be handled. -pub fn enqueue_rooms_list_update(update: RoomsListUpdate) { - PENDING_ROOM_UPDATES.push(update); +pub fn enqueue_rooms_list_update(update: RoomsListUpdate, is_direct: bool) { + if is_direct { + PENDING_IS_DIRECT_ROOM_UPDATES.push(update); + } else { + PENDING_ROOM_UPDATES.push(update); + } SignalToUI::set_ui_signal(); } @@ -173,6 +178,7 @@ pub struct RoomsList { #[rust] current_active_room_index: Option, /// The maximum number of rooms that will ever be loaded. #[rust] max_known_rooms: Option, + #[live] room_type: String } impl RoomsList { @@ -189,8 +195,14 @@ impl Widget for RoomsList { fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { // Process all pending updates to the list of all rooms, and then redraw it. { + + let queue = if self.room_type == "people"{ + &PENDING_IS_DIRECT_ROOM_UPDATES + } else { + &PENDING_ROOM_UPDATES + }; let mut num_updates: usize = 0; - while let Some(update) = PENDING_ROOM_UPDATES.pop() { + while let Some(update) = queue.pop() { num_updates += 1; match update { RoomsListUpdate::AddRoom(room) => { diff --git a/src/home/rooms_sidebar.rs b/src/home/rooms_sidebar.rs index 357c8a82..be1182da 100644 --- a/src/home/rooms_sidebar.rs +++ b/src/home/rooms_sidebar.rs @@ -125,6 +125,11 @@ live_design! { } } } + + { + room_type: "people" + } + { title = { text: "Channels" @@ -149,7 +154,9 @@ live_design! { } } { - rooms_list = {} + rooms_list = { + room_type: "room" + } } } diff --git a/src/sliding_sync.rs b/src/sliding_sync.rs index 0720090c..558692d8 100644 --- a/src/sliding_sync.rs +++ b/src/sliding_sync.rs @@ -149,7 +149,7 @@ async fn login(cli: Cli) -> Result<(Client, Option)> { log!("Logged in successfully? {:?}", client.logged_in()); enqueue_rooms_list_update(RoomsListUpdate::Status { status: format!("Logged in as {}. Loading rooms...", &cli.username), - }); + },false); if let Err(e) = persistent_state::save_session( &client, client_session, @@ -160,7 +160,7 @@ async fn login(cli: Cli) -> Result<(Client, Option)> { } else { enqueue_rooms_list_update(RoomsListUpdate::Status { status: format!("Failed to login as {}: {:?}", &cli.username, login_result), - }); + },false); bail!("Failed to login as {}: {login_result:?}", &cli.username) } } @@ -715,7 +715,7 @@ pub fn start_matrix_tokio() -> Result<()> { error!("Error: main async loop task ended:\n\t{e:?}"); rooms_list::enqueue_rooms_list_update(RoomsListUpdate::Status { status: e.to_string(), - }); + },false); }, Err(e) => { error!("BUG: failed to join main async loop task: {e:?}"); @@ -732,7 +732,7 @@ pub fn start_matrix_tokio() -> Result<()> { error!("Error: async worker task ended:\n\t{e:?}"); rooms_list::enqueue_rooms_list_update(RoomsListUpdate::Status { status: e.to_string(), - }); + },false); }, Err(e) => { error!("BUG: failed to join async worker task: {e:?}"); @@ -882,12 +882,12 @@ async fn async_main_loop() -> Result<()> { status: String::from("Error: missing username and password in 'login.toml' file. \ Please provide a valid username and password in 'login.toml' and rebuild the app." ), - }); + }, false); loop { } // nothing else we can do right now }; enqueue_rooms_list_update(RoomsListUpdate::Status { status: format!("Logging in as {}...", &cli.username) - }); + }, false); let specified_username: Option = cli.username.to_string().try_into().ok() .or_else(|| { @@ -950,7 +950,9 @@ async fn async_main_loop() -> Result<()> { // TODO: we probably need to remove each room individually to kill off // all of the async tasks associated with them (i.e., the timeline subscriber). // Or, better yet, implement the drop handler for RoomInfo to do so. - enqueue_rooms_list_update(RoomsListUpdate::ClearRooms); + enqueue_rooms_list_update(RoomsListUpdate::ClearRooms , false); + enqueue_rooms_list_update(RoomsListUpdate::ClearRooms , true); + } VectorDiff::PushFront { value: new_room } => { if LOG_ROOM_LIST_DIFFS { log!("room_list: diff PushFront"); } @@ -965,13 +967,15 @@ async fn async_main_loop() -> Result<()> { VectorDiff::PopFront => { if LOG_ROOM_LIST_DIFFS { log!("room_list: diff PopFront"); } if let Some(room) = all_known_rooms.pop_front() { - remove_room(room); + let is_direct = room.is_direct().await.unwrap_or(false); + remove_room(room, is_direct); } } VectorDiff::PopBack => { if LOG_ROOM_LIST_DIFFS { log!("room_list: diff PopBack"); } if let Some(room) = all_known_rooms.pop_back() { - remove_room(room); + let is_direct = room.is_direct().await.unwrap_or(false); + remove_room(room, is_direct); } } VectorDiff::Insert { index, value: new_room } => { @@ -988,7 +992,8 @@ async fn async_main_loop() -> Result<()> { if LOG_ROOM_LIST_DIFFS { log!("room_list: diff Remove at {index}"); } if index < all_known_rooms.len() { let room = all_known_rooms.remove(index); - remove_room(room); + let is_direct = room.is_direct().await.unwrap_or(false); + remove_room(room, is_direct); } else { error!("BUG: room_list: diff Remove index {index} out of bounds, len {}", all_known_rooms.len()); } @@ -997,7 +1002,8 @@ async fn async_main_loop() -> Result<()> { if LOG_ROOM_LIST_DIFFS { log!("room_list: diff Truncate to {length}"); } while all_known_rooms.len() > length { if let Some(room) = all_known_rooms.pop_back() { - remove_room(room); + let is_direct = room.is_direct().await.unwrap_or(false); + remove_room(room, is_direct); } } all_known_rooms.truncate(length); // sanity check @@ -1010,7 +1016,9 @@ async fn async_main_loop() -> Result<()> { // TODO: we probably need to remove each room individually to kill off // all of the async tasks associated with them (i.e., the timeline subscriber). // Or, better yet, implement the drop handler for RoomInfo to do so. - enqueue_rooms_list_update(RoomsListUpdate::ClearRooms); + enqueue_rooms_list_update(RoomsListUpdate::ClearRooms, false); + enqueue_rooms_list_update(RoomsListUpdate::ClearRooms, true); + for room in &all_known_rooms { add_new_room(&room).await?; } @@ -1030,11 +1038,18 @@ async fn update_room(_room: &room_list_service::Room) -> matrix_sdk::Result<()> /// Invoked when the room list service has received an update to remove an existing room. -fn remove_room(room: room_list_service::Room) { +fn remove_room(room: room_list_service::Room, is_direct: bool) { ALL_ROOM_INFO.lock().unwrap().remove(room.room_id()); - enqueue_rooms_list_update( - RoomsListUpdate::RemoveRoom(room.room_id().to_owned()) - ); + if is_direct { + enqueue_rooms_list_update( + RoomsListUpdate::RemoveRoom(room.room_id().to_owned()), true + ); + } else { + enqueue_rooms_list_update( + RoomsListUpdate::RemoveRoom(room.room_id().to_owned()), false + ); + } + // TODO: we probably need to kill all of the async tasks associated // with this room (i.e., the timeline subscriber. etc). // Or, better yet, implement `RoomInfo::drop()` to do so. @@ -1086,7 +1101,7 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> { .format_with(sender_username), ) }); - + let is_direct = room.is_direct().await.unwrap_or(false); rooms_list::enqueue_rooms_list_update(RoomsListUpdate::AddRoom(RoomPreviewEntry { room_id: room_id.clone(), latest, @@ -1095,9 +1110,9 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> { room_name, has_been_paginated: false, is_selected: false, - })); + }),is_direct); - spawn_fetch_room_avatar(room.inner_room().clone()); + spawn_fetch_room_avatar(room.inner_room().clone(),is_direct); ALL_ROOM_INFO.lock().unwrap().insert( room_id.clone(), @@ -1187,10 +1202,10 @@ fn handle_room_list_service_loading_state(mut loading_state: Subscriber { - enqueue_rooms_list_update(RoomsListUpdate::NotLoaded); + enqueue_rooms_list_update(RoomsListUpdate::NotLoaded, false); } RoomListLoadingState::Loaded { maximum_number_of_rooms } => { - enqueue_rooms_list_update(RoomsListUpdate::LoadedRooms { max_rooms: maximum_number_of_rooms }); + enqueue_rooms_list_update(RoomsListUpdate::LoadedRooms { max_rooms: maximum_number_of_rooms }, false); } } } @@ -1216,7 +1231,7 @@ async fn timeline_subscriber_handler( }).expect("Error: timeline update sender couldn't send update with initial items!"); let mut latest_event = timeline.latest_event().await; - + let is_direct = room.is_direct().await.unwrap_or(false); while let Some(batch) = subscriber.next().await { let mut num_updates = 0; // For now we always requery the latest event, but this can be better optimized. @@ -1350,10 +1365,10 @@ async fn timeline_subscriber_handler( // Update the latest event for this room. if let Some(new_latest) = new_latest_event { if latest_event.as_ref().map_or(true, |ev| ev.timestamp() < new_latest.timestamp()) { - let room_avatar_changed = update_latest_event(&room_id, &new_latest); + let room_avatar_changed = update_latest_event(&room_id, is_direct, &new_latest); latest_event = Some(new_latest); if room_avatar_changed { - spawn_fetch_room_avatar(room.clone()); + spawn_fetch_room_avatar(room.clone(), is_direct); } } } @@ -1370,6 +1385,7 @@ async fn timeline_subscriber_handler( /// and should also be updated. fn update_latest_event( room_id: &RoomId, + is_direct: bool, event_tl_item: &EventTimelineItem, ) -> bool { let mut room_avatar_changed = false; @@ -1401,7 +1417,7 @@ fn update_latest_event( rooms_list::enqueue_rooms_list_update(RoomsListUpdate::UpdateRoomName { room_id: room_id.to_owned(), new_room_name: content.name.clone(), - }); + }, is_direct); } AnyOtherFullStateEventContent::RoomAvatar(_avatar_event) => { room_avatar_changed = true; @@ -1414,13 +1430,13 @@ fn update_latest_event( room_id: room_id.to_owned(), timestamp: event_tl_item.timestamp(), latest_message_text, - }); + }, is_direct); room_avatar_changed } /// Spawn a new async task to fetch the room's new avatar. -fn spawn_fetch_room_avatar(room: Room) { +fn spawn_fetch_room_avatar(room: Room, is_direct: bool) { let room_id = room.room_id().to_owned(); let room_name_str = room.cached_display_name().map(|dn| dn.to_string()); Handle::current().spawn(async move { @@ -1428,7 +1444,7 @@ fn spawn_fetch_room_avatar(room: Room) { rooms_list::enqueue_rooms_list_update(RoomsListUpdate::UpdateRoomAvatar { room_id, avatar, - }); + }, is_direct); }); } From 5a7412f0fc05679657cc8beb004e07ece4732256 Mon Sep 17 00:00:00 2001 From: alanpoon Date: Mon, 7 Oct 2024 17:32:14 +0800 Subject: [PATCH 2/4] fixed crashed --- src/home/rooms_list.rs | 18 +++++++++++++----- src/home/rooms_sidebar.rs | 13 ++++++++++--- src/sliding_sync.rs | 2 ++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/home/rooms_list.rs b/src/home/rooms_list.rs index 996c6318..ea3ec513 100644 --- a/src/home/rooms_list.rs +++ b/src/home/rooms_list.rs @@ -180,11 +180,14 @@ pub struct RoomsList { #[rust] max_known_rooms: Option, #[live] room_type: String } - +pub struct TotalLoadedRoomsCount(u32); impl RoomsList { - fn update_status_rooms_count(&mut self) { + fn update_status_rooms_count(&mut self, cx: &mut Cx) { + let total_loaded_rooms_count = if cx.has_global::() { + cx.get_global::().0 + } else { 0 }; self.status = if let Some(max_rooms) = self.max_known_rooms { - format!("Loaded {} of {} total rooms.", self.all_rooms.len(), max_rooms) + format!("Loaded {} of {} total rooms.", total_loaded_rooms_count, max_rooms) } else { format!("Loaded {} rooms.", self.all_rooms.len()) }; @@ -206,6 +209,11 @@ impl Widget for RoomsList { num_updates += 1; match update { RoomsListUpdate::AddRoom(room) => { + if cx.has_global::() { + cx.get_global::().0 += 1; + } else { + cx.set_global(TotalLoadedRoomsCount(1)); + } self.all_rooms.push(room); } RoomsListUpdate::UpdateRoomAvatar { room_id, avatar } => { @@ -244,7 +252,7 @@ impl Widget for RoomsList { } RoomsListUpdate::LoadedRooms { max_rooms } => { self.max_known_rooms = max_rooms; - self.update_status_rooms_count(); + self.update_status_rooms_count(cx); } RoomsListUpdate::Status { status } => { self.status = status; @@ -327,7 +335,7 @@ impl Widget for RoomsList { item } // Draw the status label as the bottom entry. - else if item_id == status_label_id { + else if item_id == status_label_id && self.room_type == "room" { let item = list.item(cx, item_id, live_id!(status_label)).unwrap(); item.as_view().apply_over(cx, live!{ height: Fit, diff --git a/src/home/rooms_sidebar.rs b/src/home/rooms_sidebar.rs index be1182da..59155c65 100644 --- a/src/home/rooms_sidebar.rs +++ b/src/home/rooms_sidebar.rs @@ -125,11 +125,17 @@ live_design! { } } } - - { + } + { + people_list = { + width: Fill, height: 75 room_type: "people" } - + } + { + flow: Down, spacing: 20 + padding: {top: 20}, + width: Fill, height: Fit { title = { text: "Channels" @@ -154,6 +160,7 @@ live_design! { } } { + height: Fit, rooms_list = { room_type: "room" } diff --git a/src/sliding_sync.rs b/src/sliding_sync.rs index 558692d8..9e9913f6 100644 --- a/src/sliding_sync.rs +++ b/src/sliding_sync.rs @@ -1203,9 +1203,11 @@ fn handle_room_list_service_loading_state(mut loading_state: Subscriber { enqueue_rooms_list_update(RoomsListUpdate::NotLoaded, false); + enqueue_rooms_list_update(RoomsListUpdate::NotLoaded, true); } RoomListLoadingState::Loaded { maximum_number_of_rooms } => { enqueue_rooms_list_update(RoomsListUpdate::LoadedRooms { max_rooms: maximum_number_of_rooms }, false); + enqueue_rooms_list_update(RoomsListUpdate::LoadedRooms { max_rooms: maximum_number_of_rooms }, true); } } } From 316bcafe5137beebf081776c7b4bf47d7a7cdc3b Mon Sep 17 00:00:00 2001 From: alanpoon Date: Mon, 7 Oct 2024 17:42:22 +0800 Subject: [PATCH 3/4] hide status from people list --- src/home/rooms_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/rooms_list.rs b/src/home/rooms_list.rs index aed24647..6bf94a0a 100644 --- a/src/home/rooms_list.rs +++ b/src/home/rooms_list.rs @@ -335,7 +335,7 @@ impl Widget for RoomsList { item } // Draw the status label as the bottom entry. - else if item_id == status_label_id { + else if item_id == status_label_id && self.room_type == "room" { let item = list.item(cx, item_id, live_id!(status_label)); item.as_view().apply_over(cx, live!{ height: Fit, From 09510bacfb2d69601ee9e9ea1193e29af971d55c Mon Sep 17 00:00:00 2001 From: alanpoon Date: Mon, 7 Oct 2024 19:46:54 +0800 Subject: [PATCH 4/4] minor whitespace cleanup --- src/sliding_sync.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sliding_sync.rs b/src/sliding_sync.rs index d90d5e05..809da26d 100644 --- a/src/sliding_sync.rs +++ b/src/sliding_sync.rs @@ -149,7 +149,7 @@ async fn login(cli: Cli) -> Result<(Client, Option)> { log!("Logged in successfully? {:?}", client.logged_in()); enqueue_rooms_list_update(RoomsListUpdate::Status { status: format!("Logged in as {}. Loading rooms...", &cli.username), - },false); + }, false); if let Err(e) = persistent_state::save_session( &client, client_session, @@ -160,7 +160,7 @@ async fn login(cli: Cli) -> Result<(Client, Option)> { } else { enqueue_rooms_list_update(RoomsListUpdate::Status { status: format!("Failed to login as {}: {:?}", &cli.username, login_result), - },false); + }, false); bail!("Failed to login as {}: {login_result:?}", &cli.username) } } @@ -715,7 +715,7 @@ pub fn start_matrix_tokio() -> Result<()> { error!("Error: main async loop task ended:\n\t{e:?}"); rooms_list::enqueue_rooms_list_update(RoomsListUpdate::Status { status: e.to_string(), - },false); + }, false); }, Err(e) => { error!("BUG: failed to join main async loop task: {e:?}"); @@ -732,7 +732,7 @@ pub fn start_matrix_tokio() -> Result<()> { error!("Error: async worker task ended:\n\t{e:?}"); rooms_list::enqueue_rooms_list_update(RoomsListUpdate::Status { status: e.to_string(), - },false); + }, false); }, Err(e) => { error!("BUG: failed to join async worker task: {e:?}"); @@ -1112,9 +1112,9 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> { room_name, has_been_paginated: false, is_selected: false, - }),is_direct); + }), is_direct); - spawn_fetch_room_avatar(room.inner_room().clone(),is_direct); + spawn_fetch_room_avatar(room.inner_room().clone(), is_direct); ALL_ROOM_INFO.lock().unwrap().insert( room_id.clone(),