[fractal/fractal-next] members-page: Only show active members
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] members-page: Only show active members
- Date: Tue, 1 Feb 2022 08:55:59 +0000 (UTC)
commit 34f71ce741340cb83aa1240ef7dc35b2c162b42c
Author: Kévin Commaille <zecakeh tedomum fr>
Date: Tue Feb 1 09:17:26 2022 +0100
members-page: Only show active members
Separate joined and invited in two lists
data/resources/ui/content-member-page.ui | 27 ++++-
.../content/room_details/member_page/mod.rs | 110 ++++++++++++++++++---
src/session/room/member.rs | 88 +++++++++++++++--
src/session/room/mod.rs | 2 +-
4 files changed, 200 insertions(+), 27 deletions(-)
---
diff --git a/data/resources/ui/content-member-page.ui b/data/resources/ui/content-member-page.ui
index cf9f4dcc..7f43a4b9 100644
--- a/data/resources/ui/content-member-page.ui
+++ b/data/resources/ui/content-member-page.ui
@@ -34,8 +34,9 @@
</object>
</child>
<child>
- <object class="GtkScrolledWindow">
+ <object class="GtkScrolledWindow" id="members_scroll">
<property name="propagate-natural-height">True</property>
+ <property name="max-content-height">300</property>
<child>
<object class="GtkListView" id="members_list_view">
<property name="show-separators">True</property>
@@ -53,6 +54,28 @@
</child>
</object>
</child>
+ <child>
+ <object class="AdwPreferencesGroup" id="invited_section">
+ <child>
+ <object class="GtkScrolledWindow" id="invited_scroll">
+ <property name="propagate-natural-height">True</property>
+ <property name="max-content-height">300</property>
+ <child>
+ <object class="GtkListView" id="invited_list_view">
+ <property name="show-separators">True</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="resource">/org/gnome/FractalNext/content-member-item.ui</property>
+ </object>
+ </property>
+ <style>
+ <class name="content"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
</template>
</interface>
-
diff --git a/src/session/content/room_details/member_page/mod.rs
b/src/session/content/room_details/member_page/mod.rs
index de6b601c..fbd20ea0 100644
--- a/src/session/content/room_details/member_page/mod.rs
+++ b/src/session/content/room_details/member_page/mod.rs
@@ -5,10 +5,10 @@ use gtk::{
subclass::prelude::*,
CompositeTemplate,
};
+use log::warn;
mod member_menu;
mod member_row;
-use log::warn;
use self::{member_menu::MemberMenu, member_row::MemberRow};
use crate::{
@@ -16,12 +16,14 @@ use crate::{
prelude::*,
session::{
content::RoomDetails,
- room::{Member, RoomAction},
+ room::{Member, Membership, RoomAction},
Room, User, UserActions,
},
spawn,
};
+const MAX_LIST_HEIGHT: i32 = 300;
+
mod imp {
use glib::subclass::InitializingObject;
use once_cell::{sync::Lazy, unsync::OnceCell};
@@ -40,7 +42,15 @@ mod imp {
pub members_search_entry: TemplateChild<gtk::SearchEntry>,
#[template_child]
pub members_list_view: TemplateChild<gtk::ListView>,
+ #[template_child]
+ pub members_scroll: TemplateChild<gtk::ScrolledWindow>,
pub member_menu: OnceCell<MemberMenu>,
+ #[template_child]
+ pub invited_section: TemplateChild<adw::PreferencesGroup>,
+ #[template_child]
+ pub invited_list_view: TemplateChild<gtk::ListView>,
+ #[template_child]
+ pub invited_scroll: TemplateChild<gtk::ScrolledWindow>,
}
#[glib::object_subclass]
@@ -117,8 +127,8 @@ mod imp {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
- obj.init_member_search();
- obj.init_member_count();
+ obj.init_members_list();
+ obj.init_invited_list();
obj.init_invite_button();
}
}
@@ -144,10 +154,28 @@ impl MemberPage {
self.imp().room.set(room).expect("Room already initialized");
}
- fn init_member_search(&self) {
+ fn init_members_list(&self) {
let priv_ = self.imp();
let members = self.room().members();
+ // Only keep the members that are in the join membership state
+ let joined_expression = gtk::PropertyExpression::new(
+ Member::static_type(),
+ gtk::Expression::NONE,
+ "membership",
+ )
+ .chain_closure::<bool>(closure!(
+ |_: Option<glib::Object>, membership: Membership| { membership == Membership::Join }
+ ));
+ let joined_filter = gtk::BoolFilter::new(Some(joined_expression));
+ let joined_members = gtk::FilterListModel::new(Some(members), Some(&joined_filter));
+
+ // Set up the members count.
+ self.member_count_changed(joined_members.n_items());
+ joined_members.connect_items_changed(clone!(@weak self as obj => move |members, _, _, _| {
+ obj.member_count_changed(members.n_items());
+ }));
+
// Sort the members list by power level, then display name.
let sorter = gtk::MultiSorter::new();
sorter.append(
@@ -167,7 +195,7 @@ impl MemberPage {
"display-name",
),
)));
- let sorted_members = gtk::SortListModel::new(Some(members), Some(&sorter));
+ let sorted_members = gtk::SortListModel::new(Some(&joined_members), Some(&sorter));
fn search_string(member: Member) -> String {
format!(
@@ -199,17 +227,71 @@ impl MemberPage {
priv_.members_list_view.set_model(Some(&model));
}
- fn init_member_count(&self) {
+ fn member_count_changed(&self, n: u32) {
+ let priv_ = self.imp();
+ priv_
+ .member_count
+ .set_text(&ngettext!("{} Member", "{} Members", n, n));
+ // FIXME: This won't be needed when we can request the natural height
+ // on AdwPreferencesPage
+ // See: https://gitlab.gnome.org/GNOME/libadwaita/-/issues/77
+ if n > 5 {
+ priv_.members_scroll.set_min_content_height(MAX_LIST_HEIGHT);
+ } else {
+ priv_.members_scroll.set_min_content_height(-1);
+ }
+ }
+
+ fn init_invited_list(&self) {
+ let priv_ = self.imp();
let members = self.room().members();
- let member_count = self.imp().member_count.get();
- fn set_member_count(member_count: >k::Label, n: u32) {
- member_count.set_text(&ngettext!("{} Member", "{} Members", n, n));
+ // Only keep the members that are in the join membership state
+ let invited_expression = gtk::PropertyExpression::new(
+ Member::static_type(),
+ gtk::Expression::NONE,
+ "membership",
+ )
+ .chain_closure::<bool>(closure!(
+ |_: Option<glib::Object>, membership: Membership| { membership == Membership::Invite }
+ ));
+ let invited_filter = gtk::BoolFilter::new(Some(invited_expression));
+ let invited_members = gtk::FilterListModel::new(Some(members), Some(&invited_filter));
+
+ // Set up the invited section visibility and the invited count.
+ self.invited_count_changed(invited_members.n_items());
+ invited_members.connect_items_changed(
+ clone!(@weak self as obj => move |members, _, _, _| {
+ obj.invited_count_changed(members.n_items());
+ }),
+ );
+
+ // Sort the invited list by display name.
+ let sorter = gtk::StringSorter::new(Some(>k::PropertyExpression::new(
+ Member::static_type(),
+ gtk::Expression::NONE,
+ "display-name",
+ )));
+ let sorted_invited = gtk::SortListModel::new(Some(&invited_members), Some(&sorter));
+
+ let model = gtk::NoSelection::new(Some(&sorted_invited));
+ priv_.invited_list_view.set_model(Some(&model));
+ }
+
+ fn invited_count_changed(&self, n: u32) {
+ let priv_ = self.imp();
+ priv_.invited_section.set_visible(n > 0);
+ priv_
+ .invited_section
+ .set_title(&ngettext!("{} Invited", "{} Invited", n, n));
+ // FIXME: This won't be needed when we can request the natural height
+ // on AdwPreferencesPage
+ // See: https://gitlab.gnome.org/GNOME/libadwaita/-/issues/77
+ if n > 5 {
+ priv_.invited_scroll.set_min_content_height(MAX_LIST_HEIGHT);
+ } else {
+ priv_.invited_scroll.set_min_content_height(-1);
}
- set_member_count(&member_count, members.n_items());
- members.connect_items_changed(clone!(@weak member_count => move |members, _, _, _| {
- set_member_count(&member_count, members.n_items());
- }));
}
fn init_invite_button(&self) {
diff --git a/src/session/room/member.rs b/src/session/room/member.rs
index 90ea62b2..6e9f3394 100644
--- a/src/session/room/member.rs
+++ b/src/session/room/member.rs
@@ -1,7 +1,10 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
use matrix_sdk::{
ruma::{
- events::{room::member::RoomMemberEventContent, StrippedStateEvent, SyncStateEvent},
+ events::{
+ room::member::{MembershipState, RoomMemberEventContent},
+ StrippedStateEvent, SyncStateEvent,
+ },
identifiers::{MxcUri, UserId},
},
RoomMember,
@@ -18,6 +21,43 @@ use crate::{
},
};
+#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)]
+#[repr(u32)]
+#[enum_type(name = "Membership")]
+pub enum Membership {
+ Leave = 0,
+ Join = 1,
+ Invite = 2,
+ Ban = 3,
+ Knock = 4,
+ Custom = 5,
+}
+
+impl Default for Membership {
+ fn default() -> Self {
+ Membership::Leave
+ }
+}
+
+impl From<&MembershipState> for Membership {
+ fn from(state: &MembershipState) -> Self {
+ match state {
+ MembershipState::Leave => Membership::Leave,
+ MembershipState::Join => Membership::Join,
+ MembershipState::Invite => Membership::Invite,
+ MembershipState::Ban => Membership::Ban,
+ MembershipState::Knock => Membership::Knock,
+ _ => Membership::Custom,
+ }
+ }
+}
+
+impl From<MembershipState> for Membership {
+ fn from(state: MembershipState) -> Self {
+ Membership::from(&state)
+ }
+}
+
mod imp {
use std::cell::Cell;
@@ -28,6 +68,7 @@ mod imp {
#[derive(Debug, Default)]
pub struct Member {
pub power_level: Cell<PowerLevel>,
+ pub membership: Cell<Membership>,
}
#[glib::object_subclass]
@@ -40,15 +81,25 @@ mod imp {
impl ObjectImpl for Member {
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
- vec![glib::ParamSpecInt64::new(
- "power-level",
- "Power level",
- "Power level of the member in its room.",
- POWER_LEVEL_MIN,
- POWER_LEVEL_MAX,
- 0,
- glib::ParamFlags::READABLE | glib::ParamFlags::EXPLICIT_NOTIFY,
- )]
+ vec![
+ glib::ParamSpecInt64::new(
+ "power-level",
+ "Power level",
+ "Power level of the member in its room.",
+ POWER_LEVEL_MIN,
+ POWER_LEVEL_MAX,
+ 0,
+ glib::ParamFlags::READABLE | glib::ParamFlags::EXPLICIT_NOTIFY,
+ ),
+ glib::ParamSpecEnum::new(
+ "membership",
+ "Membership",
+ "This member's membership state.",
+ Membership::static_type(),
+ Membership::default() as i32,
+ glib::ParamFlags::READABLE | glib::ParamFlags::EXPLICIT_NOTIFY,
+ ),
+ ]
});
PROPERTIES.as_ref()
@@ -57,6 +108,7 @@ mod imp {
fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"power-level" => obj.power_level().to_value(),
+ "membership" => obj.membership().to_value(),
_ => unimplemented!(),
}
}
@@ -103,6 +155,20 @@ impl Member {
self.role().is_peasant()
}
+ pub fn membership(&self) -> Membership {
+ let priv_ = imp::Member::from_instance(self);
+ priv_.membership.get()
+ }
+
+ fn set_membership(&self, membership: Membership) {
+ if self.membership() == membership {
+ return;
+ }
+ let priv_ = imp::Member::from_instance(self);
+ priv_.membership.replace(membership);
+ self.notify("membership");
+ }
+
/// Update the user based on the the room member state event
pub fn update_from_room_member(&self, member: &RoomMember) {
if member.user_id() != &*self.user_id() {
@@ -114,6 +180,7 @@ impl Member {
self.avatar()
.set_url(member.avatar_url().map(std::borrow::ToOwned::to_owned));
self.set_power_level(member.power_level());
+ self.set_membership(member.membership().into());
}
/// Update the user based on the the room member state event
@@ -125,6 +192,7 @@ impl Member {
self.set_display_name(event.display_name());
self.avatar().set_url(event.avatar_url());
+ self.set_membership((&event.content().membership).into());
}
}
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index c3733b85..6e447364 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -48,7 +48,7 @@ pub use self::{
event_actions::EventActions,
highlight_flags::HighlightFlags,
item::{Item, ItemType},
- member::Member,
+ member::{Member, Membership},
member_role::MemberRole,
power_levels::{PowerLevel, PowerLevels, RoomAction, POWER_LEVEL_MAX, POWER_LEVEL_MIN},
reaction_group::ReactionGroup,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]