fractal/session/view/content/room_details/permissions/
member_power_level.rs1use adw::subclass::prelude::*;
2use gtk::{glib, glib::clone, prelude::*};
3use ruma::{Int, OwnedUserId, events::room::power_levels::PowerLevelUserAction};
4
5use crate::{
6 prelude::*,
7 session::model::{MemberRole, POWER_LEVEL_MAX, POWER_LEVEL_MIN, Permissions, PowerLevel, User},
8 utils::BoundObjectWeakRef,
9};
10
11mod imp {
12 use std::cell::{Cell, OnceCell};
13
14 use super::*;
15
16 #[derive(Debug, Default, glib::Properties)]
17 #[properties(wrapper_type = super::MemberPowerLevel)]
18 pub struct MemberPowerLevel {
19 #[property(get, set = Self::set_permissions, construct_only)]
21 permissions: BoundObjectWeakRef<Permissions>,
22 #[property(get, construct_only)]
24 user: OnceCell<User>,
25 #[property(get, set = Self::set_power_level, explicit_notify, minimum = POWER_LEVEL_MIN, maximum = POWER_LEVEL_MAX)]
30 power_level: Cell<PowerLevel>,
31 #[property(get, builder(MemberRole::default()))]
33 role: Cell<MemberRole>,
34 #[property(get)]
36 editable: Cell<bool>,
37 }
38
39 #[glib::object_subclass]
40 impl ObjectSubclass for MemberPowerLevel {
41 const NAME: &'static str = "RoomDetailsPermissionsMemberPowerLevel";
42 type Type = super::MemberPowerLevel;
43 }
44
45 #[glib::derived_properties]
46 impl ObjectImpl for MemberPowerLevel {
47 fn constructed(&self) {
48 self.parent_constructed();
49
50 self.update_power_level();
51 self.update_role();
52 self.update_editable();
53 }
54 }
55
56 impl MemberPowerLevel {
57 fn set_permissions(&self, permissions: &Permissions) {
59 let changed_handler = permissions.connect_changed(clone!(
60 #[weak(rename_to = imp)]
61 self,
62 move |_| {
63 imp.update_power_level();
64 imp.update_role();
65 imp.update_editable();
66 }
67 ));
68 self.permissions.set(permissions, vec![changed_handler]);
69 }
70
71 fn update_power_level(&self) {
73 let Some(user) = self.user.get() else {
74 return;
75 };
76 let Some(permissions) = self.permissions.obj() else {
77 return;
78 };
79
80 self.set_power_level(permissions.user_power_level(user.user_id()));
81 }
82
83 fn set_power_level(&self, power_level: PowerLevel) {
85 if self.power_level.get() == power_level {
86 return;
87 }
88
89 self.power_level.set(power_level);
90 self.update_role();
91 self.obj().notify_power_level();
92 }
93
94 fn update_role(&self) {
96 let Some(permissions) = self.permissions.obj() else {
97 return;
98 };
99
100 let role = permissions.role(self.power_level.get());
101
102 if self.role.get() == role {
103 return;
104 }
105
106 self.role.set(role);
107 self.obj().notify_role();
108 }
109
110 fn update_editable(&self) {
112 let Some(user) = self.user.get() else {
113 return;
114 };
115 let Some(permissions) = self.permissions.obj() else {
116 return;
117 };
118
119 let editable =
120 permissions.can_do_to_user(user.user_id(), PowerLevelUserAction::ChangePowerLevel);
121
122 if self.editable.get() == editable {
123 return;
124 }
125
126 self.editable.set(editable);
127 self.obj().notify_editable();
128 }
129 }
130}
131
132glib::wrapper! {
133 pub struct MemberPowerLevel(ObjectSubclass<imp::MemberPowerLevel>);
135}
136
137impl MemberPowerLevel {
138 pub fn new(user: &impl IsA<User>, permissions: &Permissions) -> Self {
140 glib::Object::builder()
141 .property("user", user)
142 .property("permissions", permissions)
143 .build()
144 }
145
146 pub(crate) fn to_parts(&self) -> Option<(OwnedUserId, Int)> {
151 let permissions = self.permissions()?;
152
153 let users_default = permissions.default_power_level();
154 let pl = self.power_level();
155
156 if pl == users_default {
157 return None;
158 }
159
160 Some((self.user().user_id().clone(), Int::new_saturating(pl)))
161 }
162
163 pub(crate) fn search_string(&self) -> String {
165 let user = self.user();
166 format!(
167 "{} {} {} {}",
168 user.display_name(),
169 user.user_id(),
170 self.role(),
171 self.power_level(),
172 )
173 }
174}