feat(gui): --first-run flag + firstrun::run stub for Phase 10
argv is read manually before adw::Application sees it (GTK's option parser rejects unknown long flags), then the filtered list is passed to app.run_with_args. Stub exits cleanly with a stderr breadcrumb so a developer who passes --first-run before Phase 10 lands doesn't get a stuck process. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
gui/src/firstrun.rs
Normal file
14
gui/src/firstrun.rs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ mod app_context;
|
|||||||
mod bus;
|
mod bus;
|
||||||
mod enroll_dialog;
|
mod enroll_dialog;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod firstrun;
|
||||||
mod keys_page;
|
mod keys_page;
|
||||||
|
|
||||||
const APP_ID: &str = "io.dangerousthings.AuthForge";
|
const APP_ID: &str = "io.dangerousthings.AuthForge";
|
||||||
@@ -20,14 +21,33 @@ fn main() -> glib::ExitCode {
|
|||||||
.expect("build tokio runtime");
|
.expect("build tokio runtime");
|
||||||
let _guard = runtime.enter();
|
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<String> = std::env::args().collect();
|
||||||
|
let first_run = raw_args.iter().any(|a| a == "--first-run");
|
||||||
|
let gtk_args: Vec<String> = raw_args
|
||||||
|
.iter()
|
||||||
|
.filter(|a| a.as_str() != "--first-run")
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
let app = adw::Application::builder().application_id(APP_ID).build();
|
let app = adw::Application::builder().application_id(APP_ID).build();
|
||||||
app.connect_activate(|app| {
|
app.connect_activate(move |app| {
|
||||||
let win = adw::ApplicationWindow::builder()
|
let win = adw::ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.default_width(720)
|
.default_width(720)
|
||||||
.default_height(540)
|
.default_height(540)
|
||||||
.title("Authentication")
|
.title("Authentication")
|
||||||
.build();
|
.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 header = adw::HeaderBar::new();
|
||||||
let stack = adw::ViewStack::new();
|
let stack = adw::ViewStack::new();
|
||||||
let switcher = adw::ViewSwitcher::builder()
|
let switcher = adw::ViewSwitcher::builder()
|
||||||
@@ -36,8 +56,6 @@ fn main() -> glib::ExitCode {
|
|||||||
.build();
|
.build();
|
||||||
header.set_title_widget(Some(&switcher));
|
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());
|
let keys = keys_page::KeysPage::new(ctx.clone());
|
||||||
stack.add_titled(&keys.root, Some("keys"), "Keys");
|
stack.add_titled(&keys.root, Some("keys"), "Keys");
|
||||||
|
|
||||||
@@ -52,5 +70,5 @@ fn main() -> glib::ExitCode {
|
|||||||
win.set_content(Some(&toast_overlay));
|
win.set_content(Some(&toast_overlay));
|
||||||
win.present();
|
win.present();
|
||||||
});
|
});
|
||||||
app.run()
|
app.run_with_args(>k_args)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user