mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-16 08:19:59 +00:00
outdated state
This commit is contained in:
1 parent
a2b4d89150
commit
9adb8e7221
14 files changed
+211
-118
No files matched your search
@@ -35,7 +35,7 @@ pub struct IdbStorage {
|
||||
}
|
||||
|
||||
fn error(error: impl std::fmt::Display) -> StorageError {
|
||||
StorageError(error.to_string())
|
||||
StorageError::Failed(error.to_string())
|
||||
}
|
||||
|
||||
/// The object store of a kind of chunks.
|
||||
|
||||
@@ -98,8 +98,9 @@ fn notify(pick: impl FnOnce(&(js_sys::Function, js_sys::Function)) -> &js_sys::F
|
||||
/// Opens the database `name` (it is created if it does not exist), puts the files that it holds
|
||||
/// in the engine, which has to be empty, and returns the settings (JSON strings by key) and the
|
||||
/// outcome of putting the files in. The changes of the files that follow are saved, unless some of
|
||||
/// what is stored was written by a newer version of the app (`readOnly`): then nothing is, so that
|
||||
/// the newer version finds its data again.
|
||||
/// what is stored was written by a newer version of the app: then nothing is read, and the files
|
||||
/// cannot be changed (the outcome has the `Outdated` error), so that the newer version finds its
|
||||
/// data again.
|
||||
///
|
||||
/// `on_saved` is called after the files were written (to tell the other tabs), and `on_behind` when
|
||||
/// a write was refused because another tab wrote since (call `sync_storage` then).
|
||||
@@ -115,11 +116,9 @@ pub async fn open_storage(
|
||||
}
|
||||
let storage = IdbStorage::open(name).await.map_err(to_js_error)?;
|
||||
let mut persister = Persister::default();
|
||||
let restored = persister.restore(&storage).await.map_err(to_js_error)?;
|
||||
let (read_only, unreadable) = (restored.read_only, restored.unreadable);
|
||||
let outcome = restore_engine(persister.restore(&storage).await).map_err(to_js_error)?;
|
||||
let settings = storage.load_settings().await.map_err(to_js_error)?;
|
||||
|
||||
let outcome = with_engine_mut(|engine| engine.restore(restored)).unwrap_or_default();
|
||||
PERSISTER.with(|slot| *slot.borrow_mut() = Some(persister));
|
||||
STORAGE.with(|slot| *slot.borrow_mut() = Some(Rc::new(storage)));
|
||||
LISTENERS.with(|slot| *slot.borrow_mut() = Some((on_saved, on_behind)));
|
||||
@@ -130,12 +129,29 @@ pub async fn open_storage(
|
||||
}
|
||||
let opened = Object::new();
|
||||
set(&opened, "settings", settings_object);
|
||||
set(&opened, "outcome", outcome_object(&outcome, None));
|
||||
set(&opened, "readOnly", read_only);
|
||||
set(&opened, "unreadable", unreadable as f64);
|
||||
set(&opened, "outcome", outcome);
|
||||
Ok(opened.unchecked_into())
|
||||
}
|
||||
|
||||
/// Overwrites the files of the engine with what was read, and tells what that did. If what is
|
||||
/// stored comes from a newer version of the app, the files are left as they are and cannot be
|
||||
/// changed anymore: the error of the outcome says so, as for the edits that are refused afterwards.
|
||||
fn restore_engine(
|
||||
read: Result<engine::Restored, engine::StorageError>,
|
||||
) -> Result<Outcome, engine::StorageError> {
|
||||
match read {
|
||||
Ok(restored) => Ok(match with_engine_mut(|engine| engine.restore(restored)) {
|
||||
Some(outcome) => outcome_object(&outcome, None),
|
||||
None => outcome_object(&engine::Outcome::default(), None),
|
||||
}),
|
||||
Err(engine::StorageError::Newer) => {
|
||||
with_engine_mut(Engine::mark_outdated);
|
||||
Ok(fail(engine::CommandError::Outdated.to_string()))
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_js_error(error: engine::StorageError) -> JsValue {
|
||||
JsValue::from_str(&error.to_string())
|
||||
}
|
||||
@@ -171,11 +187,11 @@ pub async fn sync_storage() -> Result<Outcome, JsValue> {
|
||||
SAVING.set(true);
|
||||
let result = async {
|
||||
if !persister.is_behind(&*storage).await? {
|
||||
return Ok(engine::Outcome::default());
|
||||
return Ok(outcome_object(&engine::Outcome::default(), None));
|
||||
}
|
||||
let restored = persister.restore(&*storage).await?;
|
||||
let outcome = restore_engine(persister.restore(&*storage).await)?;
|
||||
DIRTY.set(false);
|
||||
Ok(with_engine_mut(|engine| engine.restore(restored)).unwrap_or_default())
|
||||
Ok(outcome)
|
||||
}
|
||||
.await;
|
||||
PERSISTER.with(|slot| *slot.borrow_mut() = Some(persister));
|
||||
@@ -187,9 +203,7 @@ pub async fn sync_storage() -> Result<Outcome, JsValue> {
|
||||
// edited while reading, and nothing was overwritten
|
||||
schedule_save();
|
||||
}
|
||||
result
|
||||
.map(|outcome| outcome_object(&outcome, None))
|
||||
.map_err(to_js_error)
|
||||
result.map_err(to_js_error)
|
||||
}
|
||||
|
||||
/// Saves a setting, `value` being its JSON.
|
||||
|
||||
@@ -21,14 +21,15 @@ pub(crate) fn fail(message: impl AsRef<str>) -> Outcome {
|
||||
|
||||
/// Runs an action and tells what it did, see `Outcome` in `ts`.
|
||||
pub(crate) fn execute(action: Action) -> Outcome {
|
||||
let Some(outcome) = with_engine_mut(|engine| engine.execute(action)) else {
|
||||
return fail("the engine is not started");
|
||||
let outcome = match with_engine_mut(|engine| engine.execute(action)) {
|
||||
Some(Ok(outcome)) => outcome,
|
||||
Some(Err(error)) => return fail(error.to_string()),
|
||||
None => return fail("the engine is not started"),
|
||||
};
|
||||
if outcome.changed && (outcome.diff.is_some() || outcome.order_changed) {
|
||||
schedule_save();
|
||||
}
|
||||
let error = outcome.error.as_ref().map(ToString::to_string);
|
||||
outcome_object(&outcome, error.as_deref())
|
||||
outcome_object(&outcome, None)
|
||||
}
|
||||
|
||||
pub(crate) fn edit(command: Command) -> Outcome {
|
||||
|
||||
@@ -97,10 +97,6 @@ export interface StorageOpened {
|
||||
settings: Record<string, string>;
|
||||
/** The files that were restored are the added ones. */
|
||||
outcome: Outcome;
|
||||
/** Some of what is stored was written by a newer version: nothing is saved. */
|
||||
readOnly: boolean;
|
||||
/** How many stored files could not be read, and are dropped at the next save. */
|
||||
unreadable: number;
|
||||
}
|
||||
export interface FileStructure {
|
||||
id: string;
|
||||
|
||||
Reference in new issue
Block a user