use adw::{prelude::*, subclass::prelude::*};
use gtk::{glib, glib::clone, CompositeTemplate};
use tracing::error;
mod ignored_user_row;
use self::ignored_user_row::IgnoredUserRow;
use crate::session::model::Session;
mod imp {
use std::cell::RefCell;
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(
resource = "/org/gnome/Fractal/ui/session/view/account_settings/security_page/ignored_users_subpage/mod.ui"
)]
#[properties(wrapper_type = super::IgnoredUsersSubpage)]
pub struct IgnoredUsersSubpage {
#[template_child]
pub stack: TemplateChild<gtk::Stack>,
#[template_child]
pub search_bar: TemplateChild<gtk::SearchBar>,
#[template_child]
pub search_entry: TemplateChild<gtk::SearchEntry>,
#[template_child]
pub list_view: TemplateChild<gtk::ListView>,
pub filtered_model: gtk::FilterListModel,
#[property(get, set = Self::set_session, explicit_notify, nullable)]
pub session: glib::WeakRef<Session>,
pub items_changed_handler: RefCell<Option<glib::SignalHandlerId>>,
}
#[glib::object_subclass]
impl ObjectSubclass for IgnoredUsersSubpage {
const NAME: &'static str = "IgnoredUsersSubpage";
type Type = super::IgnoredUsersSubpage;
type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for IgnoredUsersSubpage {
fn constructed(&self) {
self.parent_constructed();
self.search_bar.connect_entry(&*self.search_entry);
let search_filter = gtk::StringFilter::builder()
.match_mode(gtk::StringFilterMatchMode::Substring)
.expression(gtk::StringObject::this_expression("string"))
.ignore_case(true)
.build();
self.search_entry
.bind_property("text", &search_filter, "search")
.sync_create()
.build();
self.filtered_model.set_filter(Some(&search_filter));
let factory = gtk::SignalListItemFactory::new();
factory.connect_setup(clone!(
#[weak(rename_to = imp)]
self,
move |_, item| {
let Some(session) = imp.session.upgrade() else {
return;
};
let Some(item) = item.downcast_ref::<gtk::ListItem>() else {
error!("List item factory did not receive a list item: {item:?}");
return;
};
let row = IgnoredUserRow::new(&session.ignored_users());
item.set_child(Some(&row));
item.bind_property("item", &row, "item").build();
item.set_activatable(false);
item.set_selectable(false);
}
));
self.list_view.set_factory(Some(&factory));
self.list_view.set_model(Some(>k::NoSelection::new(Some(
self.filtered_model.clone(),
))));
}
fn dispose(&self) {
if let Some(session) = self.session.upgrade() {
if let Some(handler) = self.items_changed_handler.take() {
session.ignored_users().disconnect(handler);
}
}
}
}
impl WidgetImpl for IgnoredUsersSubpage {}
impl NavigationPageImpl for IgnoredUsersSubpage {}
impl IgnoredUsersSubpage {
fn set_session(&self, session: Option<Session>) {
let prev_session = self.session.upgrade();
if prev_session == session {
return;
}
if let Some(session) = prev_session {
if let Some(handler) = self.items_changed_handler.take() {
session.ignored_users().disconnect(handler);
}
}
let ignored_users = session.as_ref().map(|s| s.ignored_users());
if let Some(ignored_users) = &ignored_users {
let items_changed_handler = ignored_users.connect_items_changed(clone!(
#[weak(rename_to = imp)]
self,
move |_, _, _, _| {
imp.update_visible_page();
}
));
self.items_changed_handler
.replace(Some(items_changed_handler));
}
self.filtered_model.set_model(ignored_users.as_ref());
self.session.set(session.as_ref());
self.obj().notify_session();
self.update_visible_page();
}
fn update_visible_page(&self) {
let has_users = self
.session
.upgrade()
.is_some_and(|s| s.ignored_users().n_items() > 0);
let page = if has_users { "list" } else { "empty" };
self.stack.set_visible_child_name(page);
}
}
}
glib::wrapper! {
pub struct IgnoredUsersSubpage(ObjectSubclass<imp::IgnoredUsersSubpage>)
@extends gtk::Widget, adw::NavigationPage;
}
impl IgnoredUsersSubpage {
pub fn new(session: &Session) -> Self {
glib::Object::builder().property("session", session).build()
}
}