diff --git a/gui/src/firstrun/mod.rs b/gui/src/firstrun/mod.rs index b6add56..d2a2831 100644 --- a/gui/src/firstrun/mod.rs +++ b/gui/src/firstrun/mod.rs @@ -56,9 +56,7 @@ pub(crate) fn run(ctx: AppContext) { let daemon = match Daemon::connect().await { Ok(d) => d, Err(e) => { - status_for_async.set_description(Some(&user_message(&e))); - // Stay open so the user sees the error; watchdog will - // logout in 60s if they don't take action. + render_unavailable(&win_for_async, &status_for_async, &user_message(&e)); return; } }; @@ -66,7 +64,7 @@ pub(crate) fn run(ctx: AppContext) { let s = match daemon.get_pending_status(&user).await { Ok(s) => s, Err(e) => { - status_for_async.set_description(Some(&user_message(&e))); + render_unavailable(&win_for_async, &status_for_async, &user_message(&e)); return; } }; @@ -130,6 +128,25 @@ fn render_get_started( status.set_child(Some(&go)); } +fn render_unavailable(win: &adw::ApplicationWindow, status: &adw::StatusPage, message: &str) { + // Daemon-connect or GetPendingStatus failure: surface the error and give + // the user a Skip button so they aren't stuck waiting 60s for the + // watchdog to log them out. + status.set_title("Setup unavailable"); + status.set_description(Some(message)); + let skip = gtk::Button::builder() + .label("Skip") + .css_classes(["pill"]) + .halign(gtk::Align::Center) + .build(); + let win_skip = win.clone(); + skip.connect_clicked(move |_| { + win_skip.close(); + std::process::exit(0); + }); + status.set_child(Some(&skip)); +} + fn install_activity_pokes(win: &adw::ApplicationWindow, watchdog: Rc>) { // Any keypress or click counts as activity. let key = gtk::EventControllerKey::new();