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