mod pages;
mod window;
use anyhow::Result;
use std::sync::{mpsc, Arc, Mutex};
use super::types::{ConfiguredPage, GuiMessage, WizardConfig, WizardPage};
use crate::Installer;
pub fn run_wizard(config: WizardConfig, installer: &mut Installer) -> Result<()> {
let cancelled = installer.cancellation_flag();
let installer_taken = std::mem::replace(installer, Installer::new(&[], &[], "none"));
let installer_arc = Arc::new(Mutex::new(installer_taken));
let default_dir = find_default_dir(&config.pages);
let install_dir = Arc::new(Mutex::new(default_dir));
let (tx, rx) = mpsc::channel::<GuiMessage>();
let mut pages_without_callback: Vec<ConfiguredPage> = Vec::new();
let mut install_callback = None;
for configured in config.pages {
let ConfiguredPage {
page,
on_enter,
on_before_leave,
skip_if,
} = configured;
let page = match page {
WizardPage::Install {
callback,
is_uninstall,
} => {
install_callback = Some(callback);
WizardPage::Install {
callback: Box::new(|_| Ok(())),
is_uninstall,
}
}
other => other,
};
pages_without_callback.push(ConfiguredPage {
page,
on_enter,
on_before_leave,
skip_if,
});
}
let wizard_config = WizardConfig {
title: config.title,
pages: pages_without_callback,
buttons: config.buttons,
on_start: None,
on_exit: None,
};
let result = window::run(
wizard_config,
installer_arc.clone(),
install_dir,
cancelled,
tx,
rx,
install_callback,
);
let restored = Arc::try_unwrap(installer_arc)
.map_err(|_| anyhow::anyhow!("installer still referenced after wizard closed"))?
.into_inner()
.map_err(|e| anyhow::anyhow!("installer mutex poisoned: {e}"))?;
*installer = restored;
result
}
fn find_default_dir(pages: &[ConfiguredPage]) -> String {
for configured in pages {
if let WizardPage::DirectoryPicker { default, .. } = &configured.page {
return default.clone();
}
}
String::new()
}