LogoLogo
  • AppFlowy
    • ⭐Start here
      • Welcome to AppFlowy Docs
      • How to get help
      • Install AppFlowy
    • 🛠️Installation
      • 🖥️System Requirements
      • 💿Installation methods
        • Mac / Windows / Linux Packages
          • Installing on Linux
            • Installing & Setting up Flutter on Linux from Source
        • Docker
    • 🌱Community
      • 🤙Get in contact
      • 📔AppFlowy Mentorship Program
        • Program Guidance
        • Proposal Template
        • Pull Request Template
        • Mentorship 2023
          • Mentee Projects
            • Calendar View for AppFlowy Database
            • Custom Themes
            • Shortcuts and Customized Hotkeys for AppFlowy
            • Table
            • ⭐Favorites
            • Code Block
            • Outlines
            • Importers
            • AI Writers
            • Templates
          • Project Ideas
      • ✍️Write for AppFlowy
        • 📃Drafts
          • [Draft] Use Case: Software Engineer
          • [Draft] Use Case: High School Students
          • [Draft] How to add a new property to appflowy database
      • 🍂Hacktoberfest
    • 🛣️Roadmap
    • 🌋Product
      • 💽Data Storage
      • 🎨Customize and Style Content
      • ⏮️Duplicate, Delete, and Restore
      • 💎Databases
        • 🔢Database Properties
        • 🗃️Manage Properties
      • Ⓜ️Markdown
      • ⌨️Shortcuts
      • 🪄AppFlowy AI
      • 🦙AppFlowy Local AI - Ollama
      • 🎨Themes
      • ☁️AppFlowy Cloud
      • 🧩AppFlowy Plugins
        • Table-view Databases
        • Kanban Board
        • Calendar
        • Auto Generator
        • Smart Edit
        • Code Blocks
        • Math Equations
        • Cover
        • Emoji
  • Documentation
    • 💎Software Contributions
      • 🟢Get started
      • 💀Architecture
        • Frontend
          • Tauri
            • 🗺️CodeMap
          • Web
            • 🌟Design Philosophy
          • Flutter
            • 🗺️Project Structure: CodeMap
            • 🧮Grid
            • ⚙️Setting
          • Inter-Process Communication
          • User
            • User Data
            • Events & Notifications
          • Folder
            • Events & Notifications
          • Document
          • Database View
            • Events & Notifications
            • Grid
            • Calendar
            • Kanban Board
        • Backend
          • Initialize
          • Events
          • Delta(WIP)
          • Profiling
          • Database
        • Domain Driven Design
        • Proposals
      • 🏗️Conventions
        • 🔤Naming Conventions
        • ⌨️Code Conventions
          • 🐦Flutter
        • 🐙Git Conventions
      • 💛Submitting Code
        • 🏦Setting Up Your Repositories
        • ⤴️Submitting your first Pull Request
      • 🤟Coding Standards and Practices
        • 👽Rust Backend
    • 🚀AppFlowy
      • 👾How to contribute to AppFlowy
      • 🏗️Building from Source
        • 🌳Flutter Setup
          • 🐧Building on Linux
          • 🍎Building on macOS
          • 🪟Building on Windows
        • 🌐Web Setup
        • 📡Tauri Setup
      • ☁️Debugging with AppFlowy Cloud
      • 🔁Debugging in VS Code
      • ☎️Translate AppFlowy
      • ❓Troubleshooting
      • 👮‍♀️Licenses
    • 🏍️AppFlowy Editor
      • ⌨️How to Implement Markdown Syntax To Style Text In AppFlowy Editor
      • 🧩How to Create a Plugin for AppFlowy Editor
      • 👮‍♀️Licenses
    • ☁️AppFlowy Cloud
      • 🌈Architecture
      • ☀️Deployment
  • Guides
    • Sync Desktop and Mobile
    • Self-Hosting AppFlowy
      • ☁️Self-hosting AppFlowy with AppFlowy Cloud
      • 🆓Self-hosting AppFlowy for free Using Supabase
    • Import From Notion
  • Blog Highlights
    • 🔮Demystifying AppFlowy Editor's Codebase
  • Handbook
    • Core values
Powered by GitBook
On this page
  • DeltaIterator
  • DeltaCursor
  • DeltaBuilder
  • Operation
  • Insert
  • Delete
  • Retain
  • OTString
  • Attributes
  • RichTextAttributes
  • PhantomAttributes
  • OperationTransform
  • Serde
  • Import and Export
  • Markdown

Was this helpful?

Edit on GitHub
  1. Documentation
  2. Software Contributions
  3. Architecture
  4. Backend

Delta(WIP)

PreviousEventsNextProfiling

Last updated 2 years ago

Was this helpful?

A Delta contains a list of operations, which describe the changes to a document. There are three kinds of operations, insert, delete, and retain. The implementation of Delta is located in the lib-ot(shared-lib/lib-ot) crate.The format of Delta is JSON based, and is human readable, it can describe any rich text document, includes all text and formatting information.

The picture shown below is a UML diagram that describes the relations between these classes. We're going to explain them on by one.

DeltaIterator

let mut delta = RichTextDelta::default();
delta.add(Operation::insert("123"));
delta.add(Operation::insert("4"));
assert_eq!(
    DeltaIterator::from_interval(&delta, Interval::new(0, 2)).ops(),
    vec![Operation::insert("12")]
);

assert_eq!(
    DeltaIterator::from_interval(&delta, Interval::new(1, 3)).ops(),
    vec![Operation::insert("23")]
);

