mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-16 08:19:59 +00:00
improve flow
This commit is contained in:
1 parent
1d13972014
commit
3c2055b50e
7 files changed
+80
-90
No files matched your search
@@ -16,8 +16,6 @@ pub enum CommandError {
|
||||
NothingToDo,
|
||||
/// The input data could not be parsed.
|
||||
InvalidData(String),
|
||||
/// The engine is in the outdated state.
|
||||
Outdated,
|
||||
}
|
||||
|
||||
impl fmt::Display for CommandError {
|
||||
@@ -25,7 +23,6 @@ impl fmt::Display for CommandError {
|
||||
match self {
|
||||
Self::NothingToDo => write!(f, "nothing to do"),
|
||||
Self::InvalidData(err) => write!(f, "invalid data: {err}"),
|
||||
Self::Outdated => write!(f, "saved by a newer version"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ pub struct Engine {
|
||||
routing_buffer: RoutingBuffer,
|
||||
categories: TrackpointCategories,
|
||||
clipboard: Option<Clipboard>,
|
||||
/// Whether what is stored was written by a newer version (see [`Engine::mark_outdated`]).
|
||||
outdated: bool,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
@@ -137,7 +135,6 @@ impl Engine {
|
||||
/// from the ones that were here are reported as added, removed or modified (all the files
|
||||
/// that were here, as they are not the same objects), and the order as changed if it is.
|
||||
pub fn restore(&mut self, restored: Restored) -> Outcome {
|
||||
self.outdated = false;
|
||||
let selection_before = self.selection.clone();
|
||||
let order_before = self.order.0.clone();
|
||||
let before = self.stack.current().cloned();
|
||||
@@ -166,14 +163,6 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells that what is stored was written by a newer version of the app, which cannot be read
|
||||
/// (see [`crate::StorageError::Newer`]). The files are left as they are, but cannot be changed
|
||||
/// from now on, as the changes could not be kept: [`Engine::execute`] refuses with
|
||||
/// [`CommandError::Outdated`], until something that is not newer is restored.
|
||||
pub fn mark_outdated(&mut self) {
|
||||
self.outdated = true;
|
||||
}
|
||||
|
||||
/// A file as GPX (UTF-8), `None` if it does not exist.
|
||||
pub fn export(&self, id: &FileId, options: ExportOptions) -> Option<Vec<u8>> {
|
||||
let file = self.stack.current()?.get(id)?;
|
||||
@@ -218,12 +207,8 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Single entry point for every action coming from the frontend. Says what it changed, or why
|
||||
/// it did nothing: an edit that fails or has nothing to do, or any change of the files while
|
||||
/// they are outdated (see [`Engine::is_outdated`]).
|
||||
/// it did nothing: an edit that fails or has nothing to do.
|
||||
pub fn execute(&mut self, action: Action) -> Result<Outcome, CommandError> {
|
||||
if self.outdated {
|
||||
return Err(CommandError::Outdated);
|
||||
}
|
||||
let selection_before = self.selection.clone();
|
||||
let order_before = self.order.0.clone();
|
||||
let clipboard_before = self.clipboard.clone();
|
||||
|
||||
@@ -1434,36 +1434,3 @@ fn test_overwriting_forgets_the_history() {
|
||||
engine.restore(restored_from(&engine, &ids, vec![]));
|
||||
assert!(!engine.can_undo());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_files_cannot_be_changed_when_what_is_stored_is_from_a_newer_version() {
|
||||
let mut engine = TestEngine::default();
|
||||
new(&mut engine, "file");
|
||||
let id = engine.order()[0];
|
||||
|
||||
engine.mark_outdated();
|
||||
|
||||
for action in [
|
||||
Action::Edit(Command::Reverse(crate::Reverse)),
|
||||
Action::Undo,
|
||||
Action::Redo,
|
||||
Action::Reorder {
|
||||
file_ids: vec![id],
|
||||
index: 0,
|
||||
},
|
||||
] {
|
||||
assert_eq!(engine.execute(action), Err(CommandError::Outdated));
|
||||
}
|
||||
assert_eq!(engine.order(), [id]);
|
||||
|
||||
// so is anything else, the selection included
|
||||
let result = engine.execute(Action::Select {
|
||||
selection: Selection::Empty,
|
||||
mode: SelectMode::Replace,
|
||||
});
|
||||
assert_eq!(result, Err(CommandError::Outdated));
|
||||
|
||||
// reading a storage that is not newer lifts it
|
||||
engine.restore(restored_from(&engine, &[id], vec![]));
|
||||
assert_ne!(engine.execute(Action::Undo), Err(CommandError::Outdated));
|
||||
}
|
||||
@@ -171,6 +171,9 @@ impl Persister {
|
||||
|
||||
/// Writes what changed since the last save. Nothing is written if nothing changed.
|
||||
///
|
||||
/// Nothing is written while what is stored comes from a newer version (`Failed(Newer)`, see
|
||||
/// [`Persister::restore`]).
|
||||
///
|
||||
/// The write only happens if nothing else was committed since the persister read or wrote
|
||||
/// last: otherwise it is refused (`Stale`), nothing is written, and the persister has to read
|
||||
/// the storage again ([`Persister::restore`]) before it can write.
|
||||
@@ -180,7 +183,7 @@ impl Persister {
|
||||
snapshot: Snapshot,
|
||||
) -> Result<(), CommitError> {
|
||||
if self.read_only {
|
||||
return Ok(());
|
||||
return Err(StorageError::Newer.into());
|
||||
}
|
||||
let mut plan = self.plan(snapshot);
|
||||
if plan.batch.is_empty() {
|
||||
@@ -525,11 +528,12 @@ mod tests {
|
||||
let result = block_on(persister.restore(&storage));
|
||||
assert_eq!(result.unwrap_err(), StorageError::Newer, "{what}");
|
||||
|
||||
// whatever is saved afterwards, nothing is written: the newer version needs its data
|
||||
// whatever is saved afterwards is refused: the newer version needs its data
|
||||
let mut changed = snapshot.clone();
|
||||
changed.order.clear();
|
||||
changed.files.clear();
|
||||
block_on(persister.save(&storage, changed)).unwrap();
|
||||
let result = block_on(persister.save(&storage, changed));
|
||||
assert_eq!(result, Err(CommitError::Failed(StorageError::Newer)), "{what}");
|
||||
assert!(storage.batches.borrow().is_empty(), "{what}");
|
||||
assert_eq!(storage.inner.counts(), before, "{what}");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user