fractal/session/view/content/room_details/permissions/
member_power_level.rsuse adw::subclass::prelude::*;
use gtk::{glib, glib::clone, prelude::*};
use ruma::{events::room::power_levels::PowerLevelUserAction, Int, OwnedUserId};
use crate::{
prelude::*,
session::model::{MemberRole, Permissions, PowerLevel, User, POWER_LEVEL_MAX, POWER_LEVEL_MIN},
utils::BoundObjectWeakRef,
};
mod imp {
use std::cell::{Cell, OnceCell};
use super::*;
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::MemberPowerLevel)]
pub struct MemberPowerLevel {
#[property(get, set = Self::set_permissions, construct_only)]
pub permissions: BoundObjectWeakRef<Permissions>,
#[property(get, construct_only)]
pub user: OnceCell<User>,
#[property(get, set = Self::set_power_level, explicit_notify, minimum = POWER_LEVEL_MIN, maximum = POWER_LEVEL_MAX)]
pub power_level: Cell<PowerLevel>,
#[property(get, builder(MemberRole::default()))]
pub role: Cell<MemberRole>,
#[property(get)]
pub editable: Cell<bool>,
}
#[glib::object_subclass]
impl ObjectSubclass for MemberPowerLevel {
const NAME: &'static str = "RoomDetailsPermissionsMemberPowerLevel";
type Type = super::MemberPowerLevel;
}
#[glib::derived_properties]
impl ObjectImpl for MemberPowerLevel {
fn constructed(&self) {
self.parent_constructed();
self.update_power_level();
self.update_role();
self.update_editable();
}
}
impl MemberPowerLevel {
fn set_permissions(&self, permissions: &Permissions) {
let changed_handler = permissions.connect_changed(clone!(
#[weak(rename_to = imp)]
self,
move |_| {
imp.update_power_level();
imp.update_role();
imp.update_editable();
}
));
self.permissions.set(permissions, vec![changed_handler]);
}
fn update_power_level(&self) {
let Some(user) = self.user.get() else {
return;
};
let Some(permissions) = self.permissions.obj() else {
return;
};
let power_levels = permissions.power_levels();
let power_level = power_levels.for_user(user.user_id());
self.set_power_level(power_level.into());
}
fn set_power_level(&self, power_level: PowerLevel) {
if self.power_level.get() == power_level {
return;
}
self.power_level.set(power_level);
self.update_role();
self.obj().notify_power_level();
}
fn update_role(&self) {
let Some(permissions) = self.permissions.obj() else {
return;
};
let role = permissions.role(self.power_level.get());
if self.role.get() == role {
return;
}
self.role.set(role);
self.obj().notify_role();
}
fn update_editable(&self) {
let Some(user) = self.user.get() else {
return;
};
let Some(permissions) = self.permissions.obj() else {
return;
};
let editable =
permissions.can_do_to_user(user.user_id(), PowerLevelUserAction::ChangePowerLevel);
if self.editable.get() == editable {
return;
}
self.editable.set(editable);
self.obj().notify_editable();
}
}
}
glib::wrapper! {
pub struct MemberPowerLevel(ObjectSubclass<imp::MemberPowerLevel>);
}
impl MemberPowerLevel {
pub fn new(user: &impl IsA<User>, permissions: &Permissions) -> Self {
glib::Object::builder()
.property("user", user)
.property("permissions", permissions)
.build()
}
pub fn to_parts(&self) -> Option<(OwnedUserId, Int)> {
let permissions = self.permissions()?;
let users_default = permissions.default_power_level();
let pl = self.power_level();
if pl == users_default {
return None;
}
Some((self.user().user_id().clone(), Int::new_saturating(pl)))
}
}