DeltaCursor

let mut delta = RichTextDelta::default();   
delta.add(Operation::insert("123"));    
delta.add(Operation::insert("4"));

let mut cursor = DeltaCursor::new(&delta, Interval::new(0, 3));
assert_eq!(cursor.next_iv(), Interval::new(0,3));
assert_eq!(cursor.next_with_len(Some(2)).unwrap(), Operation::insert("12"));
assert_eq!(cursor.get_next_op().unwrap(), Operation::insert("3"));
assert_eq!(cursor.get_next_op(), None);

DeltaBuilder

let delta = TextDeltaBuilder::new()
    .insert("AppFlowy")
    .build();
assert_eq!(delta.content().unwrap(), "AppFlowy");

let mut attribute = RichTextAttribute::Bold(true);
let delta = RichTextDeltaBuilder::new().retain_with_attributes(7, attribute.into()).build();    
assert_eq!(delta.json_str(), r#"[{"retain":7,"attributes":{"bold":true}}]"#);

Operation

Operation contains three types, Insert, Delete, and Retain.

Insert

Insert operations have an insert key defined. A String value represents inserting text. an optional attributes key can be defined with an Object to describe additional formatting information. Formats can be changed by the retain operation.

Delete

Delete operations have a Number delete key defined representing the number of characters to delete.

Retain

Retain operations have a Number retain key defined representing the number of characters to keep An optional attributes key can be defined with an Object to describe formatting changes to the character range. A value of null in the attributes Object represents removal of that key.

OTString

The length of strings behaves differently in different languages. For example: [Dart] string's length is calculated with UTF-16 code units. The method [utf16_len] returns the length of a String in UTF-16 code units.

let utf16_len = OTString::from("👋").utf16_len();
assert_eq!(utf16_len, 2);
let bytes_len = String::from("👋").len();
assert_eq!(bytes_len, 4);

OTUtf16CodePointIterator

let s: OTString = "👋😁👋".into();    ///
let mut iter = s.utf16_code_point_iter();
assert_eq!(iter.next().unwrap(), "👋".to_string());
assert_eq!(iter.next().unwrap(), "😁".to_string());
assert_eq!(iter.next().unwrap(), "👋".to_string());
assert_eq!(iter.next(), None);

let mut iter = s.utf16_code_point_iter();
assert_eq!(iter.next().unwrap(), "👋".to_string());
assert_eq!(iter.next().unwrap(), "1".to_string());
assert_eq!(iter.next().unwrap(), "2".to_string());
assert_eq!(iter.skip(OTString::from("ab一二").utf16_len()).next().unwrap(), "👋".to_string());

Attributes

Each operation can carry attributes. For example, the [RichTextAttributes] has a list of key/value attributes. Such as { bold: true, italic: true }.

Because [Operation] is generic over the T, so you must specify the T. For example, the [TextDelta] uses [PhantomAttributes] as the T. [PhantomAttributes] does nothing, just a phantom.

RichTextAttributes

pub type RichTextDelta = Delta<RichTextAttributes>;
pub type RichTextDeltaBuilder = DeltaBuilder<RichTextAttributes>;

PhantomAttributes

pub type TextDelta = Delta<PhantomAttributes>;
pub type TextDeltaBuilder = DeltaBuilder<PhantomAttributes>;

OperationTransform

https://en.wikipedia.org/wiki/Operational_transformation

pub trait OperationTransform {
    /// Merges the operation with `other` into one operation while preserving
    /// the changes of both.    
    ///
    /// # Arguments
    ///
    /// * `other`: The delta gonna to merge.
    ///
    /// # Examples
    ///
    /// ```
    ///  use lib_ot::core::{OperationTransform, TextDeltaBuilder};
    ///  let document = TextDeltaBuilder::new().build();
    ///  let delta = TextDeltaBuilder::new().insert("abc").build();
    ///  let new_document = document.compose(&delta).unwrap();
    ///  assert_eq!(new_document.content().unwrap(), "abc".to_owned());
    /// ```
    fn compose(&self, other: &Self) -> Result<Self, OTError>
        where
            Self: Sized;

    /// Transforms two operations a and b that happened concurrently and
    /// produces two operations a' and b'.
    ///  (a', b') = a.transform(b)
    ///  a.compose(b') = b.compose(a')    
    ///
    fn transform(&self, other: &Self) -> Result<(Self, Self), OTError>
        where
            Self: Sized;

    /// Returns the invert delta from the other. It can be used to do the undo operation.
    ///
    /// # Arguments
    ///
    /// * `other`:  Generate the undo delta for [Other]. [Other] can compose the undo delta to return
    /// to the previous state.
    ///
    /// # Examples
    ///
    /// ```
    /// use lib_ot::core::{OperationTransform, TextDeltaBuilder};
    /// let original_document = TextDeltaBuilder::new().build();
    /// let delta = TextDeltaBuilder::new().insert("abc").build();
    ///
    /// let undo_delta = delta.invert(&original_document);
    /// let new_document = original_document.compose(&delta).unwrap();
    /// let document = new_document.compose(&undo_delta).unwrap();
    ///
    /// assert_eq!(original_document, document);
    ///
    /// ```
    fn invert(&self, other: &Self) -> Self;
}

Serde

Import and Export

Markdown

We can use a Markdown parser to import the document into AppFlowy or export the data to a Markdown file. AppFlowy uses Delta to represent the document content.

💎
💀
file : delta.plantuml