Wire welcome dialog with navigation and first-run detection
- Welcome dialog buttons navigate between pages - Done button closes dialog and marks first_run_complete - Show welcome dialog on first launch only - Add first_run_complete field to AppConfig with serde(default)
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
|
pub first_run_complete: bool,
|
||||||
pub output_subfolder: String,
|
pub output_subfolder: String,
|
||||||
pub output_fixed_path: Option<String>,
|
pub output_fixed_path: Option<String>,
|
||||||
pub overwrite_behavior: OverwriteBehavior,
|
pub overwrite_behavior: OverwriteBehavior,
|
||||||
@@ -20,6 +22,7 @@ pub struct AppConfig {
|
|||||||
impl Default for AppConfig {
|
impl Default for AppConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
first_run_complete: false,
|
||||||
output_subfolder: "processed".into(),
|
output_subfolder: "processed".into(),
|
||||||
output_fixed_path: None,
|
output_fixed_path: None,
|
||||||
overwrite_behavior: OverwriteBehavior::Ask,
|
overwrite_behavior: OverwriteBehavior::Ask,
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ fn build_ui(app: &adw::Application) {
|
|||||||
ui.step_indicator.set_current(0);
|
ui.step_indicator.set_current(0);
|
||||||
|
|
||||||
window.present();
|
window.present();
|
||||||
|
|
||||||
|
crate::welcome::show_welcome_if_first_launch(&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_menu() -> gtk::gio::Menu {
|
fn build_menu() -> gtk::gio::Menu {
|
||||||
|
|||||||
@@ -1,7 +1,26 @@
|
|||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
pub fn show_welcome_if_first_launch(window: &adw::ApplicationWindow) {
|
||||||
pub fn build_welcome_dialog() -> adw::Dialog {
|
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()
|
let dialog = adw::Dialog::builder()
|
||||||
.title("Welcome to Pixstrip")
|
.title("Welcome to Pixstrip")
|
||||||
.content_width(500)
|
.content_width(500)
|
||||||
@@ -10,23 +29,20 @@ pub fn build_welcome_dialog() -> adw::Dialog {
|
|||||||
|
|
||||||
let nav_view = adw::NavigationView::new();
|
let nav_view = adw::NavigationView::new();
|
||||||
|
|
||||||
// Page 1: Welcome
|
let welcome_page = build_welcome_page(&nav_view);
|
||||||
let welcome_page = build_welcome_page();
|
|
||||||
nav_view.add(&welcome_page);
|
nav_view.add(&welcome_page);
|
||||||
|
|
||||||
// Page 2: Skill level
|
let skill_page = build_skill_page(&nav_view);
|
||||||
let skill_page = build_skill_page();
|
|
||||||
nav_view.add(&skill_page);
|
nav_view.add(&skill_page);
|
||||||
|
|
||||||
// Page 3: Output defaults
|
let output_page = build_output_page(&dialog);
|
||||||
let output_page = build_output_page();
|
|
||||||
nav_view.add(&output_page);
|
nav_view.add(&output_page);
|
||||||
|
|
||||||
dialog.set_child(Some(&nav_view));
|
dialog.set_child(Some(&nav_view));
|
||||||
dialog
|
dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_welcome_page() -> adw::NavigationPage {
|
fn build_welcome_page(nav_view: &adw::NavigationView) -> adw::NavigationPage {
|
||||||
let content = gtk::Box::builder()
|
let content = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Vertical)
|
.orientation(gtk::Orientation::Vertical)
|
||||||
.spacing(12)
|
.spacing(12)
|
||||||
@@ -50,6 +66,11 @@ fn build_welcome_page() -> adw::NavigationPage {
|
|||||||
next_button.add_css_class("suggested-action");
|
next_button.add_css_class("suggested-action");
|
||||||
next_button.add_css_class("pill");
|
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(&status);
|
||||||
content.append(&next_button);
|
content.append(&next_button);
|
||||||
|
|
||||||
@@ -60,7 +81,7 @@ fn build_welcome_page() -> adw::NavigationPage {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_skill_page() -> adw::NavigationPage {
|
fn build_skill_page(nav_view: &adw::NavigationView) -> adw::NavigationPage {
|
||||||
let content = gtk::Box::builder()
|
let content = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Vertical)
|
.orientation(gtk::Orientation::Vertical)
|
||||||
.spacing(12)
|
.spacing(12)
|
||||||
@@ -116,6 +137,11 @@ fn build_skill_page() -> adw::NavigationPage {
|
|||||||
next_button.add_css_class("suggested-action");
|
next_button.add_css_class("suggested-action");
|
||||||
next_button.add_css_class("pill");
|
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(&title);
|
||||||
content.append(&subtitle);
|
content.append(&subtitle);
|
||||||
content.append(&group);
|
content.append(&group);
|
||||||
@@ -128,7 +154,7 @@ fn build_skill_page() -> adw::NavigationPage {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_output_page() -> adw::NavigationPage {
|
fn build_output_page(dialog: &adw::Dialog) -> adw::NavigationPage {
|
||||||
let content = gtk::Box::builder()
|
let content = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Vertical)
|
.orientation(gtk::Orientation::Vertical)
|
||||||
.spacing(12)
|
.spacing(12)
|
||||||
@@ -184,6 +210,11 @@ fn build_output_page() -> adw::NavigationPage {
|
|||||||
done_button.add_css_class("suggested-action");
|
done_button.add_css_class("suggested-action");
|
||||||
done_button.add_css_class("pill");
|
done_button.add_css_class("pill");
|
||||||
|
|
||||||
|
let dlg = dialog.clone();
|
||||||
|
done_button.connect_clicked(move |_| {
|
||||||
|
dlg.close();
|
||||||
|
});
|
||||||
|
|
||||||
content.append(&title);
|
content.append(&title);
|
||||||
content.append(&subtitle);
|
content.append(&subtitle);
|
||||||
content.append(&group);
|
content.append(&group);
|
||||||
|
|||||||
Reference in New Issue
Block a user