瀏覽代碼

correct the document delta by removing unnecessary op

appflowy 3 年之前
父節點
當前提交
9ca2d60f3f

+ 1 - 1
frontend/rust-lib/flowy-document/src/core/edit/queue.rs

@@ -114,6 +114,7 @@ impl EditorCommandQueue {
                     let read_guard = self.document.read().await;
                     let mut server_prime: Option<RichTextDelta> = None;
                     let client_prime: RichTextDelta;
+                    // The document is empty if its text is equal to the initial text.
                     if read_guard.is_empty::<NewlineDoc>() {
                         // Do nothing
                         client_prime = new_delta;
@@ -122,7 +123,6 @@ impl EditorCommandQueue {
                         client_prime = c_prime;
                         server_prime = Some(s_prime);
                     }
-
                     drop(read_guard);
                     Ok::<TransformDeltas, CollaborateError>(TransformDeltas {
                         client_prime,

+ 17 - 27
frontend/rust-lib/flowy-document/src/core/revision/manager.rs

@@ -9,16 +9,12 @@ use flowy_collaboration::{
         doc::DocumentInfo,
         revision::{RepeatedRevision, Revision, RevisionRange, RevisionState},
     },
-    util::{md5, pair_rev_id_from_revisions, RevIdCounter},
+    util::{make_delta_from_revisions, md5, pair_rev_id_from_revisions, RevIdCounter},
 };
 use flowy_error::FlowyResult;
 use futures_util::{future, stream, stream::StreamExt};
 use lib_infra::future::FutureResult;
-use lib_ot::{
-    core::{trim, Operation, OperationTransformable},
-    errors::OTError,
-    rich_text::RichTextDelta,
-};
+use lib_ot::{core::Operation, errors::OTError, rich_text::RichTextDelta};
 use std::{collections::VecDeque, sync::Arc};
 use tokio::sync::RwLock;
 
@@ -239,18 +235,8 @@ impl RevisionLoader {
 
 fn mk_doc_from_revisions(doc_id: &str, revisions: Vec<Revision>) -> FlowyResult<DocumentInfo> {
     let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id();
-    let mut delta = RichTextDelta::new();
-    for (_, revision) in revisions.into_iter().enumerate() {
-        match RichTextDelta::from_bytes(revision.delta_data) {
-            Ok(local_delta) => {
-                delta = delta.compose(&local_delta)?;
-            },
-            Err(e) => {
-                tracing::error!("Deserialize delta from revision failed: {}", e);
-            },
-        }
-    }
-    correct_delta_if_need(&mut delta);
+    let mut delta = make_delta_from_revisions(revisions)?;
+    correct_delta(&mut delta);
 
     Result::<DocumentInfo, FlowyError>::Ok(DocumentInfo {
         doc_id: doc_id.to_owned(),
@@ -260,16 +246,20 @@ fn mk_doc_from_revisions(doc_id: &str, revisions: Vec<Revision>) -> FlowyResult<
     })
 }
 
-fn correct_delta_if_need(delta: &mut RichTextDelta) {
-    trim(delta);
-
-    if delta.ops.last().is_none() {
-        return;
+// quill-editor requires the delta should end with '\n' and only contains the
+// insert operation. The function, correct_delta maybe be removed in the future.
+fn correct_delta(delta: &mut RichTextDelta) {
+    if let Some(op) = delta.ops.last() {
+        let op_data = op.get_data();
+        if !op_data.ends_with('\n') {
+            log::warn!("The document must end with newline. Correcting it by inserting newline op");
+            delta.ops.push(Operation::Insert("\n".into()));
+        }
     }
-    let data = delta.ops.last().as_ref().unwrap().get_data();
-    if !data.ends_with('\n') {
-        log::error!("❌The op must end with newline. Correcting it by inserting newline op");
-        delta.ops.push(Operation::Insert("\n".into()));
+
+    if let Some(op) = delta.ops.iter().find(|op| !op.is_insert()) {
+        log::warn!("The document can only contains insert operations, but found {:?}", op);
+        delta.ops.retain(|op| op.is_insert());
     }
 }
 

+ 5 - 9
frontend/rust-lib/flowy-document/src/core/web_socket/web_socket.rs

@@ -130,17 +130,12 @@ impl DocumentWSSinkDataProvider for DocumentWSSinkDataProviderAdapter {
 }
 
 async fn transform_pushed_revisions(
-    revisions: &[Revision],
+    revisions: Vec<Revision>,
     edit_cmd: &UnboundedSender<EditorCommand>,
 ) -> FlowyResult<TransformDeltas> {
     let (ret, rx) = oneshot::channel::<CollaborateResult<TransformDeltas>>();
-    // Transform the revision
-    let _ = edit_cmd.send(EditorCommand::TransformRevision {
-        revisions: revisions.to_vec(),
-        ret,
-    });
-    let transformed_delta = rx.await.map_err(internal_error)??;
-    Ok(transformed_delta)
+    let _ = edit_cmd.send(EditorCommand::TransformRevision { revisions, ret });
+    Ok(rx.await.map_err(internal_error)??)
 }
 
 #[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))]
@@ -170,7 +165,8 @@ pub(crate) async fn handle_remote_revision(
     let TransformDeltas {
         client_prime,
         server_prime,
-    } = transform_pushed_revisions(&revisions, &edit_cmd_tx).await?;
+    } = transform_pushed_revisions(revisions.clone(), &edit_cmd_tx).await?;
+
     match server_prime {
         None => {
             // The server_prime is None means the client local revisions conflict with the

+ 2 - 2
frontend/rust-lib/flowy-user/src/services/user/user_session.rs

@@ -1,7 +1,6 @@
-use std::sync::Arc;
-
 use parking_lot::RwLock;
 use serde::{Deserialize, Serialize};
+use std::sync::Arc;
 use tokio::sync::mpsc;
 
 use backend_service::configuration::ClientServerConfiguration;
@@ -293,6 +292,7 @@ struct Session {
     user_id: String,
     token: String,
     email: String,
+    #[serde(default)]
     name: String,
 }
 

+ 4 - 4
shared-lib/flowy-collaboration/src/util.rs

@@ -45,15 +45,15 @@ impl RevIdCounter {
 }
 
 pub fn make_delta_from_revisions(revisions: Vec<Revision>) -> CollaborateResult<RichTextDelta> {
-    let mut new_delta = RichTextDelta::new();
+    let mut delta = RichTextDelta::new();
     for revision in revisions {
-        let delta = RichTextDelta::from_bytes(revision.delta_data).map_err(|e| {
+        let revision_delta = RichTextDelta::from_bytes(revision.delta_data).map_err(|e| {
             let err_msg = format!("Deserialize remote revision failed: {:?}", e);
             CollaborateError::internal().context(err_msg)
         })?;
-        new_delta = new_delta.compose(&delta)?;
+        delta = delta.compose(&revision_delta)?;
     }
-    Ok(new_delta)
+    Ok(delta)
 }
 
 pub fn make_delta_from_revision_pb(revisions: Vec<RevisionPB>) -> CollaborateResult<RichTextDelta> {

+ 1 - 1
shared-lib/lib-ot/src/core/delta/delta.rs

@@ -241,7 +241,7 @@ where
                 .next_op_with_len(length)
                 .unwrap_or_else(|| OpBuilder::retain(length).build());
 
-            debug_assert_eq!(op.len(), other_op.len());
+            // debug_assert_eq!(op.len(), other_op.len(), "Composing delta failed,");
 
             match (&op, &other_op) {
                 (Operation::Retain(retain), Operation::Retain(other_retain)) => {