use crate::{EditorModel, MainWindow, gui::show_toast};
use slint::ComponentHandle;
pub(super) fn user_manual_candidates(exe_dir: &std::path::Path) -> Vec<std::path::PathBuf> {
vec![
exe_dir.join("docs/manual/README.md"),
exe_dir.join("../docs/manual/README.md"),
exe_dir.join("../../apps/indicatrix-cut/docs/manual/README.md"),
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("docs/manual/README.md"),
]
}
fn locate_user_manual() -> Option<std::path::PathBuf> {
let exe_dir = std::env::current_exe()
.ok()
.and_then(|exe| exe.parent().map(std::path::Path::to_path_buf))?;
user_manual_candidates(&exe_dir)
.into_iter()
.find(|candidate| candidate.is_file())
}
pub(super) fn setup_user_manual_callback(ui: &MainWindow) {
let ui_weak = ui.as_weak();
ui.on_open_user_manual(move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let Some(manual_path) = locate_user_manual() else {
show_toast(&ui, "User manual not found", "error");
return;
};
open_with_os_handler(&manual_path.to_string_lossy());
});
}
fn open_with_os_handler(path: &str) {
#[cfg(target_os = "linux")]
let _ = std::process::Command::new("xdg-open").arg(path).spawn();
#[cfg(target_os = "windows")]
let _ = std::process::Command::new("cmd")
.args(["/C", "start", "", path])
.spawn();
#[cfg(target_os = "macos")]
let _ = std::process::Command::new("open").arg(path).spawn();
}
pub(super) fn setup_reveal_last_saved_callback(ui: &MainWindow) {
let ui_weak = ui.as_weak();
ui.global::<EditorModel>()
.on_reveal_last_saved_path(move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let saved = ui.global::<EditorModel>().get_last_saved_path();
if saved.is_empty() {
return;
}
let path = std::path::PathBuf::from(saved.as_str());
let target = path.parent().unwrap_or(&path);
open_with_os_handler(&target.to_string_lossy());
});
}
#[cfg(test)]
mod tests {
use super::user_manual_candidates;
#[test]
fn user_manual_candidates_are_relative_to_exe_dir_in_order() {
let exe_dir = std::path::Path::new("/opt/indicatrix-cut/bin");
let candidates = user_manual_candidates(exe_dir);
assert_eq!(
candidates[0],
std::path::Path::new("/opt/indicatrix-cut/bin/docs/manual/README.md")
);
assert_eq!(
candidates[1],
std::path::Path::new("/opt/indicatrix-cut/bin/../docs/manual/README.md")
);
assert_eq!(
candidates[2],
std::path::Path::new(
"/opt/indicatrix-cut/bin/../../apps/indicatrix-cut/docs/manual/README.md"
)
);
assert_eq!(
candidates[3],
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("docs/manual/README.md")
);
assert_eq!(candidates.len(), 4);
}
}