Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render roomlist under people's header #174

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions src/home/rooms_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,16 @@ pub enum RoomsListUpdate {
}

static PENDING_ROOM_UPDATES: SegQueue<RoomsListUpdate> = SegQueue::new();
static PENDING_IS_DIRECT_ROOM_UPDATES: SegQueue<RoomsListUpdate> = 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();
}

Expand Down Expand Up @@ -173,12 +178,16 @@ pub struct RoomsList {
#[rust] current_active_room_index: Option<usize>,
/// The maximum number of rooms that will ever be loaded.
#[rust] max_known_rooms: Option<u32>,
#[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::<TotalLoadedRoomsCount>() {
cx.get_global::<TotalLoadedRoomsCount>().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())
};
Expand All @@ -189,11 +198,22 @@ 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) => {
if cx.has_global::<TotalLoadedRoomsCount>() {
cx.get_global::<TotalLoadedRoomsCount>().0 += 1;
} else {
cx.set_global(TotalLoadedRoomsCount(1));
}
self.all_rooms.push(room);
}
RoomsListUpdate::UpdateRoomAvatar { room_id, avatar } => {
Expand Down Expand Up @@ -232,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;
Expand Down Expand Up @@ -315,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,
Expand Down
16 changes: 15 additions & 1 deletion src/home/rooms_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ live_design! {
}
}
}
}
<CachedWidget> {
people_list = <RoomsList> {
width: Fill, height: 75
room_type: "people"
}
}
<View> {
flow: Down, spacing: 20
padding: {top: 20},
width: Fill, height: Fit
<CollapsableTitle> {
title = {
text: "Channels"
Expand All @@ -149,7 +160,10 @@ live_design! {
}
}
<CachedWidget> {
rooms_list = <RoomsList> {}
height: Fit,
rooms_list = <RoomsList> {
room_type: "room"
}
}
}

Expand Down
74 changes: 46 additions & 28 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ async fn login(cli: Cli) -> Result<(Client, Option<String>)> {
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,
Expand All @@ -160,7 +160,7 @@ async fn login(cli: Cli) -> Result<(Client, Option<String>)> {
} 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)
}
}
Expand Down Expand Up @@ -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:?}");
Expand All @@ -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:?}");
Expand Down Expand Up @@ -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<OwnedUserId> = cli.username.to_string().try_into().ok()
.or_else(|| {
Expand Down Expand Up @@ -952,7 +952,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"); }
Expand All @@ -967,13 +969,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 } => {
Expand All @@ -990,7 +994,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());
}
Expand All @@ -999,7 +1004,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
Expand All @@ -1012,7 +1018,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?;
}
Expand All @@ -1032,11 +1040,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.
Expand Down Expand Up @@ -1088,7 +1103,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,
Expand All @@ -1097,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);

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(),
Expand Down Expand Up @@ -1192,10 +1207,12 @@ fn handle_room_list_service_loading_state(mut loading_state: Subscriber<RoomList
log!("Received a room list loading state update: {state:?}");
match state {
RoomListLoadingState::NotLoaded => {
enqueue_rooms_list_update(RoomsListUpdate::NotLoaded);
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 });
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);
}
}
}
Expand Down Expand Up @@ -1224,7 +1241,7 @@ async fn timeline_subscriber_handler(
);

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.
Expand Down Expand Up @@ -1358,10 +1375,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);
}
}
}
Expand All @@ -1378,6 +1395,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;
Expand Down Expand Up @@ -1409,7 +1427,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;
Expand All @@ -1422,21 +1440,21 @@ 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 {
let avatar = room_avatar(&room, &room_name_str).await;
rooms_list::enqueue_rooms_list_update(RoomsListUpdate::UpdateRoomAvatar {
room_id,
avatar,
});
}, is_direct);
});
}

Expand Down