use super::{
CURRENT_NATIVE_PATH,
autosave::{autosave_path, record_recent_native_file},
catalogue::CatalogueWriteBack,
};
use crate::{
EditorModel, MainWindow,
bridge::library::source::LibrarySource,
gui::{editor::state::EditorState, show_toast},
};
use indicatrix_vault::db::sqlite::Database;
use slint::ComponentHandle;
use std::{
cell::RefCell,
path::{Path, PathBuf},
rc::Rc,
sync::{Arc, Mutex, atomic::Ordering},
};
pub(super) fn record_last_saved_path(ui: &MainWindow, path: &Path) {
let full = path.display().to_string();
let label = path
.file_name()
.map_or_else(|| full.clone(), |name| name.to_string_lossy().into_owned());
let model = ui.global::<EditorModel>();
model.set_last_saved_path(full.into());
model.set_last_saved_label(label.into());
}
pub(super) struct WriteNativeOutcome {
pub(super) dest_path: PathBuf,
pub(super) native_path: PathBuf,
pub(super) asc_filename: String,
pub(super) paired: indicatrix_cut_core::native::PairedSave,
pub(super) catalogue: Result<(i64, CatalogueWriteBack), String>,
}
pub(super) fn finish_save_native_success(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
outcome: WriteNativeOutcome,
db: &Arc<Mutex<Database>>,
source: &Arc<Mutex<LibrarySource>>,
) {
let WriteNativeOutcome {
dest_path,
native_path,
asc_filename,
paired,
catalogue,
} = outcome;
let _ = std::fs::remove_file(autosave_path(Some(asc_filename.as_str())));
record_recent_native_file(ui, &native_path.display().to_string());
CURRENT_NATIVE_PATH.with(|cell| *cell.borrow_mut() = Some(native_path.clone()));
ui.set_loaded_design_name(asc_filename.clone().into());
record_last_saved_path(ui, &dest_path);
{
let mut st = state.borrow_mut();
st.asc_filename = Some(asc_filename);
st.original_asc_text = Some(paired.asc_text);
st.saved_generation = st.generation.load(Ordering::Relaxed);
}
ui.global::<EditorModel>()
.set_is_dirty(state.borrow().is_dirty());
if let Some(reason) = &paired.draft_reason {
show_toast(
ui,
&format!(
"Saved '{}' as a draft ({reason}). Add a scale-reference tier to \
finish it.",
dest_path.display()
),
"warning",
);
} else {
let asc_note = if paired.asc_preserved {
"unchanged .asc preserved"
} else {
".asc regenerated (meet notes rewritten)"
};
show_toast(
ui,
&format!(
"Saved '{}' and '{}' ({asc_note}).",
dest_path.display(),
native_path.display()
),
"success",
);
}
match catalogue {
Ok((id, catalogue_outcome)) => {
state.borrow_mut().source_entry_id = Some(id);
crate::gui::library::local::refresh_after_library_change(ui, db, source);
match catalogue_outcome {
CatalogueWriteBack::SourceRowGoneNewRowCreated => {
show_toast(
ui,
"This design's catalogue row no longer exists (it may have been \
deleted) -- saved as a new catalogue entry instead of updating it.",
"info",
);
}
CatalogueWriteBack::UpdatedExisting {
stale_cache_invalidation_failed: true,
} => {
show_toast(
ui,
"Saved, but this design's cached preview image and tilt curves in \
the library could not be cleared automatically -- they may still \
show the geometry from before this save. Re-export or recompute \
them if they look wrong.",
"warning",
);
}
CatalogueWriteBack::UpdatedExisting {
stale_cache_invalidation_failed: false,
}
| CatalogueWriteBack::NewRow => {}
}
}
Err(message) => show_toast(ui, &format!("Catalogue not updated: {message}"), "error"),
}
}