diff --git a/gui/src/firstrun.rs b/gui/src/firstrun.rs new file mode 100644 index 0000000..970c361 --- /dev/null +++ b/gui/src/firstrun.rs @@ -0,0 +1,14 @@ +//! First-login modal. Phase 10 implements the body of `run`. + +#![allow(dead_code)] // body lands in Phase 10. + +use crate::app_context::AppContext; + +/// Entry point for `authforge --first-run`. Phase 10 fills this with the +/// fullscreen modal + watchdog + enroll-then-clear-pending logic. +/// Until then it exits cleanly so a developer who passes `--first-run` +/// doesn't get a stuck process. +pub(crate) fn run(_ctx: AppContext) { + eprintln!("authforge: --first-run mode is a Phase 10 stub; exiting."); + std::process::exit(0); +} diff --git a/gui/src/main.rs b/gui/src/main.rs index 9d0634e..fc5f9da 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -5,6 +5,7 @@ mod app_context; mod bus; mod enroll_dialog; mod error; +mod firstrun; mod keys_page; const APP_ID: &str = "io.dangerousthings.AuthForge"; @@ -20,14 +21,33 @@ fn main() -> glib::ExitCode { .expect("build tokio runtime"); let _guard = runtime.enter(); + // Strip `--first-run` from argv before GTK's own option parser sees it; + // GTK rejects unknown long options. Phase 10 fills the body of + // firstrun::run; the prep lane only wires the entry point. + let raw_args: Vec = std::env::args().collect(); + let first_run = raw_args.iter().any(|a| a == "--first-run"); + let gtk_args: Vec = raw_args + .iter() + .filter(|a| a.as_str() != "--first-run") + .cloned() + .collect(); + let app = adw::Application::builder().application_id(APP_ID).build(); - app.connect_activate(|app| { + app.connect_activate(move |app| { let win = adw::ApplicationWindow::builder() .application(app) .default_width(720) .default_height(540) .title("Authentication") .build(); + let toast_overlay = adw::ToastOverlay::new(); + let ctx = app_context::AppContext::new(win.clone().upcast(), toast_overlay.clone()); + + if first_run { + firstrun::run(ctx); + return; + } + let header = adw::HeaderBar::new(); let stack = adw::ViewStack::new(); let switcher = adw::ViewSwitcher::builder() @@ -36,8 +56,6 @@ fn main() -> glib::ExitCode { .build(); header.set_title_widget(Some(&switcher)); - let toast_overlay = adw::ToastOverlay::new(); - let ctx = app_context::AppContext::new(win.clone().upcast(), toast_overlay.clone()); let keys = keys_page::KeysPage::new(ctx.clone()); stack.add_titled(&keys.root, Some("keys"), "Keys"); @@ -52,5 +70,5 @@ fn main() -> glib::ExitCode { win.set_content(Some(&toast_overlay)); win.present(); }); - app.run() + app.run_with_args(>k_args) }