diff --git a/pixstrip-core/src/config.rs b/pixstrip-core/src/config.rs index 4c3b534..cb9c38d 100644 --- a/pixstrip-core/src/config.rs +++ b/pixstrip-core/src/config.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] pub struct AppConfig { + pub first_run_complete: bool, pub output_subfolder: String, pub output_fixed_path: Option, pub overwrite_behavior: OverwriteBehavior, @@ -20,6 +22,7 @@ pub struct AppConfig { impl Default for AppConfig { fn default() -> Self { Self { + first_run_complete: false, output_subfolder: "processed".into(), output_fixed_path: None, overwrite_behavior: OverwriteBehavior::Ask, diff --git a/pixstrip-gtk/src/app.rs b/pixstrip-gtk/src/app.rs index 27e2cbd..2f4c027 100644 --- a/pixstrip-gtk/src/app.rs +++ b/pixstrip-gtk/src/app.rs @@ -159,6 +159,8 @@ fn build_ui(app: &adw::Application) { ui.step_indicator.set_current(0); window.present(); + + crate::welcome::show_welcome_if_first_launch(&window); } fn build_menu() -> gtk::gio::Menu { diff --git a/pixstrip-gtk/src/welcome.rs b/pixstrip-gtk/src/welcome.rs index 0855494..b415ea3 100644 --- a/pixstrip-gtk/src/welcome.rs +++ b/pixstrip-gtk/src/welcome.rs @@ -1,7 +1,26 @@ use adw::prelude::*; -#[allow(dead_code)] -pub fn build_welcome_dialog() -> adw::Dialog { +pub fn show_welcome_if_first_launch(window: &adw::ApplicationWindow) { + let config = pixstrip_core::storage::ConfigStore::new(); + if let Ok(cfg) = config.load() + && cfg.first_run_complete + { + return; + } + + let dialog = build_welcome_dialog(); + let win = window.clone(); + dialog.connect_closed(move |_| { + let config = pixstrip_core::storage::ConfigStore::new(); + if let Ok(mut cfg) = config.load() { + cfg.first_run_complete = true; + let _ = config.save(&cfg); + } + }); + dialog.present(Some(&win)); +} + +fn build_welcome_dialog() -> adw::Dialog { let dialog = adw::Dialog::builder() .title("Welcome to Pixstrip") .content_width(500) @@ -10,23 +29,20 @@ pub fn build_welcome_dialog() -> adw::Dialog { let nav_view = adw::NavigationView::new(); - // Page 1: Welcome - let welcome_page = build_welcome_page(); + let welcome_page = build_welcome_page(&nav_view); nav_view.add(&welcome_page); - // Page 2: Skill level - let skill_page = build_skill_page(); + let skill_page = build_skill_page(&nav_view); nav_view.add(&skill_page); - // Page 3: Output defaults - let output_page = build_output_page(); + let output_page = build_output_page(&dialog); nav_view.add(&output_page); dialog.set_child(Some(&nav_view)); dialog } -fn build_welcome_page() -> adw::NavigationPage { +fn build_welcome_page(nav_view: &adw::NavigationView) -> adw::NavigationPage { let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(12) @@ -50,6 +66,11 @@ fn build_welcome_page() -> adw::NavigationPage { next_button.add_css_class("suggested-action"); next_button.add_css_class("pill"); + let nav = nav_view.clone(); + next_button.connect_clicked(move |_| { + nav.push_by_tag("skill-level"); + }); + content.append(&status); content.append(&next_button); @@ -60,7 +81,7 @@ fn build_welcome_page() -> adw::NavigationPage { .build() } -fn build_skill_page() -> adw::NavigationPage { +fn build_skill_page(nav_view: &adw::NavigationView) -> adw::NavigationPage { let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(12) @@ -116,6 +137,11 @@ fn build_skill_page() -> adw::NavigationPage { next_button.add_css_class("suggested-action"); next_button.add_css_class("pill"); + let nav = nav_view.clone(); + next_button.connect_clicked(move |_| { + nav.push_by_tag("output-location"); + }); + content.append(&title); content.append(&subtitle); content.append(&group); @@ -128,7 +154,7 @@ fn build_skill_page() -> adw::NavigationPage { .build() } -fn build_output_page() -> adw::NavigationPage { +fn build_output_page(dialog: &adw::Dialog) -> adw::NavigationPage { let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(12) @@ -184,6 +210,11 @@ fn build_output_page() -> adw::NavigationPage { done_button.add_css_class("suggested-action"); done_button.add_css_class("pill"); + let dlg = dialog.clone(); + done_button.connect_clicked(move |_| { + dlg.close(); + }); + content.append(&title); content.append(&subtitle); content.append(&group);