mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-31 05:46:46 -06:00
M1: a recovery copy made during a version preview holds the file, not the version shown (#1588)
Desktop recovery copies saved DocState::doc, which is the version shown while a version (or a live text preview) is previewed, so a crash during a preview brought the old version back as the unsaved file. What a recovery copy holds is now one shared helper, branches::recovery_copy: the document itself (document_itself(), the same document the unsaved-changes check compares), its history and its branches. The desktop copies and the browser's (#1580) both use it.
This commit is contained in:
+2
-1
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use base64::Engine as _;
|
||||
use figcraft_engine::branches::{self, needs_copy, stamp};
|
||||
use figcraft_engine::branches::{needs_copy, recovery_copy, stamp};
|
||||
use figcraft_engine::doc::Document;
|
||||
use figcraft_engine::{DocState, Session};
|
||||
use figcraft_format::{Branch, Version};
|
||||
@@ -26,8 +26,8 @@ struct Copy {
|
||||
|
||||
impl Copy {
|
||||
fn of(s: &Session, d: &DocState) -> Self {
|
||||
let (versions, branches) = (d.versions.clone(), branches::current(s, d.uid));
|
||||
Self { uid: d.uid, stamp: stamp(s, d), doc: d.document_itself().clone(), versions, branches }
|
||||
let (doc, versions, branches) = recovery_copy(s, d);
|
||||
Self { uid: d.uid, stamp: stamp(s, d), doc, versions, branches }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,3 +96,20 @@ fn the_stopped_page_says_what_was_kept() {
|
||||
says(2, 0, "too large for the browser to keep");
|
||||
says(3, 1, "the browser had room for");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_copy_taken_while_a_version_is_previewed_is_of_the_file() {
|
||||
let mut s = edited("Poster");
|
||||
s.execute("file.saveVersion", &json!({"name": "v1"})).unwrap();
|
||||
s.execute("file.rename", &json!({"name": "Later"})).unwrap();
|
||||
// Version v1 (named Poster) shows in place of the file.
|
||||
s.execute("version.preview", &json!({"index": 0})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().name, "Poster", "the preview shows");
|
||||
let mut u = Unsaved::default();
|
||||
u.follow(&s);
|
||||
let mut next = Session::new();
|
||||
assert_eq!(restore(&mut next, stored(&u)), 1);
|
||||
let d = next.ds().unwrap();
|
||||
assert_eq!(d.doc.name, "Later", "the file comes back, not the version shown");
|
||||
assert_eq!(d.versions.iter().map(|v| v.name.as_str()).collect::<Vec<_>>(), ["v1"]);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use figcraft_engine::branches::{needs_copy, stamp};
|
||||
use figcraft_engine::branches::{needs_copy, recovery_copy, stamp};
|
||||
use figcraft_engine::{DocState, Session};
|
||||
use figcraft_format::{Branch, Version};
|
||||
use serde_json::json;
|
||||
@@ -204,8 +204,7 @@ impl Recovery {
|
||||
if entry.done.as_ref() == Some(&stamp) || entry.flight.is_some() {
|
||||
continue;
|
||||
}
|
||||
let doc = d.doc.clone();
|
||||
let (versions, branches) = (d.versions.clone(), figcraft_engine::branches::current(s, d.uid));
|
||||
let (doc, versions, branches) = recovery_copy(s, d);
|
||||
// Which online file it is and what of the server's this very copy has (a line each:
|
||||
// the server, the file's id, then the session, client id, last change and the secret the
|
||||
// client id resumes with), while it
|
||||
|
||||
@@ -388,3 +388,21 @@ fn a_background_copy_that_failed_is_tried_again_without_another_edit() {
|
||||
r.finish();
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_copy_made_while_a_version_is_previewed_is_of_the_file_not_the_version() {
|
||||
let root = root("preview");
|
||||
let mut s = edited();
|
||||
s.execute("file.saveVersion", &json!({"name": "v1"})).unwrap();
|
||||
s.execute("shape.rectangle", &json!({"x": 20, "y": 0, "width": 10, "height": 10})).unwrap();
|
||||
// The one-rectangle version shows in place of the two-rectangle file.
|
||||
s.execute("version.preview", &json!({"index": 0})).unwrap();
|
||||
assert_eq!(rectangles(s.doc().unwrap()), 1, "the preview shows");
|
||||
assert!(s.ds().unwrap().is_dirty(), "the file itself still has unsaved changes");
|
||||
let mut r = Recovery::start(&root).unwrap();
|
||||
r.write(&s, true);
|
||||
let next = crash_and_recover(r, &root);
|
||||
assert_eq!(rectangles(next.doc().unwrap()), 2, "the file comes back, not the version shown");
|
||||
assert_eq!(next.docs[0].versions.iter().map(|v| v.name.as_str()).collect::<Vec<_>>(), ["v1"]);
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,13 @@ pub fn needs_copy(s: &Session, d: &DocState) -> bool {
|
||||
d.branch_of.is_none() && (d.is_dirty() || tabs(s, d.uid).any(DocState::is_dirty))
|
||||
}
|
||||
|
||||
/// What a recovery copy of `d` holds: the document itself (not a version or live text preview
|
||||
/// shown in its place: a crash during a preview must bring the file back, not the version),
|
||||
/// its version history and its branches as they are now ([`current`]).
|
||||
pub fn recovery_copy(s: &Session, d: &DocState) -> (Arc<Document>, Vec<figcraft_format::Version>, Vec<Branch>) {
|
||||
(d.document_itself().clone(), d.versions.clone(), current(s, d.uid))
|
||||
}
|
||||
|
||||
/// The revisions a recovery copy of `d` is of: its own and its branch tabs' (a branch tab's edits
|
||||
/// change only its own revision). A new copy is due when they change.
|
||||
pub fn stamp(s: &Session, d: &DocState) -> Vec<u64> {
|
||||
|
||||
+2
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user