Skip to content

WIP: Sort room list by date #416

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
45 changes: 39 additions & 6 deletions src/home/rooms_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use makepad_widgets::*;
use matrix_sdk::ruma::{events::tag::{TagName, Tags}, MilliSecondsSinceUnixEpoch, OwnedRoomAliasId, OwnedRoomId};
use bitflags::bitflags;
use crate::{app::AppState, shared::jump_to_bottom_button::UnreadMessageCount, sliding_sync::{submit_async_request, MatrixRequest, PaginationDirection}};
use matrix_sdk_ui::timeline::TimelineItemContent;

use super::{room_preview::RoomPreviewAction, rooms_sidebar::RoomsViewAction};

Expand Down Expand Up @@ -81,12 +82,15 @@ pub enum RoomsListUpdate {
/// the max number of rooms that will ever be loaded.
LoadedRooms{ max_rooms: Option<u32> },
/// Add a new room to the list of all rooms.
AddRoom(RoomsListEntry),
AddRoomFront(RoomsListEntry),
/// Add a new room to the list of all rooms.
AddRoomBack(RoomsListEntry),
/// Clear all rooms in the list of all rooms.
ClearRooms,
/// Update the latest event content and timestamp for the given room.
UpdateLatestEvent {
room_id: OwnedRoomId,
content: TimelineItemContent,
timestamp: MilliSecondsSinceUnixEpoch,
/// The Html-formatted text preview of the latest message.
latest_message_text: String,
Expand Down Expand Up @@ -163,6 +167,8 @@ pub struct RoomsListEntry {
pub tags: Option<Tags>,
/// The timestamp and Html text content of the latest message in this room.
pub latest: Option<(MilliSecondsSinceUnixEpoch, String)>,
/// The timestamp and Html text content of the latest display message in this room.
pub latest_display: Option<(MilliSecondsSinceUnixEpoch, String)>,
/// 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,
Expand Down Expand Up @@ -407,6 +413,8 @@ pub struct RoomsList {
/// The single set of all known rooms and their cached preview info.
#[rust] all_rooms: HashMap<OwnedRoomId, RoomsListEntry>,

#[rust] all_rooms_sorted: Vec<OwnedRoomId>,

/// The currently-active filter function for the list of rooms.
///
/// Note: for performance reasons, this does not get automatically applied
Expand Down Expand Up @@ -461,10 +469,11 @@ impl Widget for RoomsList {
while let Some(update) = PENDING_ROOM_UPDATES.pop() {
num_updates += 1;
match update {
RoomsListUpdate::AddRoom(room) => {
RoomsListUpdate::AddRoomBack(room) => {
let room_id = room.room_id.clone();
let should_display = (self.display_filter)(&room);
let _replaced = self.all_rooms.insert(room_id.clone(), room);
self.all_rooms_sorted.push(room_id.clone());
if let Some(_old_room) = _replaced {
error!("BUG: Added room {room_id} that already existed");
} else {
Expand All @@ -474,15 +483,35 @@ impl Widget for RoomsList {
}
self.update_status_rooms_count();
}
RoomsListUpdate::AddRoomFront(room) => {
let room_id = room.room_id.clone();
let should_display = (self.display_filter)(&room);
let _replaced = self.all_rooms.insert(room_id.clone(), room);
self.all_rooms_sorted.insert(0, room_id.clone());
if let Some(_old_room) = _replaced {
error!("BUG: Added room {room_id} that already existed");
} else {
if should_display {
self.displayed_rooms.insert(0,room_id);
}
}
self.update_status_rooms_count();
}
RoomsListUpdate::UpdateRoomAvatar { room_id, avatar } => {
if let Some(room) = self.all_rooms.get_mut(&room_id) {
room.avatar = avatar;
} else {
error!("Error: couldn't find room {room_id} to update avatar");
}
}
RoomsListUpdate::UpdateLatestEvent { room_id, timestamp, latest_message_text } => {
RoomsListUpdate::UpdateLatestEvent { room_id, timestamp, content, latest_message_text } => {
if let Some(room) = self.all_rooms.get_mut(&room_id) {
// Update the latest display message if this event should be displayed
if let TimelineItemContent::Message(_) = content {
room.latest_display =
Some((timestamp, latest_message_text.clone()));
}

room.latest = Some((timestamp, latest_message_text));
} else {
error!("Error: couldn't find room {room_id} to update latest event");
Expand Down Expand Up @@ -533,6 +562,10 @@ impl Widget for RoomsList {
.unwrap_or_else(|| {
error!("Error: couldn't find room {room_id} to remove room");
});
let pos = self.all_rooms_sorted.iter().position(|r| r == &room_id);
if let Some(pos) = pos{
self.all_rooms_sorted.remove(pos);
}

self.update_status_rooms_count();

Expand All @@ -546,6 +579,7 @@ impl Widget for RoomsList {
}
RoomsListUpdate::ClearRooms => {
self.all_rooms.clear();
self.all_rooms_sorted.clear();
self.displayed_rooms.clear();
self.update_status_rooms_count();
}
Expand Down Expand Up @@ -697,16 +731,15 @@ impl WidgetMatchEvent for RoomsList {
for action in actions {
if let RoomsViewAction::Search(keywords) = action.as_widget_action().cast() {
let portal_list = self.view.portal_list(id!(list));

if keywords.is_empty() {
// Reset the displayed rooms list to show all rooms.
self.display_filter = RoomDisplayFilter::default();
self.displayed_rooms = self.all_rooms.keys().cloned().collect();
self.displayed_rooms = self.all_rooms_sorted.to_vec();
self.update_status_rooms_count();
portal_list.set_first_id_and_scroll(0, 0.0);
self.redraw(cx);
return;
}

let (filter, sort_fn) = RoomDisplayFilterBuilder::new()
.set_keywords(keywords.clone())
.set_filter_criteria(RoomFilterCriteria::All)
Expand Down
57 changes: 42 additions & 15 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use matrix_sdk::{
}, sliding_sync::VersionBuilder, Client, ClientBuildError, Error, Room, RoomMemberships
};
use matrix_sdk_ui::{
room_list_service::{self, RoomListLoadingState}, sync_service::{self, SyncService}, timeline::{AnyOtherFullStateEventContent, EventTimelineItem, MembershipChange, RepliedToInfo, TimelineEventItemId, TimelineItem, TimelineItemContent}, RoomListService, Timeline
room_list_service::{self, RoomListLoadingState}, sync_service::{self, SyncService}, timeline::{AnyOtherFullStateEventContent, EventTimelineItem, MembershipChange, RepliedToInfo, TimelineEventItemId, TimelineItem, TimelineItemContent, TimelineItemKind}, RoomListService, Timeline
};
use robius_open::Uri;
use tokio::{
Expand Down Expand Up @@ -1335,7 +1335,7 @@ async fn async_main_loop(
Box::new(|_room| true),
);

const LOG_ROOM_LIST_DIFFS: bool = false;
const LOG_ROOM_LIST_DIFFS: bool = true;

let mut all_known_rooms = Vector::new();
pin_mut!(room_diff_stream);
Expand All @@ -1347,7 +1347,7 @@ async fn async_main_loop(
let _num_new_rooms = new_rooms.len();
if LOG_ROOM_LIST_DIFFS { log!("room_list: diff Append {_num_new_rooms}"); }
for new_room in &new_rooms {
add_new_room(new_room, &room_list_service).await?;
add_new_room(new_room, &room_list_service, true).await?;
}
all_known_rooms.append(new_rooms);
}
Expand All @@ -1359,12 +1359,12 @@ async fn async_main_loop(
}
VectorDiff::PushFront { value: new_room } => {
if LOG_ROOM_LIST_DIFFS { log!("room_list: diff PushFront"); }
add_new_room(&new_room, &room_list_service).await?;
add_new_room(&new_room, &room_list_service, false).await?;
all_known_rooms.push_front(new_room);
}
VectorDiff::PushBack { value: new_room } => {
if LOG_ROOM_LIST_DIFFS { log!("room_list: diff PushBack"); }
add_new_room(&new_room, &room_list_service).await?;
add_new_room(&new_room, &room_list_service,true).await?;
all_known_rooms.push_back(new_room);
}
VectorDiff::PopFront => {
Expand All @@ -1383,7 +1383,8 @@ async fn async_main_loop(
}
VectorDiff::Insert { index, value: new_room } => {
if LOG_ROOM_LIST_DIFFS { log!("room_list: diff Insert at {index}"); }
add_new_room(&new_room, &room_list_service).await?;
// TODO: handle correctly insert
add_new_room(&new_room, &room_list_service, true).await?;
all_known_rooms.insert(index, new_room);
}
VectorDiff::Set { index, value: changed_room } => {
Expand Down Expand Up @@ -1445,7 +1446,7 @@ async fn async_main_loop(
ALL_ROOM_INFO.lock().unwrap().clear();
enqueue_rooms_list_update(RoomsListUpdate::ClearRooms);
for room in &new_rooms {
add_new_room(room, &room_list_service).await?;
add_new_room(room, &room_list_service, true).await?;
}
all_known_rooms = new_rooms;
}
Expand Down Expand Up @@ -1511,7 +1512,7 @@ async fn update_room(
old_room.room_id(), new_room_id,
);
remove_room(old_room);
add_new_room(new_room, room_list_service).await
add_new_room(new_room, room_list_service, false).await
}
}

Expand All @@ -1526,7 +1527,8 @@ fn remove_room(room: &room_list_service::Room) {


/// Invoked when the room list service has received an update with a brand new room.
async fn add_new_room(room: &room_list_service::Room, room_list_service: &RoomListService) -> Result<()> {
async fn add_new_room(room: &room_list_service::Room, room_list_service: &RoomListService, back: bool) -> Result<()> {

let room_id = room.room_id().to_owned();

// NOTE: the call to `sync_up()` never returns, so I'm not sure how to force a room to fully sync.
Expand Down Expand Up @@ -1572,9 +1574,29 @@ async fn add_new_room(room: &room_list_service::Room, room_list_service: &RoomLi
room.timeline().ok_or_else(|| anyhow::anyhow!("BUG: room timeline not found for room {room_id}"))?
};
let latest_event = timeline.latest_event().await;

let items = timeline.items().await;

let latest_display = items
.iter()
.rev()
.find(|&item| match item.kind() {
TimelineItemKind::Event(e) => {
matches!(e.content(), TimelineItemContent::Message(_))
}
_ => false,
})
.map(|element| match element.kind() {
TimelineItemKind::Event(ev) => Some(get_latest_event_details(ev, &room_id)),
_ => None,
})
.unwrap_or_default();

let (timeline_update_sender, timeline_update_receiver) = crossbeam_channel::unbounded();

let room_name = room.compute_display_name().await
let room_name = room
.compute_display_name()
.await
.map(|n| n.to_string())
.ok();

Expand All @@ -1586,12 +1608,13 @@ async fn add_new_room(room: &room_list_service::Room, room_list_service: &RoomLi
request_receiver,
));

let latest = latest_event.as_ref().map(
|ev| get_latest_event_details(ev, &room_id)
);
let latest = latest_event
.as_ref()
.map(|ev| get_latest_event_details(ev, &room_id));

rooms_list::enqueue_rooms_list_update(RoomsListUpdate::AddRoom(RoomsListEntry {
let room_list_entry = RoomsListEntry {
room_id: room_id.clone(),
latest_display,
latest,
tags: room.tags().await.ok().flatten(),
num_unread_messages: room.num_unread_messages(),
Expand All @@ -1603,7 +1626,9 @@ async fn add_new_room(room: &room_list_service::Room, room_list_service: &RoomLi
alt_aliases: room.alt_aliases(),
has_been_paginated: false,
is_selected: false,
}));
};

rooms_list::enqueue_rooms_list_update(match back {true => RoomsListUpdate::AddRoomBack(room_list_entry), false =>RoomsListUpdate::AddRoomFront(room_list_entry)});

spawn_fetch_room_avatar(room.inner_room().clone());

Expand Down Expand Up @@ -2085,6 +2110,7 @@ fn update_latest_event(
let mut room_avatar_changed = false;

let (timestamp, latest_message_text) = get_latest_event_details(event_tl_item, &room_id);
let content = event_tl_item.content().clone();
match event_tl_item.content() {
// Check for relevant state events.
TimelineItemContent::OtherState(other) => {
Expand Down Expand Up @@ -2133,6 +2159,7 @@ fn update_latest_event(

enqueue_rooms_list_update(RoomsListUpdate::UpdateLatestEvent {
room_id,
content,
timestamp,
latest_message_text,
});
Expand Down