Files
authforge/gui/src/main.rs

92 lines
3.1 KiB
Rust

use adw::prelude::*;
use gtk::glib;
mod app_context;
mod bus;
mod enroll_dialog;
mod error;
mod firstrun;
mod keys_page;
mod policy_form;
mod policy_page;
mod recovery_page;
#[cfg(feature = "totp")]
mod totp_page;
const APP_ID: &str = "io.dangerousthings.AuthForge";
fn main() -> glib::ExitCode {
// Multi-thread tokio runtime hosts zbus's tokio-flavored futures. The
// `_guard` keeps the runtime context active on this thread so calls like
// `zbus::Connection::system().await` from within `glib::MainContext::
// spawn_local` closures don't panic with "no current reactor".
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.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<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();
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()
.stack(&stack)
.policy(adw::ViewSwitcherPolicy::Wide)
.build();
header.set_title_widget(Some(&switcher));
let keys = keys_page::KeysPage::new(ctx.clone());
stack.add_titled(&keys.root, Some("keys"), "Keys");
let policy = policy_page::PolicyPage::new(ctx.clone());
stack.add_titled(&policy.root, Some("policy"), "Policy");
let recovery = recovery_page::RecoveryPage::new(ctx.clone());
stack.add_titled(&recovery.root, Some("recovery"), "Recovery");
#[cfg(feature = "totp")]
{
let totp = totp_page::TotpPage::new(ctx.clone());
stack.add_titled(&totp.root, Some("totp"), "TOTP");
}
// ToolbarView is libadwaita v1_4-gated; the project sticks with the
// simpler Box layout for portability (see commit c6a5e94).
let layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
layout.append(&header);
layout.append(&stack);
stack.set_vexpand(true);
toast_overlay.set_child(Some(&layout));
win.set_content(Some(&toast_overlay));
win.present();
});
app.run_with_args(&gtk_args)
}