Support an "invite" field in the room sorting settings (#395)

Co-authored-by: Felix Van der Jeugt <felix.vanderjeugt@posteo.net>
This commit is contained in:
Felix Van der Jeugt 2025-05-15 04:39:22 +02:00 committed by GitHub
parent 1dcd658928
commit 7dd09e32a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 109 additions and 1 deletions

View file

@ -334,6 +334,26 @@ window.
Defaults to
.Sy ["power",\ "id"] .
.El
The available values are:
.Bl -tag -width Ds
.It Sy favorite
Put favorite rooms before other rooms.
.It Sy lowpriority
Put lowpriority rooms after other rooms.
.It Sy name
Sort rooms by alphabetically ascending room name.
.It Sy alias
Sort rooms by alphabetically ascending canonical room alias.
.It Sy id
Sort rooms by alphabetically ascending Matrix room identifier.
.It Sy unread
Put unread rooms before other rooms.
.It Sy recent
Sort rooms by most recent message timestamp.
.It Sy invite
Put invites before other rooms.
.El
.El
.Ss Example 1: Group room members by their server first

View file

@ -243,6 +243,9 @@ pub enum SortFieldRoom {
/// Sort rooms by the timestamps of their most recent messages.
Recent,
/// Sort rooms by whether they are invites.
Invite,
}
/// Fields that users can be sorted by.
@ -307,6 +310,7 @@ impl<'de> Visitor<'de> for SortRoomVisitor {
"name" => SortFieldRoom::Name,
"alias" => SortFieldRoom::Alias,
"id" => SortFieldRoom::RoomId,
"invite" => SortFieldRoom::Invite,
_ => {
let msg = format!("Unknown sort field: {value:?}");
return Err(E::custom(msg));

View file

@ -45,8 +45,9 @@ const DEFAULT_MEMBERS_SORT: [SortColumn<SortFieldUser>; 2] = [
SortColumn(SortFieldUser::UserId, SortOrder::Ascending),
];
const DEFAULT_ROOM_SORT: [SortColumn<SortFieldRoom>; 4] = [
const DEFAULT_ROOM_SORT: [SortColumn<SortFieldRoom>; 5] = [
SortColumn(SortFieldRoom::Favorite, SortOrder::Ascending),
SortColumn(SortFieldRoom::Invite, SortOrder::Ascending),
SortColumn(SortFieldRoom::LowPriority, SortOrder::Ascending),
SortColumn(SortFieldRoom::Unread, SortOrder::Ascending),
SortColumn(SortFieldRoom::Name, SortOrder::Ascending),

View file

@ -23,6 +23,7 @@ use matrix_sdk::{
RoomAliasId,
RoomId,
},
RoomState as MatrixRoomState,
};
use ratatui::{
@ -195,6 +196,10 @@ fn room_cmp<T: RoomLikeItem>(a: &T, b: &T, field: &SortFieldRoom) -> Ordering {
// sort larger timestamps towards the top.
some_cmp(a.recent_ts(), b.recent_ts(), |a, b| b.cmp(a))
},
SortFieldRoom::Invite => {
// sort invites before other rooms.
b.is_invite().cmp(&a.is_invite())
},
}
}
@ -273,6 +278,7 @@ trait RoomLikeItem {
fn recent_ts(&self) -> Option<&MessageTimeStamp>;
fn alias(&self) -> Option<&RoomAliasId>;
fn name(&self) -> &str;
fn is_invite(&self) -> bool;
}
#[inline]
@ -914,6 +920,10 @@ impl RoomLikeItem for GenericChatItem {
fn is_unread(&self) -> bool {
self.unread.is_unread()
}
fn is_invite(&self) -> bool {
self.room().state() == MatrixRoomState::Invited
}
}
impl Display for GenericChatItem {
@ -1024,6 +1034,10 @@ impl RoomLikeItem for RoomItem {
fn is_unread(&self) -> bool {
self.unread.is_unread()
}
fn is_invite(&self) -> bool {
self.room().state() == MatrixRoomState::Invited
}
}
impl Display for RoomItem {
@ -1124,6 +1138,10 @@ impl RoomLikeItem for DirectItem {
fn is_unread(&self) -> bool {
self.unread.is_unread()
}
fn is_invite(&self) -> bool {
self.room().state() == MatrixRoomState::Invited
}
}
impl Display for DirectItem {
@ -1223,6 +1241,10 @@ impl RoomLikeItem for SpaceItem {
// XXX: this needs to check whether the space contains rooms with unread messages
false
}
fn is_invite(&self) -> bool {
self.room().state() == MatrixRoomState::Invited
}
}
impl Display for SpaceItem {
@ -1556,6 +1578,7 @@ mod tests {
alias: Option<OwnedRoomAliasId>,
name: &'static str,
unread: UnreadInfo,
invite: bool,
}
impl RoomLikeItem for &TestRoomItem {
@ -1582,6 +1605,10 @@ mod tests {
fn is_unread(&self) -> bool {
self.unread.is_unread()
}
fn is_invite(&self) -> bool {
self.invite
}
}
#[test]
@ -1594,6 +1621,7 @@ mod tests {
alias: Some(room_alias_id!("#room1:example.com").to_owned()),
name: "Z",
unread: UnreadInfo::default(),
invite: false,
};
let room2 = TestRoomItem {
@ -1602,6 +1630,7 @@ mod tests {
alias: Some(room_alias_id!("#a:example.com").to_owned()),
name: "Unnamed Room",
unread: UnreadInfo::default(),
invite: false,
};
let room3 = TestRoomItem {
@ -1610,6 +1639,7 @@ mod tests {
alias: None,
name: "Cool Room",
unread: UnreadInfo::default(),
invite: false,
};
// Sort by Name ascending.
@ -1655,6 +1685,7 @@ mod tests {
alias: None,
name: "Room 1",
unread: UnreadInfo { unread: false, latest: None },
invite: false,
};
let room2 = TestRoomItem {
@ -1666,6 +1697,7 @@ mod tests {
unread: false,
latest: Some(MessageTimeStamp::OriginServer(40u32.into())),
},
invite: false,
};
let room3 = TestRoomItem {
@ -1677,6 +1709,7 @@ mod tests {
unread: false,
latest: Some(MessageTimeStamp::OriginServer(20u32.into())),
},
invite: false,
};
// Sort by Recent ascending.
@ -1691,4 +1724,54 @@ mod tests {
rooms.sort_by(|a, b| room_fields_cmp(a, b, fields));
assert_eq!(rooms, vec![&room1, &room3, &room2]);
}
#[test]
fn test_sort_room_invites() {
let server = server_name!("example.com");
let room1 = TestRoomItem {
room_id: RoomId::new(server).to_owned(),
tags: vec![],
alias: None,
name: "Old room 1",
unread: UnreadInfo::default(),
invite: false,
};
let room2 = TestRoomItem {
room_id: RoomId::new(server).to_owned(),
tags: vec![],
alias: None,
name: "Old room 2",
unread: UnreadInfo::default(),
invite: false,
};
let room3 = TestRoomItem {
room_id: RoomId::new(server).to_owned(),
tags: vec![],
alias: None,
name: "New Fancy Room",
unread: UnreadInfo::default(),
invite: true,
};
// Sort invites first
let mut rooms = vec![&room1, &room2, &room3];
let fields = &[
SortColumn(SortFieldRoom::Invite, SortOrder::Ascending),
SortColumn(SortFieldRoom::Name, SortOrder::Ascending),
];
rooms.sort_by(|a, b| room_fields_cmp(a, b, fields));
assert_eq!(rooms, vec![&room3, &room1, &room2]);
// Sort invites after
let mut rooms = vec![&room1, &room2, &room3];
let fields = &[
SortColumn(SortFieldRoom::Invite, SortOrder::Descending),
SortColumn(SortFieldRoom::Name, SortOrder::Ascending),
];
rooms.sort_by(|a, b| room_fields_cmp(a, b, fields));
assert_eq!(rooms, vec![&room1, &room2, &room3]);
}
}