Skip to main content

flashkraft_gui/
lib.rs

1//! FlashKraft GUI Library
2//!
3//! This crate contains the Iced desktop application for FlashKraft.
4//!
5//! ## Contents
6//!
7//! | Module | What lives here |
8//! |--------|-----------------|
9//! | [`core`] | Iced app state, messages, update logic, flash subscription, storage |
10//! | [`components`] | Iced UI widgets and component renderers |
11//! | [`view`] | Top-level view orchestration |
12//! | [`utils`] | GUI-specific utilities (Bootstrap icon mapper) |
13//!
14//! ## Dependency on `flashkraft-core`
15//!
16//! All domain models, the flash pipeline, and drive-detection logic live in
17//! the `flashkraft-core` crate.  This crate re-exports the most commonly
18//! used types so callers only need to import from `flashkraft_gui`.
19
20// GUI-specific utilities (Bootstrap icon mapper uses iced types)
21#[macro_use]
22pub mod utils;
23
24pub mod components;
25pub mod core;
26pub mod view;
27
28// ── Core re-exports ───────────────────────────────────────────────────────────
29
30// Re-export `flashkraft_core::domain` at the crate root so that submodules can
31// use `crate::domain::DriveInfo` / `crate::domain::ImageInfo` etc.
32pub use flashkraft_core::domain;
33
34// Re-export the `flash_debug!` macro from flashkraft_core so that
35// `use crate::flash_debug;` in flash_subscription.rs resolves correctly.
36pub use flashkraft_core::flash_debug;
37
38// Re-export Iced app entry points
39pub use core::{FlashKraft, Message};
40
41// ── GUI entry point ───────────────────────────────────────────────────────────
42
43/// Entry point for the Iced desktop GUI.
44/// Called by the published `flashkraft` crate's GUI binary.
45pub fn run_gui() -> iced::Result {
46    use iced::{Settings, Task};
47
48    let args: Vec<String> = std::env::args().collect();
49    if args.get(1).map(String::as_str) == Some("--flash-helper") {
50        let image_path = args.get(2).map(String::as_str).unwrap_or_else(|| {
51            eprintln!("flash-helper: missing <image_path> argument");
52            std::process::exit(2);
53        });
54        let device_path = args.get(3).map(String::as_str).unwrap_or_else(|| {
55            eprintln!("flash-helper: missing <device_path> argument");
56            std::process::exit(2);
57        });
58        flashkraft_core::flash_helper::run(image_path, device_path);
59        std::process::exit(0);
60    }
61
62    iced::application(
63        "FlashKraft - OS Image Writer",
64        FlashKraft::update,
65        FlashKraft::view,
66    )
67    .subscription(FlashKraft::subscription)
68    .theme(|state: &FlashKraft| state.theme.clone())
69    .settings(Settings {
70        fonts: vec![iced_fonts::BOOTSTRAP_FONT_BYTES.into()],
71        ..Default::default()
72    })
73    .window(iced::window::Settings {
74        size: iced::Size::new(1300.0, 700.0),
75        resizable: false,
76        decorations: true,
77        ..Default::default()
78    })
79    .run_with(|| {
80        let initial_state = FlashKraft::new();
81        let initial_command = Task::perform(
82            flashkraft_core::commands::load_drives(),
83            Message::DrivesRefreshed,
84        );
85        (initial_state, initial_command)
86    })
87}
88
89// Re-export domain types from core so downstream code can do
90// `use flashkraft_gui::{DriveInfo, ImageInfo}` without knowing about
91// flashkraft-core directly.
92pub use flashkraft_core::{DriveInfo, ImageInfo};