fractal/session/view/content/room_details/members_page/
mod.rs

1use adw::{prelude::*, subclass::prelude::*};
2use gtk::{CompositeTemplate, glib};
3
4mod members_list_view;
5
6use self::members_list_view::MembersListView;
7use super::membership_lists::MembershipLists;
8use crate::session::model::{Membership, Room};
9
10mod imp {
11    use glib::subclass::InitializingObject;
12
13    use super::*;
14
15    #[derive(Debug, Default, CompositeTemplate, glib::Properties)]
16    #[template(
17        resource = "/org/gnome/Fractal/ui/session/view/content/room_details/members_page/mod.ui"
18    )]
19    #[properties(wrapper_type = super::MembersPage)]
20    pub struct MembersPage {
21        #[template_child]
22        navigation_view: TemplateChild<adw::NavigationView>,
23        /// The room containing the members.
24        #[property(get, construct_only)]
25        room: glib::WeakRef<Room>,
26        /// The lists of members filtered by membership for the room.
27        #[property(get, construct_only)]
28        membership_lists: glib::WeakRef<MembershipLists>,
29    }
30
31    #[glib::object_subclass]
32    impl ObjectSubclass for MembersPage {
33        const NAME: &'static str = "MembersPage";
34        type Type = super::MembersPage;
35        type ParentType = adw::NavigationPage;
36
37        fn class_init(klass: &mut Self::Class) {
38            Self::bind_template(klass);
39
40            klass.install_action(
41                "members.show-membership-list",
42                Some(&Membership::static_variant_type()),
43                |obj, _, param| {
44                    let Some(membership) = param.and_then(glib::Variant::get::<Membership>) else {
45                        return;
46                    };
47
48                    obj.imp().show_membership_list(membership);
49                },
50            );
51        }
52
53        fn instance_init(obj: &InitializingObject<Self>) {
54            obj.init_template();
55        }
56    }
57
58    #[glib::derived_properties]
59    impl ObjectImpl for MembersPage {
60        fn constructed(&self) {
61            self.parent_constructed();
62
63            // Initialize the first page.
64            self.show_membership_list(Membership::Join);
65        }
66    }
67
68    impl WidgetImpl for MembersPage {}
69    impl NavigationPageImpl for MembersPage {}
70
71    impl MembersPage {
72        /// Show the subpage for the list with the given membership.
73        fn show_membership_list(&self, membership: Membership) {
74            let tag = membership_as_tag(membership);
75
76            if self.navigation_view.find_page(tag).is_some() {
77                self.navigation_view.push_by_tag(tag);
78                return;
79            }
80
81            let Some(room) = self.room.upgrade() else {
82                return;
83            };
84            let Some(membership_lists) = self.membership_lists.upgrade() else {
85                return;
86            };
87
88            let subpage = MembersListView::new(&room, &membership_lists, membership);
89            self.navigation_view.push(&subpage);
90        }
91    }
92}
93
94glib::wrapper! {
95    /// A page showing the members of a room.
96    pub struct MembersPage(ObjectSubclass<imp::MembersPage>)
97        @extends gtk::Widget, adw::NavigationPage;
98}
99
100impl MembersPage {
101    /// Construct a `MembersPage` for the given room and membership lists.
102    pub fn new(room: &Room, membership_lists: &MembershipLists) -> Self {
103        glib::Object::builder()
104            .property("room", room)
105            .property("membership-lists", membership_lists)
106            .build()
107    }
108}
109
110/// Get a page tag for the given membership.
111fn membership_as_tag(membership: Membership) -> &'static str {
112    match membership {
113        Membership::Invite => "invited",
114        Membership::Ban => "banned",
115        _ => "joined",
116    }
117}