2021-08-05 20:05:40 +08:00
|
|
|
use crate::{
|
2021-08-11 11:42:46 +08:00
|
|
|
client::{view::View, History, RevId, UndoResult},
|
2021-08-10 11:22:57 +08:00
|
|
|
core::*,
|
2021-08-05 22:52:19 +08:00
|
|
|
errors::{ErrorBuilder, OTError, OTErrorCode::*},
|
2021-08-05 20:05:40 +08:00
|
|
|
};
|
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
pub const RECORD_THRESHOLD: usize = 400; // in milliseconds
|
|
|
|
|
2021-08-05 20:05:40 +08:00
|
|
|
pub struct Document {
|
2021-08-11 11:42:46 +08:00
|
|
|
delta: Delta,
|
2021-08-05 20:05:40 +08:00
|
|
|
history: History,
|
2021-08-11 11:42:46 +08:00
|
|
|
view: View,
|
2021-08-06 23:06:27 +08:00
|
|
|
rev_id_counter: usize,
|
2021-08-10 11:22:57 +08:00
|
|
|
last_edit_time: usize,
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Document {
|
|
|
|
pub fn new() -> Self {
|
2021-08-06 23:06:27 +08:00
|
|
|
let delta = Delta::new();
|
2021-08-05 20:05:40 +08:00
|
|
|
Document {
|
2021-08-11 11:42:46 +08:00
|
|
|
delta,
|
2021-08-05 20:05:40 +08:00
|
|
|
history: History::new(),
|
2021-08-11 11:42:46 +08:00
|
|
|
view: View::new(),
|
2021-08-05 22:52:19 +08:00
|
|
|
rev_id_counter: 1,
|
2021-08-10 11:22:57 +08:00
|
|
|
last_edit_time: 0,
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-11 08:40:58 +08:00
|
|
|
pub fn insert(&mut self, index: usize, text: &str) -> Result<(), OTError> {
|
2021-08-11 11:42:46 +08:00
|
|
|
if self.delta.target_len < index {
|
2021-08-05 20:05:40 +08:00
|
|
|
log::error!(
|
|
|
|
"{} out of bounds. should 0..{}",
|
|
|
|
index,
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta.target_len
|
2021-08-05 20:05:40 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
let probe = Interval::new(index, index + 1);
|
2021-08-11 11:42:46 +08:00
|
|
|
let mut attributes = self.delta.get_attributes(probe);
|
2021-08-10 14:24:41 +08:00
|
|
|
if attributes.is_empty() {
|
2021-08-05 20:05:40 +08:00
|
|
|
attributes = Attributes::Follow;
|
|
|
|
}
|
2021-08-11 11:42:46 +08:00
|
|
|
|
|
|
|
// let delta = self.view.handle_insert(&self.delta, s, interval);
|
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
let mut delta = Delta::new();
|
2021-08-08 22:29:16 +08:00
|
|
|
let insert = Builder::insert(text).attributes(attributes).build();
|
2021-08-05 20:05:40 +08:00
|
|
|
let interval = Interval::new(index, index);
|
2021-08-10 11:22:57 +08:00
|
|
|
delta.add(insert);
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
self.update_with_op(&delta, interval)
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-06 08:40:45 +08:00
|
|
|
pub fn format(
|
|
|
|
&mut self,
|
|
|
|
interval: Interval,
|
|
|
|
attribute: Attribute,
|
|
|
|
enable: bool,
|
|
|
|
) -> Result<(), OTError> {
|
2021-08-05 20:05:40 +08:00
|
|
|
let attributes = match enable {
|
2021-08-07 09:19:18 +08:00
|
|
|
true => AttrsBuilder::new().add(attribute).build(),
|
|
|
|
false => AttrsBuilder::new().remove(&attribute).build(),
|
2021-08-05 20:05:40 +08:00
|
|
|
};
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("format with {} at {}", attributes, interval);
|
2021-08-06 08:40:45 +08:00
|
|
|
self.update_with_attribute(attributes, interval)
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-11 08:40:58 +08:00
|
|
|
pub fn replace(&mut self, interval: Interval, s: &str) -> Result<(), OTError> {
|
|
|
|
let mut delta = Delta::default();
|
|
|
|
if !s.is_empty() {
|
|
|
|
let insert = Builder::insert(s).attributes(Attributes::Follow).build();
|
|
|
|
delta.add(insert);
|
|
|
|
}
|
|
|
|
|
|
|
|
if !interval.is_empty() {
|
|
|
|
let delete = Builder::delete(interval.size()).build();
|
|
|
|
delta.add(delete);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.update_with_op(&delta, interval)
|
|
|
|
}
|
|
|
|
|
2021-08-05 22:52:19 +08:00
|
|
|
pub fn can_undo(&self) -> bool { self.history.can_undo() }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-05 22:52:19 +08:00
|
|
|
pub fn can_redo(&self) -> bool { self.history.can_redo() }
|
|
|
|
|
|
|
|
pub fn undo(&mut self) -> Result<UndoResult, OTError> {
|
|
|
|
match self.history.undo() {
|
2021-08-10 11:22:57 +08:00
|
|
|
None => Err(ErrorBuilder::new(UndoFail)
|
|
|
|
.msg("Undo stack is empty")
|
|
|
|
.build()),
|
2021-08-05 22:52:19 +08:00
|
|
|
Some(undo_delta) => {
|
2021-08-10 11:22:57 +08:00
|
|
|
let (new_delta, inverted_delta) = self.invert_change(&undo_delta)?;
|
|
|
|
let result = UndoResult::success(new_delta.target_len as usize);
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta = new_delta;
|
2021-08-10 11:22:57 +08:00
|
|
|
self.history.add_redo(inverted_delta);
|
2021-08-05 22:52:19 +08:00
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn redo(&mut self) -> Result<UndoResult, OTError> {
|
|
|
|
match self.history.redo() {
|
|
|
|
None => Err(ErrorBuilder::new(RedoFail).build()),
|
|
|
|
Some(redo_delta) => {
|
2021-08-10 11:22:57 +08:00
|
|
|
let (new_delta, inverted_delta) = self.invert_change(&redo_delta)?;
|
2021-08-06 23:06:27 +08:00
|
|
|
let result = UndoResult::success(new_delta.target_len as usize);
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta = new_delta;
|
2021-08-08 22:29:16 +08:00
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
self.history.add_undo(inverted_delta);
|
2021-08-05 22:52:19 +08:00
|
|
|
Ok(result)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn to_json(&self) -> String { self.delta.to_json() }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
|
2021-08-06 22:25:09 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn data(&self) -> &Delta { &self.delta }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
pub fn set_data(&mut self, data: Delta) { self.delta = data; }
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
fn update_with_op(&mut self, delta: &Delta, interval: Interval) -> Result<(), OTError> {
|
2021-08-05 20:05:40 +08:00
|
|
|
let mut new_delta = Delta::default();
|
2021-08-11 11:42:46 +08:00
|
|
|
let (prefix, interval, suffix) =
|
|
|
|
split_length_with_interval(self.delta.target_len, interval);
|
2021-08-05 20:05:40 +08:00
|
|
|
|
|
|
|
// prefix
|
|
|
|
if prefix.is_empty() == false && prefix != interval {
|
2021-08-11 11:42:46 +08:00
|
|
|
DeltaAttributesIter::from_interval(&self.delta, prefix).for_each(
|
|
|
|
|(length, attributes)| {
|
|
|
|
log::debug!("prefix attribute: {:?}, len: {}", attributes, length);
|
|
|
|
new_delta.retain(length, attributes);
|
|
|
|
},
|
|
|
|
);
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
delta.ops.iter().for_each(|op| {
|
|
|
|
new_delta.add(op.clone());
|
|
|
|
});
|
2021-08-05 20:05:40 +08:00
|
|
|
|
|
|
|
// suffix
|
|
|
|
if suffix.is_empty() == false {
|
2021-08-11 11:42:46 +08:00
|
|
|
DeltaAttributesIter::from_interval(&self.delta, suffix).for_each(
|
|
|
|
|(length, attributes)| {
|
|
|
|
log::debug!("suffix attribute: {:?}, len: {}", attributes, length);
|
|
|
|
new_delta.retain(length, attributes);
|
|
|
|
},
|
|
|
|
);
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
self.delta = self.record_change(&new_delta)?;
|
2021-08-06 08:40:45 +08:00
|
|
|
Ok(())
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
2021-08-06 08:40:45 +08:00
|
|
|
pub fn update_with_attribute(
|
|
|
|
&mut self,
|
|
|
|
mut attributes: Attributes,
|
|
|
|
interval: Interval,
|
|
|
|
) -> Result<(), OTError> {
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("Update document with attributes: {:?}", attributes,);
|
2021-08-11 11:42:46 +08:00
|
|
|
let old_attributes = self.delta.get_attributes(interval);
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("combine with old: {:?}", old_attributes);
|
2021-08-05 20:05:40 +08:00
|
|
|
let new_attributes = match &mut attributes {
|
|
|
|
Attributes::Follow => old_attributes,
|
|
|
|
Attributes::Custom(attr_data) => {
|
2021-08-10 17:08:47 +08:00
|
|
|
attr_data.merge(old_attributes.data());
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("combine with old result : {:?}", attr_data);
|
2021-08-10 17:08:47 +08:00
|
|
|
attr_data.clone().into()
|
2021-08-05 20:05:40 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("combine result: {:?}", new_attributes);
|
2021-08-08 22:29:16 +08:00
|
|
|
let retain = Builder::retain(interval.size())
|
2021-08-05 20:05:40 +08:00
|
|
|
.attributes(new_attributes)
|
|
|
|
.build();
|
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
let mut delta = Delta::new();
|
|
|
|
delta.add(retain);
|
2021-08-05 20:05:40 +08:00
|
|
|
|
2021-08-10 11:22:57 +08:00
|
|
|
self.update_with_op(&delta, interval)
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
2021-08-05 22:52:19 +08:00
|
|
|
|
|
|
|
fn next_rev_id(&self) -> RevId { RevId(self.rev_id_counter) }
|
2021-08-10 11:22:57 +08:00
|
|
|
|
|
|
|
fn record_change(&mut self, delta: &Delta) -> Result<Delta, OTError> {
|
|
|
|
let (composed_delta, mut undo_delta) = self.invert_change(&delta)?;
|
|
|
|
self.rev_id_counter += 1;
|
|
|
|
|
|
|
|
let now = chrono::Utc::now().timestamp_millis() as usize;
|
|
|
|
if now - self.last_edit_time < RECORD_THRESHOLD {
|
|
|
|
if let Some(last_delta) = self.history.undo() {
|
|
|
|
log::debug!("compose previous change");
|
|
|
|
log::debug!("current = {}", undo_delta);
|
|
|
|
log::debug!("previous = {}", last_delta);
|
|
|
|
undo_delta = undo_delta.compose(&last_delta)?;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.last_edit_time = now;
|
|
|
|
}
|
|
|
|
|
|
|
|
if !undo_delta.is_empty() {
|
|
|
|
log::debug!("record change: {}", undo_delta);
|
|
|
|
self.history.record(undo_delta);
|
|
|
|
}
|
|
|
|
|
2021-08-10 14:24:41 +08:00
|
|
|
log::debug!("document delta: {}", &composed_delta);
|
2021-08-10 11:22:57 +08:00
|
|
|
Ok(composed_delta)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn invert_change(&self, change: &Delta) -> Result<(Delta, Delta), OTError> {
|
|
|
|
// c = a.compose(b)
|
|
|
|
// d = b.invert(a)
|
|
|
|
// a = c.compose(d)
|
|
|
|
log::debug!("👉invert change {}", change);
|
2021-08-11 11:42:46 +08:00
|
|
|
let new_delta = self.delta.compose(change)?;
|
|
|
|
let inverted_delta = change.invert(&self.delta);
|
2021-08-10 11:22:57 +08:00
|
|
|
// trim(&mut inverted_delta);
|
|
|
|
|
|
|
|
Ok((new_delta, inverted_delta))
|
|
|
|
}
|
2021-08-05 20:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn split_length_with_interval(length: usize, interval: Interval) -> (Interval, Interval, Interval) {
|
|
|
|
let original_interval = Interval::new(0, length);
|
|
|
|
let prefix = original_interval.prefix(interval);
|
|
|
|
let suffix = original_interval.suffix(interval);
|
|
|
|
(prefix, interval, suffix)
|
|
|
|
}
|
|
|
|
|
2021-08-11 11:42:46 +08:00
|
|
|
fn split_interval_by_delta(delta: &Delta, interval: &Interval) -> Vec<Interval> {
|
2021-08-05 20:05:40 +08:00
|
|
|
let mut start = 0;
|
|
|
|
let mut new_intervals = vec![];
|
|
|
|
delta.ops.iter().for_each(|op| match op {
|
|
|
|
Operation::Delete(_) => {},
|
|
|
|
Operation::Retain(_) => {},
|
|
|
|
Operation::Insert(insert) => {
|
|
|
|
let len = insert.num_chars() as usize;
|
|
|
|
let end = start + len;
|
|
|
|
let insert_interval = Interval::new(start, end);
|
|
|
|
let new_interval = interval.intersect(insert_interval);
|
|
|
|
|
|
|
|
if !new_interval.is_empty() {
|
|
|
|
new_intervals.push(new_interval)
|
|
|
|
}
|
|
|
|
start += len;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
new_intervals
|
|
|
|
}
|
2021-08-10 11:22:57 +08:00
|
|
|
|
|
|
|
pub fn trim(delta: &mut Delta) {
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|