mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Try to fix quill-editor load document error. Because Document can only contain insert operations
This commit is contained in:
parent
ddd0dec5c3
commit
85ad90fc51
@ -15,7 +15,7 @@ use flowy_error::FlowyResult;
|
||||
use futures_util::{future, stream, stream::StreamExt};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::{
|
||||
core::{Operation, OperationTransformable},
|
||||
core::{trim, Operation, OperationTransformable},
|
||||
errors::OTError,
|
||||
rich_text::RichTextDelta,
|
||||
};
|
||||
@ -259,11 +259,13 @@ fn mk_doc_from_revisions(doc_id: &str, revisions: Vec<Revision>) -> FlowyResult<
|
||||
base_rev_id,
|
||||
})
|
||||
}
|
||||
|
||||
fn correct_delta_if_need(delta: &mut RichTextDelta) {
|
||||
trim(delta);
|
||||
|
||||
if delta.ops.last().is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -1,10 +1,3 @@
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use lib_ot::{
|
||||
core::*,
|
||||
rich_text::{RichTextAttribute, RichTextDelta},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
document::{
|
||||
default::initial_delta,
|
||||
@ -13,6 +6,11 @@ use crate::{
|
||||
},
|
||||
errors::CollaborateError,
|
||||
};
|
||||
use lib_ot::{
|
||||
core::*,
|
||||
rich_text::{RichTextAttribute, RichTextDelta},
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
pub trait InitialDocumentText {
|
||||
fn initial_delta() -> RichTextDelta;
|
||||
@ -81,12 +79,10 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compose_delta(&mut self, mut delta: RichTextDelta) -> Result<(), CollaborateError> {
|
||||
pub fn compose_delta(&mut self, delta: RichTextDelta) -> Result<(), CollaborateError> {
|
||||
tracing::trace!("👉 receive change: {}", delta);
|
||||
|
||||
trim(&mut delta);
|
||||
tracing::trace!("{} compose {}", &self.delta.to_json(), delta.to_json());
|
||||
let mut composed_delta = self.delta.compose(&delta)?;
|
||||
let composed_delta = self.delta.compose(&delta)?;
|
||||
let mut undo_delta = delta.invert(&self.delta);
|
||||
|
||||
let now = chrono::Utc::now().timestamp_millis() as usize;
|
||||
@ -107,7 +103,6 @@ impl Document {
|
||||
}
|
||||
|
||||
tracing::trace!("compose result: {}", composed_delta.to_json());
|
||||
trim(&mut composed_delta);
|
||||
|
||||
self.set_delta(composed_delta);
|
||||
Ok(())
|
||||
@ -171,11 +166,9 @@ impl Document {
|
||||
None => Err(CollaborateError::undo().context("Undo stack is empty")),
|
||||
Some(undo_delta) => {
|
||||
let (new_delta, inverted_delta) = self.invert(&undo_delta)?;
|
||||
let result = UndoResult::success(new_delta.target_len as usize);
|
||||
self.set_delta(new_delta);
|
||||
self.history.add_redo(inverted_delta);
|
||||
|
||||
Ok(result)
|
||||
Ok(UndoResult { delta: undo_delta })
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -185,11 +178,9 @@ impl Document {
|
||||
None => Err(CollaborateError::redo()),
|
||||
Some(redo_delta) => {
|
||||
let (new_delta, inverted_delta) = self.invert(&redo_delta)?;
|
||||
let result = UndoResult::success(new_delta.target_len as usize);
|
||||
self.set_delta(new_delta);
|
||||
|
||||
self.history.add_undo(inverted_delta);
|
||||
Ok(result)
|
||||
Ok(UndoResult { delta: redo_delta })
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -216,12 +207,3 @@ fn validate_interval(delta: &RichTextDelta, interval: &Interval) -> Result<(), C
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes trailing retain operation with empty attributes, if present.
|
||||
pub fn trim(delta: &mut RichTextDelta) {
|
||||
if let Some(last) = delta.ops.last() {
|
||||
if last.is_retain() && last.is_plain() {
|
||||
delta.ops.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::core::{Attributes, Delta, Operation};
|
||||
use crate::core::{trim, Attributes, Delta, Operation};
|
||||
|
||||
pub struct DeltaBuilder<T: Attributes> {
|
||||
delta: Delta<T>,
|
||||
@ -49,17 +49,3 @@ where
|
||||
|
||||
pub fn build(self) -> Delta<T> { self.delta }
|
||||
}
|
||||
|
||||
pub fn trim<T: Attributes>(delta: &mut Delta<T>) {
|
||||
let remove_last = match delta.ops.last() {
|
||||
None => false,
|
||||
Some(op) => match op {
|
||||
Operation::Delete(_) => false,
|
||||
Operation::Retain(retain) => retain.is_plain(),
|
||||
Operation::Insert(_) => false,
|
||||
},
|
||||
};
|
||||
if remove_last {
|
||||
delta.ops.pop();
|
||||
}
|
||||
}
|
||||
|
@ -150,17 +150,17 @@ where
|
||||
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
|
||||
}
|
||||
let mut new_s = String::new();
|
||||
let chars = &mut s.chars();
|
||||
let utf16_iter = &mut s.utf16_iter();
|
||||
for op in &self.ops {
|
||||
match &op {
|
||||
Operation::Retain(retain) => {
|
||||
for c in chars.take(retain.n as usize) {
|
||||
new_s.push(c);
|
||||
for c in utf16_iter.take(retain.n as usize) {
|
||||
new_s.push_str(&c);
|
||||
}
|
||||
},
|
||||
Operation::Delete(delete) => {
|
||||
for _ in 0..*delete {
|
||||
chars.next();
|
||||
utf16_iter.next();
|
||||
}
|
||||
},
|
||||
Operation::Insert(insert) => {
|
||||
@ -264,7 +264,6 @@ where
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(new_delta)
|
||||
}
|
||||
|
||||
@ -428,6 +427,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes trailing retain operation with empty attributes, if present.
|
||||
pub fn trim<T>(delta: &mut Delta<T>)
|
||||
where
|
||||
T: Attributes,
|
||||
{
|
||||
if let Some(last) = delta.ops.last() {
|
||||
if last.is_retain() && last.is_plain() {
|
||||
delta.ops.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn invert_from_other<T: Attributes>(
|
||||
base: &mut Delta<T>,
|
||||
other: &Delta<T>,
|
||||
|
Loading…
Reference in New Issue
Block a user