fractal/session/view/content/room_details/
mod.rs#![allow(deprecated)]
use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::{glib, glib::clone, CompositeTemplate};
use ruma::UserId;
mod addresses_subpage;
mod edit_details_subpage;
mod general_page;
mod history_viewer;
mod invite_subpage;
mod member_row;
mod members_page;
mod membership_lists;
mod membership_subpage_item;
mod permissions;
mod room_upgrade_dialog;
use self::{
addresses_subpage::AddressesSubpage,
edit_details_subpage::EditDetailsSubpage,
general_page::GeneralPage,
history_viewer::{
AudioHistoryViewer, FileHistoryViewer, HistoryViewerTimeline, VisualMediaHistoryViewer,
},
invite_subpage::InviteSubpage,
member_row::MemberRow,
members_page::MembersPage,
membership_lists::MembershipLists,
membership_subpage_item::MembershipSubpageItem,
permissions::PermissionsSubpage,
};
use crate::{components::UserPage, session::model::Room, toast};
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, glib::Variant)]
pub enum SubpageName {
EditDetails,
Members,
Invite,
VisualMediaHistory,
FileHistory,
AudioHistory,
Addresses,
Permissions,
}
mod imp {
use std::{
cell::{OnceCell, RefCell},
collections::HashMap,
};
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(resource = "/org/gnome/Fractal/ui/session/view/content/room_details/mod.ui")]
#[properties(wrapper_type = super::RoomDetails)]
pub struct RoomDetails {
#[property(get, set = Self::set_room, construct_only)]
room: OnceCell<Room>,
#[property(get)]
membership_lists: MembershipLists,
#[property(get)]
timeline: OnceCell<HistoryViewerTimeline>,
general_page: OnceCell<GeneralPage>,
subpages: RefCell<HashMap<SubpageName, adw::NavigationPage>>,
}
#[glib::object_subclass]
impl ObjectSubclass for RoomDetails {
const NAME: &'static str = "RoomDetails";
type Type = super::RoomDetails;
type ParentType = adw::PreferencesWindow;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
klass.install_action(
"details.show-subpage",
Some(&String::static_variant_type()),
|obj, _, param| {
let subpage = param
.and_then(glib::Variant::get::<SubpageName>)
.expect("The parameter should be a valid subpage name");
obj.imp().show_subpage(subpage, false);
},
);
klass.install_action(
"details.show-member",
Some(&String::static_variant_type()),
|obj, _, param| {
let Some(user_id) = param
.and_then(glib::Variant::get::<String>)
.and_then(|s| UserId::parse(s).ok())
else {
return;
};
let member = obj.membership_lists().members().get_or_create(user_id);
let user_page = UserPage::new(&member);
user_page.connect_close(clone!(
#[weak]
obj,
move |_| {
obj.pop_subpage();
toast!(
obj,
gettext("The user is not in the room members list anymore")
);
}
));
obj.push_subpage(&user_page);
},
);
klass.install_action("win.toggle-fullscreen", None, |obj, _, _| {
if obj.is_fullscreen() {
obj.unfullscreen();
} else {
obj.fullscreen();
}
});
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for RoomDetails {}
impl WidgetImpl for RoomDetails {
fn map(&self) {
self.parent_map();
self.general_page
.get()
.expect("general page is initialized")
.unselect_topic();
}
}
impl WindowImpl for RoomDetails {}
impl AdwWindowImpl for RoomDetails {}
impl PreferencesWindowImpl for RoomDetails {}
impl RoomDetails {
fn set_room(&self, room: Room) {
let room = self.room.get_or_init(|| room);
self.timeline
.set(HistoryViewerTimeline::new(room))
.expect("timeline is uninitialized");
self.membership_lists
.set_members(room.get_or_create_members());
let general_page = self
.general_page
.get_or_init(|| GeneralPage::new(room, &self.membership_lists));
self.obj().add(general_page);
}
fn timeline(&self) -> &HistoryViewerTimeline {
self.timeline.get().expect("timeline is initialized")
}
pub(super) fn show_subpage(&self, name: SubpageName, is_initial: bool) {
let room = self.room.get().expect("room is initialized");
let mut subpages = self.subpages.borrow_mut();
let subpage = subpages.entry(name).or_insert_with(|| match name {
SubpageName::EditDetails => EditDetailsSubpage::new(room).upcast(),
SubpageName::Members => MembersPage::new(room, &self.membership_lists).upcast(),
SubpageName::Invite => InviteSubpage::new(room).upcast(),
SubpageName::VisualMediaHistory => {
VisualMediaHistoryViewer::new(self.timeline()).upcast()
}
SubpageName::FileHistory => FileHistoryViewer::new(self.timeline()).upcast(),
SubpageName::AudioHistory => AudioHistoryViewer::new(self.timeline()).upcast(),
SubpageName::Addresses => AddressesSubpage::new(room).upcast(),
SubpageName::Permissions => PermissionsSubpage::new(&room.permissions()).upcast(),
});
if is_initial {
subpage.set_can_pop(false);
}
self.obj().push_subpage(subpage);
}
}
}
glib::wrapper! {
pub struct RoomDetails(ObjectSubclass<imp::RoomDetails>)
@extends gtk::Widget, gtk::Window, adw::Window, gtk::Root, adw::PreferencesWindow,
@implements gtk::Accessible;
}
impl RoomDetails {
pub fn new(parent_window: Option<>k::Window>, room: &Room) -> Self {
glib::Object::builder()
.property("transient-for", parent_window)
.property("room", room)
.build()
}
pub fn show_initial_subpage(&self, name: SubpageName) {
self.imp().show_subpage(name, true);
}
}