diff --git a/po/POTFILES.in b/po/POTFILES.in index 31ec53a5..f6bbecf5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -197,6 +197,7 @@ src/session_view/room_history/typing_row.rs src/session_view/room_history/verification_info_bar.rs src/session_view/sidebar/mod.blp src/session_view/sidebar/mod.rs +src/session_view/sidebar/room_row.blp src/session_view/sidebar/room_row.rs src/session_view/sidebar/row.rs src/session_view/sidebar/section_row.rs diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs index d95cd7c2..1c37da2c 100644 --- a/src/session/room/mod.rs +++ b/src/session/room/mod.rs @@ -230,6 +230,9 @@ mod imp { /// Whether we already attempted an auto-join. #[property(get)] attempted_auto_join: Cell, + /// Whether this is a video room as defined by [MSC3417](https://github.com/matrix-org/matrix-spec-proposals/pull/3417) + #[property(get = Self::is_video_room)] + is_video_room: PhantomData, } #[glib::object_subclass] @@ -1333,6 +1336,14 @@ mod imp { .unwrap_or_default() } + /// If this is a video room according to [MSC3417](https://github.com/matrix-org/matrix-spec-proposals/pull/3417) + fn is_video_room(&self) -> bool { + self.matrix_room() + .create_content() + .and_then(|c| c.room_type) + .is_some_and(|t| t.as_str() == "org.matrix.msc3417.call") + } + /// The rules for the version of this room. pub(super) fn rules(&self) -> RoomVersionRules { self.matrix_room() diff --git a/src/session_view/sidebar/room_row.blp b/src/session_view/sidebar/room_row.blp index fab085e5..85e6693a 100644 --- a/src/session_view/sidebar/room_row.blp +++ b/src/session_view/sidebar/room_row.blp @@ -16,6 +16,29 @@ template $SidebarRoomRow: Adw.Bin { Gtk.Box display_name_box { spacing: 6; + // Show icons depending on room state, some aren't mutually exclusive, so + // the priority is: + // - Room is a video room -> video icon + // - Room is a DM -> DM icon + // - Otherwise -> no icon + Gtk.Image room_icon { + icon-name: bind $ternary_string( + template.room as <$Room>.is-video-room, + "video-symbolic", + "person-symbolic" + ) as ; + visible: bind $logical_or(template.room as <$Room>.is-video-room, template.room as <$Room>.is-direct) as ; + + styles [ + "dimmed", + ] + + tooltip-text: bind $ternary_string( + (template.room as <$Room>).is-video-room, + _("Video Room"), + _("Direct Chat") + ) as ; + } Gtk.Label display_name { ellipsize: end; diff --git a/src/session_view/sidebar/room_row.rs b/src/session_view/sidebar/room_row.rs index 9e6446ae..59161faa 100644 --- a/src/session_view/sidebar/room_row.rs +++ b/src/session_view/sidebar/room_row.rs @@ -11,8 +11,6 @@ use crate::{ }; mod imp { - use std::cell::RefCell; - use glib::subclass::InitializingObject; use super::*; @@ -29,7 +27,6 @@ mod imp { display_name: TemplateChild, #[template_child] notification_count: TemplateChild, - direct_icon: RefCell>, /// The room represented by this row. #[property(get, set = Self::set_room, explicit_notify, nullable)] room: BoundObject, @@ -108,13 +105,6 @@ mod imp { imp.update_highlight(); } )); - let direct_handler = room.connect_is_direct_notify(clone!( - #[weak(rename_to = imp)] - self, - move |_| { - imp.update_direct_icon(); - } - )); let name_handler = room.connect_display_name_notify(clone!( #[weak(rename_to = imp)] self, @@ -141,7 +131,6 @@ mod imp { room, vec![ highlight_handler, - direct_handler, name_handler, notifications_count_handler, category_handler, @@ -153,7 +142,6 @@ mod imp { self.update_display_name(); self.update_highlight(); - self.update_direct_icon(); self.obj().notify_room(); } @@ -244,26 +232,6 @@ mod imp { row.remove_css_class("drag"); } - /// Update the icon showing whether a room is direct or not. - fn update_direct_icon(&self) { - let is_direct = self.room.obj().is_some_and(|room| room.is_direct()); - - if is_direct { - if self.direct_icon.borrow().is_none() { - let icon = gtk::Image::builder() - .icon_name("person-symbolic") - .icon_size(gtk::IconSize::Normal) - .css_classes(["dimmed"]) - .build(); - - self.display_name_box.prepend(&icon); - self.direct_icon.replace(Some(icon)); - } - } else if let Some(icon) = self.direct_icon.take() { - self.display_name_box.remove(&icon); - } - } - /// Update the accessibility label of this row. fn update_accessibility_label(&self) { let Some(parent) = self.obj().parent() else { @@ -278,16 +246,28 @@ mod imp { return String::new(); }; - let name = if room.is_direct() { - gettext_f( + let name = match (room.is_video_room(), room.is_direct()) { + (true, true) => gettext_f( + // Translators: Do NOT translate the content between '{' and '}', this is a + // variable name. Presented to screen readers when a + // room is a direct chat with another user. + "Video chat with {name}", + &[("name", &room.display_name())], + ), + (false, true) => gettext_f( // Translators: Do NOT translate the content between '{' and '}', this is a // variable name. Presented to screen readers when a // room is a direct chat with another user. "Direct chat with {name}", &[("name", &room.display_name())], - ) - } else { - room.display_name() + ), + (true, false) => gettext_f( + // Translators: Do NOT translate the content between '{' and '}', this is a + // variable name. + "Video room called {room}", + &[("room", &room.display_name())], + ), + (false, false) => room.display_name(), }; if room.notification_count() > 0 {