fractal/
error_page.rs

1use adw::{prelude::*, subclass::prelude::*};
2use gettextrs::gettext;
3use gtk::glib;
4
5use crate::{APP_ID, toast};
6
7/// The possible error subpages.
8#[derive(Debug, Clone, Copy, strum::AsRefStr)]
9#[strum(serialize_all = "kebab-case")]
10pub enum ErrorSubpage {
11    /// The page to present when there was an error with the secret API.
12    Secret,
13    /// The page to present when there was an error when initializing a session.
14    Session,
15}
16
17mod imp {
18    use glib::subclass::InitializingObject;
19
20    use super::*;
21
22    #[derive(Debug, Default, gtk::CompositeTemplate)]
23    #[template(resource = "/org/gnome/Fractal/ui/error_page.ui")]
24    pub struct ErrorPage {
25        #[template_child]
26        stack: TemplateChild<gtk::Stack>,
27        #[template_child]
28        secret_error_page: TemplateChild<adw::StatusPage>,
29        #[template_child]
30        linux_secret_instructions: TemplateChild<adw::Clamp>,
31        #[template_child]
32        secret_service_override_command: TemplateChild<gtk::Label>,
33        #[template_child]
34        session_error_page: TemplateChild<adw::StatusPage>,
35    }
36
37    #[glib::object_subclass]
38    impl ObjectSubclass for ErrorPage {
39        const NAME: &'static str = "ErrorPage";
40        type Type = super::ErrorPage;
41        type ParentType = adw::Bin;
42
43        fn class_init(klass: &mut Self::Class) {
44            Self::bind_template(klass);
45            Self::bind_template_callbacks(klass);
46
47            klass.set_accessible_role(gtk::AccessibleRole::Group);
48        }
49
50        fn instance_init(obj: &InitializingObject<Self>) {
51            obj.init_template();
52        }
53    }
54
55    impl ObjectImpl for ErrorPage {}
56    impl WidgetImpl for ErrorPage {}
57    impl BinImpl for ErrorPage {}
58
59    #[gtk::template_callbacks]
60    impl ErrorPage {
61        /// Display the given secret error.
62        pub(super) fn display_secret_error(&self, message: &str) {
63            #[cfg(not(target_os = "linux"))]
64            self.linux_secret_instructions.set_visible(false);
65
66            #[cfg(target_os = "linux")]
67            {
68                self.linux_secret_instructions.set_visible(true);
69
70                self.secret_service_override_command.set_markup(&format!(
71                    "<tt>flatpak --user override --talk-name=org.freedesktop.secrets {APP_ID}</tt>",
72                ));
73            }
74
75            self.secret_error_page.set_description(Some(message));
76            self.stack
77                .set_visible_child_name(ErrorSubpage::Secret.as_ref());
78        }
79
80        /// Display the given session error.
81        pub(super) fn display_session_error(&self, message: &str) {
82            self.session_error_page.set_description(Some(message));
83            self.stack
84                .set_visible_child_name(ErrorSubpage::Session.as_ref());
85        }
86
87        /// Copy the secret service override command to the clipboard.
88        #[template_callback]
89        fn copy_secret_service_override_command(&self) {
90            let obj = self.obj();
91            let command = self.secret_service_override_command.label();
92            obj.clipboard()
93                .set_text(command.trim_start_matches("<tt>").trim_end_matches("</tt>"));
94            toast!(obj, gettext("Command copied to clipboard"));
95        }
96    }
97}
98
99glib::wrapper! {
100    /// A view displaying an error.
101    pub struct ErrorPage(ObjectSubclass<imp::ErrorPage>)
102        @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
103}
104
105impl ErrorPage {
106    pub fn new() -> Self {
107        glib::Object::new()
108    }
109
110    /// Display the given secret error.
111    pub(crate) fn display_secret_error(&self, message: &str) {
112        self.imp().display_secret_error(message);
113    }
114
115    /// Display the given session error.
116    pub(crate) fn display_session_error(&self, message: &str) {
117        self.imp().display_session_error(message);
118    }
119}