Browse Source

feat: transform patht

Vincent Chan 2 năm trước cách đây
mục cha
commit
0def48d0ca

+ 2 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/operation/operation.dart

@@ -207,10 +207,10 @@ Path transformPath(Path preInsertPath, Path b, [int delta = 1]) {
 
 Operation transformOperation(Operation a, Operation b) {
   if (a is InsertOperation) {
-    final newPath = transformPath(a.path, b.path);
+    final newPath = transformPath(a.path, b.path, a.nodes.length);
     return b.copyWithPath(newPath);
   } else if (a is DeleteOperation) {
-    final newPath = transformPath(a.path, b.path, -1);
+    final newPath = transformPath(a.path, b.path, -1 * a.nodes.length);
     return b.copyWithPath(newPath);
   }
   // TODO: transform update and textedit

+ 9 - 0
shared-lib/lib-ot/src/core/document/document.rs

@@ -124,6 +124,15 @@ impl DocumentTree {
             return;
         }
 
+        let children_length = parent.children(&self.arena).fold(0, |counter, _| counter + 1);
+
+        if index == children_length {
+            for id in insert_children {
+                parent.append(*id, &mut self.arena);
+            }
+            return;
+        }
+
         let node_to_insert = self.child_at_index_of_path(parent, index).unwrap();
 
         for id in insert_children {

+ 42 - 2
shared-lib/lib-ot/src/core/document/document_operation.rs

@@ -10,6 +10,14 @@ pub enum DocumentOperation {
 }
 
 impl DocumentOperation {
+    pub fn path(&self) -> &Position {
+        match self {
+            DocumentOperation::Insert(insert) => &insert.path,
+            DocumentOperation::Update(update) => &update.path,
+            DocumentOperation::Delete(delete) => &delete.path,
+            DocumentOperation::TextEdit(text_edit) => &text_edit.path,
+        }
+    }
     pub fn invert(&self) -> DocumentOperation {
         match self {
             DocumentOperation::Insert(insert_operation) => DocumentOperation::Delete(DeleteOperation {
@@ -32,8 +40,40 @@ impl DocumentOperation {
             }),
         }
     }
-    pub fn transform(_a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation {
-        b.clone()
+    pub fn clone_with_new_path(&self, path: Position) -> DocumentOperation {
+        match self {
+            DocumentOperation::Insert(insert) => DocumentOperation::Insert(InsertOperation {
+                path,
+                nodes: insert.nodes.clone(),
+            }),
+            DocumentOperation::Update(update) => DocumentOperation::Update(UpdateOperation {
+                path,
+                attributes: update.attributes.clone(),
+                old_attributes: update.old_attributes.clone(),
+            }),
+            DocumentOperation::Delete(delete) => DocumentOperation::Delete(DeleteOperation {
+                path,
+                nodes: delete.nodes.clone(),
+            }),
+            DocumentOperation::TextEdit(text_edit) => DocumentOperation::TextEdit(TextEditOperation {
+                path,
+                delta: text_edit.delta.clone(),
+                inverted: text_edit.inverted.clone(),
+            }),
+        }
+    }
+    pub fn transform(a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation {
+        match a {
+            DocumentOperation::Insert(insert_op) => {
+                let new_path = Position::transform(a.path(), b.path(), insert_op.nodes.len() as i64);
+                b.clone_with_new_path(new_path)
+            }
+            DocumentOperation::Delete(delete_op) => {
+                let new_path = Position::transform(a.path(), b.path(), delete_op.nodes.len() as i64);
+                b.clone_with_new_path(new_path)
+            }
+            _ => b.clone(),
+        }
     }
 }
 

+ 2 - 2
shared-lib/lib-ot/src/core/document/position.rs

@@ -12,7 +12,7 @@ impl Position {
 
 impl Position {
     // delta is default to be 1
-    pub fn transform(pre_insert_path: &Position, b: &Position, delta: usize) -> Position {
+    pub fn transform(pre_insert_path: &Position, b: &Position, delta: i64) -> Position {
         if pre_insert_path.len() > b.len() {
             return b.clone();
         }
@@ -30,7 +30,7 @@ impl Position {
         let prev_insert_last: usize = *pre_insert_path.0.last().unwrap();
         let b_at_index = b.0[pre_insert_path.0.len() - 1];
         if prev_insert_last <= b_at_index {
-            prefix.push(b_at_index + delta);
+            prefix.push(((b_at_index as i64) + delta) as usize);
         } else {
             prefix.push(b_at_index);
         }

+ 20 - 0
shared-lib/lib-ot/tests/main.rs

@@ -34,3 +34,23 @@ fn test_documents() {
     document.apply(transaction);
     assert!(document.node_at_path(&vec![0].into()).is_none());
 }
+
+#[test]
+fn test_transform_paths() {
+    let mut document = DocumentTree::new();
+    let transaction = {
+        let mut tb = TransactionBuilder::new(&document);
+        tb.insert_nodes(&vec![0].into(), &vec![NodeData::new("text")]);
+        tb.insert_nodes(&vec![1].into(), &vec![NodeData::new("text")]);
+        tb.insert_nodes(&vec![2].into(), &vec![NodeData::new("text")]);
+        tb.finalize()
+    };
+    document.apply(transaction);
+
+    let transaction = {
+        let mut tb = TransactionBuilder::new(&document);
+        tb.insert_nodes(&vec![1].into(), &vec![NodeData::new("text")]);
+        tb.finalize()
+    };
+    document.apply(transaction);
+}