Skip to content
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
8 changes: 6 additions & 2 deletions docs/iamb.5
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ How to sort the
.Sy :rooms
window.
Defaults to
.Sy ["favorite",\ "lowpriority",\ "unread",\ "name"] .
.Sy ["favorite",\ "invite",\ "lowpriority",\ "mentions",\ "notifications",\ "recent",\ "name"] .
.It Sy chats
How to sort the
.Sy :chats
Expand Down Expand Up @@ -532,7 +532,11 @@ Sort rooms by alphabetically ascending server name from the room alias.
This will fall back to the server from the room identifier if there is
no canonical alias for the room.
.It Sy unread
Put unread rooms before other rooms.
Put rooms with unread messages before other rooms.
.It Sy notifications
Put rooms with unread notifications before other rooms.
.It Sy mentions
Put rooms with unread mentions before other rooms.
.It Sy recent
Sort rooms by most recent message timestamp.
.It Sy invite
Expand Down
16 changes: 8 additions & 8 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ pub enum SortFieldRoom {
/// Sort rooms by whether they have unread messages.
Unread,

/// Sort rooms by whether they have unread notifications.
Notifications,

/// Sort rooms by whether they have unread mentions.
Mentions,

/// Sort rooms by the timestamps of their most recent messages.
Recent,

Expand Down Expand Up @@ -345,6 +351,8 @@ impl Visitor<'_> for SortRoomVisitor {
"lowpriority" => SortFieldRoom::LowPriority,
"recent" => SortFieldRoom::Recent,
"unread" => SortFieldRoom::Unread,
"notifications" => SortFieldRoom::Notifications,
"mentions" => SortFieldRoom::Mentions,
"name" => SortFieldRoom::Name,
"alias" => SortFieldRoom::Alias,
"id" => SortFieldRoom::RoomId,
Expand Down Expand Up @@ -978,14 +986,6 @@ pub struct UnreadInfo {
}

impl UnreadInfo {
pub fn is_unread(&self) -> bool {
self.unread_mark || self.unread_notifications > 0 || self.unread_mentions > 0
}

pub fn has_mention(&self) -> bool {
self.unread_mentions > 0
}

pub fn latest(&self) -> Option<&MessageTimeStamp> {
self.latest.as_ref()
}
Expand Down
6 changes: 4 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ const DEFAULT_MEMBERS_SORT: [SortColumn<SortFieldUser>; 4] = [
SortColumn(SortFieldUser::UserId, SortOrder::Ascending),
];

const DEFAULT_ROOM_SORT: [SortColumn<SortFieldRoom>; 5] = [
const DEFAULT_ROOM_SORT: [SortColumn<SortFieldRoom>; 7] = [
SortColumn(SortFieldRoom::Favorite, SortOrder::Ascending),
SortColumn(SortFieldRoom::Invite, SortOrder::Ascending),
SortColumn(SortFieldRoom::LowPriority, SortOrder::Ascending),
SortColumn(SortFieldRoom::Unread, SortOrder::Ascending),
SortColumn(SortFieldRoom::Mentions, SortOrder::Ascending),
SortColumn(SortFieldRoom::Notifications, SortOrder::Ascending),
SortColumn(SortFieldRoom::Recent, SortOrder::Ascending),
SortColumn(SortFieldRoom::Name, SortOrder::Ascending),
];

Expand Down
118 changes: 90 additions & 28 deletions src/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,37 @@ fn selected_text(s: &str, selected: bool) -> Text<'_> {
Text::from(selected_span(s, selected))
}

fn name_and_labels<'a>(
fn name_unreads_labels<'a>(
name: &'a str,
unread: &UnreadInfo,
room: &MatrixRoom,
style: Style,
) -> (Span<'a>, Vec<Vec<Span<'static>>>) {
// TODO: use different colors for "mention", "notification", "muted room"
let name_style = if unread.is_unread() {
style.add_modifier(StyleModifier::BOLD)
) -> (Span<'static>, Span<'a>, Vec<Vec<Span<'static>>>) {
let (value, number_style) = if unread.unread_mentions > 0 {
(unread.unread_mentions + unread.unread_notifications, Color::Red)
} else if unread.unread_notifications > 0 {
(unread.unread_notifications, Color::Yellow)
} else {
style
(unread.unread_messages, Color::Gray)
};

let unreads = if unread.unread_mark {
Span::styled(" U ", Color::Green)
} else if value > 99 {
Span::styled("99+ ", number_style)
} else if value == 0 {
Span::styled(" ", number_style)
} else {
Span::styled(format!(" {:2} ", value), number_style)
};

let name_style =
if unread.unread_mark || unread.unread_notifications > 0 || unread.unread_mentions > 0 {
style.bold()
} else {
style
};

let name = Span::styled(name, name_style);

let mut labels = vec![];
Expand All @@ -152,13 +170,7 @@ fn name_and_labels<'a>(
MatrixRoomState::Invited => labels.push(vec![Span::styled("Invited", style)]),
}

if unread.unread_mentions > 0 {
labels.push(vec![Span::styled("Unread Mention", style)]);
} else if unread.is_unread() {
labels.push(vec![Span::styled("Unread", style)]);
}

(name, labels)
(unreads, name, labels)
}

/// Sort `Some` to be less than `None` so that list items with values come before those without.
Expand Down Expand Up @@ -237,6 +249,14 @@ fn room_cmp<T: RoomLikeItem>(
// Sort true (unread) before false (read)
b.is_unread().cmp(&a.is_unread())
},
SortFieldRoom::Notifications => {
// Sort true (unread) before false (read)
b.has_notification().cmp(&a.has_notification())
},
SortFieldRoom::Mentions => {
// Sort true (unread) before false (read)
b.has_mention().cmp(&a.has_mention())
},
SortFieldRoom::Recent => {
// sort larger timestamps towards the top.
some_cmp(a.recent_ts(), b.recent_ts(), |a, b| b.cmp(a))
Expand Down Expand Up @@ -321,6 +341,8 @@ trait RoomLikeItem {
fn room_id(&self) -> &RoomId;
fn has_tag(&self, tag: TagName) -> bool;
fn is_unread(&self) -> bool;
fn has_notification(&self) -> bool;
fn has_mention(&self) -> bool;
fn recent_ts(&self) -> Option<&MessageTimeStamp>;
fn alias(&self) -> Option<&RoomAliasId>;
fn name(&self) -> &str;
Expand Down Expand Up @@ -1033,11 +1055,6 @@ impl GenericChatItem {
fn tags(&self) -> &Option<Tags> {
&self.room_info.deref().1
}

#[inline]
fn has_mention(&self) -> bool {
self.unread.has_mention()
}
}

impl RoomLikeItem for GenericChatItem {
Expand Down Expand Up @@ -1066,7 +1083,15 @@ impl RoomLikeItem for GenericChatItem {
}

fn is_unread(&self) -> bool {
self.unread.is_unread()
self.unread.unread_messages > 0
}

fn has_notification(&self) -> bool {
self.unread.unread_notifications > 0
}

fn has_mention(&self) -> bool {
self.unread.unread_mentions > 0
}

fn is_invite(&self) -> bool {
Expand All @@ -1088,8 +1113,9 @@ impl ListItem<IambInfo> for GenericChatItem {
_: &mut ProgramStore,
) -> Text<'_> {
let style = selected_style(selected);
let (name, mut labels) = name_and_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![name];
let (unreads, name, mut labels) =
name_unreads_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![unreads, name];

labels.push(if self.is_dm {
vec![Span::styled("DM", style)]
Expand Down Expand Up @@ -1184,7 +1210,15 @@ impl RoomLikeItem for RoomItem {
}

fn is_unread(&self) -> bool {
self.unread.is_unread()
self.unread.unread_messages > 0
}

fn has_notification(&self) -> bool {
self.unread.unread_notifications > 0
}

fn has_mention(&self) -> bool {
self.unread.unread_mentions > 0
}

fn is_invite(&self) -> bool {
Expand All @@ -1206,8 +1240,9 @@ impl ListItem<IambInfo> for RoomItem {
_: &mut ProgramStore,
) -> Text<'_> {
let style = selected_style(selected);
let (name, mut labels) = name_and_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![name];
let (unreads, name, mut labels) =
name_unreads_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![unreads, name];

if let Some(tags) = &self.tags() {
labels.extend(tags.keys().map(|t| tag_to_span(t, style)));
Expand Down Expand Up @@ -1293,7 +1328,15 @@ impl RoomLikeItem for DirectItem {
}

fn is_unread(&self) -> bool {
self.unread.is_unread()
self.unread.unread_messages > 0
}

fn has_notification(&self) -> bool {
self.unread.unread_notifications > 0
}

fn has_mention(&self) -> bool {
self.unread.unread_mentions > 0
}

fn is_invite(&self) -> bool {
Expand All @@ -1315,8 +1358,9 @@ impl ListItem<IambInfo> for DirectItem {
_: &mut ProgramStore,
) -> Text<'_> {
let style = selected_style(selected);
let (name, mut labels) = name_and_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![name];
let (unreads, name, mut labels) =
name_unreads_labels(&self.name, &self.unread, self.room(), style);
let mut spans = vec![unreads, name];

if let Some(tags) = &self.tags() {
labels.extend(tags.keys().map(|t| tag_to_span(t, style)));
Expand Down Expand Up @@ -1403,6 +1447,16 @@ impl RoomLikeItem for SpaceItem {
false
}

fn has_notification(&self) -> bool {
// XXX: this needs to check whether the space contains rooms with unread messages
false
}

fn has_mention(&self) -> bool {
// XXX: this needs to check whether the space contains rooms with unread messages
false
}

fn is_invite(&self) -> bool {
self.room().state() == MatrixRoomState::Invited
}
Expand Down Expand Up @@ -1621,7 +1675,15 @@ mod tests {
}

fn is_unread(&self) -> bool {
self.unread.is_unread()
self.unread.unread_messages > 0
}

fn has_notification(&self) -> bool {
self.unread.unread_notifications > 0
}

fn has_mention(&self) -> bool {
self.unread.unread_mentions > 0
}

fn is_invite(&self) -> bool {
Expand Down
Loading