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

Pre-paginate each visible room in the rooms list once #170

Merged
Merged
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
53 changes: 34 additions & 19 deletions src/home/rooms_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crossbeam_queue::SegQueue;
use makepad_widgets::*;
use matrix_sdk::ruma::{MilliSecondsSinceUnixEpoch, OwnedRoomId};

use crate::sliding_sync::{submit_async_request, MatrixRequest};

use super::room_preview::RoomPreviewAction;

live_design! {
Expand Down Expand Up @@ -134,6 +136,11 @@ pub struct RoomPreviewEntry {
/// The avatar for this room: either an array of bytes holding the avatar image
/// or a string holding the first Unicode character of the room name.
pub avatar: RoomPreviewAvatar,
/// Whether this room has been paginated at least once.
/// We pre-paginate visible rooms at least once in order to
/// be able to display the latest message in the room preview,
/// and to have something to immediately show when a user first opens a room.
pub has_been_paginated: bool,
/// Whether this room is currently selected in the UI.
pub is_selected: bool,
}
Expand Down Expand Up @@ -272,21 +279,43 @@ impl Widget for RoomsList {
// TODO: sort list of `all_rooms` by alphabetic, most recent message, grouped by spaces, etc

let count = self.all_rooms.len();
let last_item_id = count;
let status_label_id = count;

// Start the actual drawing procedure.
while let Some(list_item) = self.view.draw_walk(cx, scope, walk).step() {
// We only care about drawing the portal list.
let portal_list_ref = list_item.as_portal_list();
let Some(mut list) = portal_list_ref.borrow_mut() else { continue };

// Add 1 again for the status label at the bottom.
list.set_item_range(cx, 0, last_item_id + 1);
// Add 1 for the status label at the bottom.
list.set_item_range(cx, 0, count + 1);

while let Some(item_id) = list.next_visible_item(cx) {
let mut scope = Scope::empty();

// Draw the room preview for each room.
let item = if let Some(room_info) = self.all_rooms.get_mut(item_id) {
let item = list.item(cx, item_id, live_id!(room_preview)).unwrap();
self.rooms_list_map.insert(item.widget_uid().0, item_id);
room_info.is_selected = self.current_active_room_index == Some(item_id);

// Paginate the room if it hasn't been paginated yet.
if !room_info.has_been_paginated {
room_info.has_been_paginated = true;
submit_async_request(MatrixRequest::PaginateRoomTimeline {
room_id: room_info.room_id.clone(),
num_events: 50,
forwards: false,
});
}

// Pass the room info through Scope down to the RoomPreview widget.
scope = Scope::with_props(&*room_info);

item
}
// Draw the status label as the bottom entry.
let item = if item_id == last_item_id {
else if item_id == status_label_id {
let item = list.item(cx, item_id, live_id!(status_label)).unwrap();
item.as_view().apply_over(cx, live!{
height: Fit,
Expand All @@ -295,22 +324,8 @@ impl Widget for RoomsList {
item
}
// Draw a filler entry to take up space at the bottom of the portal list.
else if item_id > last_item_id {
list.item(cx, item_id, live_id!(bottom_filler)).unwrap()
}
else {
let item_template = live_id!(room_preview);

let item = list.item(cx, item_id, item_template).unwrap();
let index_of_room = item_id as usize;
self.rooms_list_map.insert(item.widget_uid().0, index_of_room);

let room_info = &mut self.all_rooms[index_of_room];
room_info.is_selected = self.current_active_room_index == Some(item_id);
// Pass down the room info to the RoomPreview widget.
scope = Scope::with_props(&*room_info);

item
list.item(cx, item_id, live_id!(bottom_filler)).unwrap()
};

item.draw_all(cx, &mut scope);
Expand Down
1 change: 1 addition & 0 deletions src/profile/user_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl AvatarState {
}

/// Returns the avatar URI, if in the `Known` state and it exists.
#[allow(unused)]
pub fn uri(&self) -> Option<&OwnedMxcUri> {
if let AvatarState::Known(Some(uri)) = self {
Some(uri)
Expand Down
1 change: 1 addition & 0 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,7 @@ async fn add_new_room(room: &room_list_service::Room) -> Result<()> {
// start with a basic text avatar; the avatar image will be fetched asynchronously below.
avatar: avatar_from_room_name(room_name.as_deref().unwrap_or_default()),
room_name,
has_been_paginated: false,
is_selected: false,
}));

Expand Down