fractal/session/view/account_settings/general_page/
deactivate_account_subpage.rsuse adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::{glib, glib::clone, CompositeTemplate};
use tracing::error;
use url::Url;
use super::AccountSettings;
use crate::{
components::{AuthDialog, LoadingButtonRow},
prelude::*,
session::model::Session,
toast,
utils::oidc,
};
mod imp {
use glib::subclass::InitializingObject;
use super::*;
#[derive(Debug, Default, CompositeTemplate, glib::Properties)]
#[template(
resource = "/org/gnome/Fractal/ui/session/view/account_settings/general_page/deactivate_account_subpage.ui"
)]
#[properties(wrapper_type = super::DeactivateAccountSubpage)]
pub struct DeactivateAccountSubpage {
#[template_child]
confirmation: TemplateChild<adw::EntryRow>,
#[template_child]
loading_button: TemplateChild<LoadingButtonRow>,
#[template_child]
open_url_button: TemplateChild<adw::ButtonRow>,
#[property(get, set = Self::set_session, construct_only)]
session: glib::WeakRef<Session>,
#[property(get, set = Self::set_account_settings, construct_only)]
account_settings: glib::WeakRef<AccountSettings>,
}
#[glib::object_subclass]
impl ObjectSubclass for DeactivateAccountSubpage {
const NAME: &'static str = "DeactivateAccountSubpage";
type Type = super::DeactivateAccountSubpage;
type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
Self::bind_template_callbacks(klass);
}
fn instance_init(obj: &InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for DeactivateAccountSubpage {}
impl WidgetImpl for DeactivateAccountSubpage {}
impl NavigationPageImpl for DeactivateAccountSubpage {}
#[gtk::template_callbacks]
impl DeactivateAccountSubpage {
fn set_session(&self, session: &Session) {
self.session.set(Some(session));
self.confirmation.set_title(session.user_id().as_str());
}
fn set_account_settings(&self, account_settings: &AccountSettings) {
self.account_settings.set(Some(account_settings));
account_settings.connect_account_management_url_changed(clone!(
#[weak(rename_to = imp)]
self,
move |_| {
imp.update_visible_button();
}
));
self.update_visible_button();
}
fn account_management_url(&self) -> Option<Url> {
self.account_settings
.upgrade()
.and_then(|s| s.account_management_url())
}
fn update_visible_button(&self) {
let should_open_url = self.account_management_url().is_some();
self.loading_button.set_visible(!should_open_url);
self.open_url_button.set_visible(should_open_url);
}
#[template_callback]
fn update_buttons_state(&self) {
let sensitive = self.can_deactivate_account();
self.loading_button.set_sensitive(sensitive);
self.open_url_button.set_sensitive(sensitive);
}
fn can_deactivate_account(&self) -> bool {
self.confirmation.text() == self.confirmation.title()
}
#[template_callback]
async fn deactivate_account(&self) {
if self.account_management_url().is_some() {
self.open_deactivate_account_url().await;
} else {
self.deactivate_account_with_request().await;
}
}
#[template_callback]
async fn deactivate_account_with_request(&self) {
let Some(session) = self.session.upgrade() else {
return;
};
if !self.can_deactivate_account() {
return;
}
self.loading_button.set_is_loading(true);
self.confirmation.set_sensitive(false);
let dialog = AuthDialog::new(&session);
let obj = self.obj();
let result = dialog
.authenticate(&*obj, move |client, auth| async move {
client
.account()
.deactivate(None, auth, false)
.await
.map_err(Into::into)
})
.await;
match result {
Ok(_) => {
if let Some(session) = self.session.upgrade() {
if let Some(window) = obj.root().and_downcast_ref::<gtk::Window>() {
toast!(window, gettext("Account successfully deactivated"));
}
session.clean_up().await;
}
let _ = obj.activate_action("account-settings.close", None);
}
Err(error) => {
error!("Could not deactivate account: {error:?}");
toast!(obj, gettext("Could not deactivate account"));
}
}
self.loading_button.set_is_loading(false);
self.confirmation.set_sensitive(true);
}
#[template_callback]
async fn open_deactivate_account_url(&self) {
let Some(mut url) = self.account_management_url() else {
error!("Could not find open account management URL");
return;
};
oidc::AccountManagementAction::AccountDeactivate
.add_to_account_management_url(&mut url);
if let Err(error) = gtk::UriLauncher::new(url.as_ref())
.launch_future(self.obj().root().and_downcast_ref::<gtk::Window>())
.await
{
error!("Could not launch account management URL: {error}");
}
}
}
}
glib::wrapper! {
pub struct DeactivateAccountSubpage(ObjectSubclass<imp::DeactivateAccountSubpage>)
@extends gtk::Widget, adw::NavigationPage, @implements gtk::Accessible;
}
impl DeactivateAccountSubpage {
pub fn new(session: &Session, account_settings: &AccountSettings) -> Self {
glib::Object::builder()
.property("session", session)
.property("account-settings", account_settings)
.build()
}
}