chore: impl handler logic

This commit is contained in:
appflowy
2022-03-05 10:59:44 +08:00
parent d0b457c007
commit 8029f1035d
30 changed files with 304 additions and 178 deletions

View File

@ -1071,6 +1071,7 @@ dependencies = [
"rusty-money",
"strum",
"strum_macros",
"tokio",
"tracing",
"uuid",
]

View File

@ -85,7 +85,7 @@ impl BlockManager {
let doc_id = doc_id.as_ref().to_owned();
let db_pool = self.block_user.db_pool()?;
// Maybe we could save the block to disk without creating the RevisionManager
let rev_manager = self.make_rev_manager(&doc_id, db_pool)?;
let rev_manager = self.make_block_rev_manager(&doc_id, db_pool)?;
let _ = rev_manager.reset_object(revisions).await?;
Ok(())
}
@ -125,7 +125,7 @@ impl BlockManager {
) -> Result<Arc<ClientBlockEditor>, FlowyError> {
let user = self.block_user.clone();
let token = self.block_user.token()?;
let rev_manager = self.make_rev_manager(block_id, pool.clone())?;
let rev_manager = self.make_block_rev_manager(block_id, pool.clone())?;
let cloud_service = Arc::new(BlockRevisionCloudService {
token,
server: self.cloud_service.clone(),
@ -136,7 +136,7 @@ impl BlockManager {
Ok(doc_editor)
}
fn make_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, FlowyError> {
fn make_block_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, FlowyError> {
let user_id = self.block_user.user_id()?;
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, doc_id, pool));
Ok(RevisionManager::new(&user_id, doc_id, rev_persistence))

View File

@ -1,6 +1,6 @@
use bytes::Bytes;
use chrono::Utc;
use flowy_collaboration::client_document::default::{initial_delta, initial_read_me};
use flowy_collaboration::client_document::default::{initial_quill_delta, initial_quill_delta_string, initial_read_me};
use flowy_folder_data_model::user_default;
use flowy_sync::RevisionWebSocket;
use lazy_static::lazy_static;
@ -199,13 +199,10 @@ impl DefaultFolderBuilder {
let view_data = if index == 0 {
initial_read_me().to_delta_json()
} else {
initial_delta().to_delta_json()
initial_quill_delta_string()
};
view_controller.set_latest_view(view);
let delta_data = Bytes::from(view_data);
let repeated_revision: RepeatedRevision =
Revision::initial_revision(user_id, &view.id, delta_data).into();
let _ = view_controller.create_view(&view.id, repeated_revision).await?;
let _ = view_controller.create_view(&view.id, Bytes::from(view_data)).await?;
}
}
let folder = FolderPad::new(vec![workspace.clone()], vec![])?;

View File

@ -86,6 +86,7 @@ impl ViewTable {
let data_type = match view.data_type {
ViewDataType::RichText => SqlViewDataType::RichText,
ViewDataType::PlainText => SqlViewDataType::PlainText,
ViewDataType::Grid => SqlViewDataType::Grid,
};
ViewTable {
@ -108,6 +109,7 @@ impl std::convert::From<ViewTable> for View {
let data_type = match table.view_type {
SqlViewDataType::RichText => ViewDataType::RichText,
SqlViewDataType::PlainText => ViewDataType::PlainText,
SqlViewDataType::Grid => ViewDataType::Grid,
};
View {
@ -179,6 +181,7 @@ impl ViewChangeset {
pub enum SqlViewDataType {
RichText = 0,
PlainText = 1,
Grid = 2,
}
impl std::default::Default for SqlViewDataType {
@ -192,6 +195,7 @@ impl std::convert::From<i32> for SqlViewDataType {
match value {
0 => SqlViewDataType::RichText,
1 => SqlViewDataType::PlainText,
2 => SqlViewDataType::Grid,
o => {
log::error!("Unsupported view type {}, fallback to ViewType::Docs", o);
SqlViewDataType::PlainText

View File

@ -4,7 +4,7 @@ use flowy_collaboration::entities::{
revision::{RepeatedRevision, Revision},
};
use flowy_collaboration::client_document::default::initial_delta_string;
use flowy_collaboration::client_document::default::initial_quill_delta_string;
use futures::{FutureExt, StreamExt};
use std::{collections::HashSet, sync::Arc};
@ -63,30 +63,24 @@ impl ViewController {
#[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)]
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> {
let view_data = if params.data.is_empty() {
initial_delta_string()
initial_quill_delta_string()
} else {
params.data.clone()
};
let delta_data = Bytes::from(view_data);
let user_id = self.user.user_id()?;
let repeated_revision: RepeatedRevision =
Revision::initial_revision(&user_id, &params.view_id, delta_data).into();
let _ = self.create_view(&params.view_id, repeated_revision).await?;
let _ = self.create_view(&params.view_id, Bytes::from(view_data)).await?;
let view = self.create_view_on_server(params).await?;
let _ = self.create_view_on_local(view.clone()).await?;
Ok(view)
}
#[tracing::instrument(level = "debug", skip(self, view_id, repeated_revision), err)]
pub(crate) async fn create_view(
&self,
view_id: &str,
repeated_revision: RepeatedRevision,
) -> Result<(), FlowyError> {
if repeated_revision.is_empty() {
#[tracing::instrument(level = "debug", skip(self, view_id, delta_data), err)]
pub(crate) async fn create_view(&self, view_id: &str, delta_data: Bytes) -> Result<(), FlowyError> {
if delta_data.is_empty() {
return Err(FlowyError::internal().context("The content of the view should not be empty"));
}
let user_id = self.user.user_id()?;
let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, view_id, delta_data).into();
let _ = self.block_manager.create_block(view_id, repeated_revision).await?;
Ok(())
}
@ -304,7 +298,7 @@ impl ViewController {
fn listen_trash_can_event(&self) {
let mut rx = self.trash_controller.subscribe();
let persistence = self.persistence.clone();
let document_manager = self.block_manager.clone();
let block_manager = self.block_manager.clone();
let trash_controller = self.trash_controller.clone();
let _ = tokio::spawn(async move {
loop {
@ -318,7 +312,7 @@ impl ViewController {
if let Some(event) = stream.next().await {
handle_trash_event(
persistence.clone(),
document_manager.clone(),
block_manager.clone(),
trash_controller.clone(),
event,
)

View File

@ -1,5 +1,5 @@
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
use flowy_collaboration::{client_document::default::initial_delta_string, entities::revision::RevisionState};
use flowy_collaboration::{client_document::default::initial_quill_delta_string, entities::revision::RevisionState};
use flowy_folder::entities::workspace::CreateWorkspacePayload;
use flowy_test::{event_builder::*, FlowySDKTest};
@ -175,7 +175,7 @@ async fn open_document_view() {
test.run_scripts(vec![OpenDocument]).await;
let document_info = test.document_info.unwrap();
assert_eq!(document_info.text, initial_delta_string());
assert_eq!(document_info.text, initial_quill_delta_string());
}
#[tokio::test]

View File

@ -30,7 +30,7 @@ uuid = { version = "0.8", features = ["serde", "v4"] }
bytes = { version = "1.0" }
diesel = {version = "1.4.8", features = ["sqlite"]}
dashmap = "4.0"
tokio = {version = "1", features = ["sync"]}
parking_lot = "0.11"

View File

@ -3,53 +3,47 @@ use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{
CreateGridPayload, Grid, GridId, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder,
};
use lib_dispatch::prelude::{AppData, Data, DataResult};
use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
use std::sync::Arc;
#[tracing::instrument(skip(data, controller), err)]
pub(crate) async fn create_grid_handler(
data: Data<CreateGridPayload>,
controller: AppData<Arc<GridManager>>,
) -> DataResult<Grid, FlowyError> {
todo!()
}
#[tracing::instrument(skip(data, controller), err)]
#[tracing::instrument(skip(data, manager), err)]
pub(crate) async fn open_grid_handler(
data: Data<GridId>,
controller: AppData<Arc<GridManager>>,
manager: AppData<Arc<GridManager>>,
) -> DataResult<Grid, FlowyError> {
let _params: GridId = data.into_inner();
todo!()
let grid_id: GridId = data.into_inner();
let editor = manager.open_grid(grid_id).await?;
let grid = editor.grid_data().await;
data_result(grid)
}
#[tracing::instrument(skip(data, controller), err)]
#[tracing::instrument(skip(data, manager), err)]
pub(crate) async fn get_rows_handler(
data: Data<RepeatedRowOrder>,
controller: AppData<Arc<GridManager>>,
manager: AppData<Arc<GridManager>>,
) -> DataResult<RepeatedRow, FlowyError> {
let row_orders: RepeatedRowOrder = data.into_inner();
todo!()
let repeated_row = manager.get_rows(row_orders).await;
data_result(repeated_row)
}
#[tracing::instrument(skip(data, controller), err)]
#[tracing::instrument(skip(data, manager), err)]
pub(crate) async fn get_fields_handler(
data: Data<RepeatedFieldOrder>,
controller: AppData<Arc<GridManager>>,
manager: AppData<Arc<GridManager>>,
) -> DataResult<RepeatedField, FlowyError> {
let field_orders: RepeatedFieldOrder = data.into_inner();
todo!()
let repeated_field = manager.get_fields(field_orders).await;
data_result(repeated_field)
}
#[tracing::instrument(skip(data, controller), err)]
#[tracing::instrument(skip(data, manager), err)]
pub(crate) async fn create_row_handler(
data: Data<GridId>,
controller: AppData<Arc<GridManager>>,
manager: AppData<Arc<GridManager>>,
) -> Result<(), FlowyError> {
let id: GridId = data.into_inner();
let editor = manager.get_grid_editor(id.as_ref())?;
let _ = editor.create_empty_row().await?;
Ok(())
}

View File

@ -8,7 +8,6 @@ use strum_macros::Display;
pub fn create(grid_manager: Arc<GridManager>) -> Module {
let mut module = Module::new().name(env!("CARGO_PKG_NAME")).data(grid_manager);
module = module
.event(GridEvent::CreateGrid, create_grid_handler)
.event(GridEvent::OpenGrid, open_grid_handler)
.event(GridEvent::GetRows, get_rows_handler)
.event(GridEvent::GetFields, get_fields_handler)
@ -20,18 +19,15 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
#[event_err = "FlowyError"]
pub enum GridEvent {
#[event(input = "CreateGridPayload", output = "Grid")]
CreateGrid = 0,
#[event(input = "GridId", output = "Grid")]
OpenGrid = 1,
OpenGrid = 0,
#[event(input = "RepeatedRowOrder", output = "RepeatedRow")]
GetRows = 2,
GetRows = 1,
#[event(input = "RepeatedFieldOrder", output = "RepeatedField")]
GetFields = 3,
GetFields = 2,
#[event(input = "GridId")]
CreateRow = 4,
CreateRow = 3,
}

View File

@ -1,8 +1,15 @@
use crate::services::grid_editor::ClientGridEditor;
use crate::services::kv_persistence::GridKVPersistence;
use dashmap::DashMap;
use flowy_collaboration::client_grid::{make_grid_delta, make_grid_revisions};
use flowy_collaboration::entities::revision::RepeatedRevision;
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{
Field, FieldOrder, Grid, RawRow, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder, RowOrder,
};
use flowy_sync::{RevisionManager, RevisionPersistence, RevisionWebSocket};
use lib_sqlite::ConnectionPool;
use parking_lot::RwLock;
use std::sync::Arc;
pub trait GridUser: Send + Sync {
@ -15,27 +22,63 @@ pub struct GridManager {
grid_editors: Arc<GridEditors>,
grid_user: Arc<dyn GridUser>,
rev_web_socket: Arc<dyn RevisionWebSocket>,
kv_persistence: Arc<RwLock<Option<Arc<GridKVPersistence>>>>,
}
impl GridManager {
pub fn new(grid_user: Arc<dyn GridUser>, rev_web_socket: Arc<dyn RevisionWebSocket>) -> Self {
let grid_editors = Arc::new(GridEditors::new());
// kv_persistence will be initialized after first access.
// See get_kv_persistence function below
let kv_persistence = Arc::new(RwLock::new(None));
Self {
grid_editors,
grid_user,
rev_web_socket,
kv_persistence,
}
}
#[tracing::instrument(level = "debug", skip(self, grid_id), fields(grid_id), err)]
pub async fn open_grid<T: AsRef<str>>(&self, grid_id: T) -> Result<Arc<ClientGridEditor>, FlowyError> {
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn create_grid<T: AsRef<str>>(
&self,
grid_id: T,
fields: Option<Vec<Field>>,
rows: Option<Vec<RawRow>>,
) -> FlowyResult<()> {
let grid_id = grid_id.as_ref();
tracing::Span::current().record("grid_id", &grid_id);
self.get_grid_editor(grid_id).await
let user_id = self.grid_user.user_id()?;
let mut field_orders = vec![];
let mut row_orders = vec![];
if let Some(fields) = fields {
field_orders = fields.iter().map(|field| FieldOrder::from(field)).collect::<Vec<_>>();
}
if let Some(rows) = rows {
row_orders = rows.iter().map(|row| RowOrder::from(row)).collect::<Vec<_>>();
}
let grid = Grid {
id: grid_id.to_owned(),
field_orders: field_orders.into(),
row_orders: row_orders.into(),
};
let revisions = make_grid_revisions(&user_id, &grid);
let db_pool = self.grid_user.db_pool()?;
let rev_manager = self.make_grid_rev_manager(grid_id, db_pool)?;
let _ = rev_manager.reset_object(revisions).await?;
Ok(())
}
#[tracing::instrument(level = "trace", skip(self, grid_id), fields(grid_id), err)]
pub fn close_grid<T: AsRef<str>>(&self, grid_id: T) -> Result<(), FlowyError> {
#[tracing::instrument(level = "debug", skip_all, fields(grid_id), err)]
pub async fn open_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<Arc<ClientGridEditor>> {
let grid_id = grid_id.as_ref();
tracing::Span::current().record("grid_id", &grid_id);
self.get_or_create_grid_editor(grid_id).await
}
#[tracing::instrument(level = "trace", skip_all, fields(grid_id), err)]
pub fn close_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<()> {
let grid_id = grid_id.as_ref();
tracing::Span::current().record("grid_id", &grid_id);
self.grid_editors.remove(grid_id);
@ -43,14 +86,29 @@ impl GridManager {
}
#[tracing::instrument(level = "debug", skip(self, grid_id), fields(doc_id), err)]
pub fn delete_grid<T: AsRef<str>>(&self, grid_id: T) -> Result<(), FlowyError> {
pub fn delete_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<()> {
let grid_id = grid_id.as_ref();
tracing::Span::current().record("grid_id", &grid_id);
self.grid_editors.remove(grid_id);
Ok(())
}
async fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<ClientGridEditor>> {
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> RepeatedRow {
todo!()
}
pub async fn get_fields(&self, field_orders: RepeatedFieldOrder) -> RepeatedField {
todo!()
}
pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<ClientGridEditor>> {
match self.grid_editors.get(grid_id) {
None => Err(FlowyError::internal().context("Should call open_grid function first")),
Some(editor) => Ok(editor),
}
}
async fn get_or_create_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<ClientGridEditor>> {
match self.grid_editors.get(grid_id) {
None => {
let db_pool = self.grid_user.db_pool()?;
@ -65,12 +123,33 @@ impl GridManager {
grid_id: &str,
pool: Arc<ConnectionPool>,
) -> Result<Arc<ClientGridEditor>, FlowyError> {
let token = self.grid_user.token()?;
let user_id = self.grid_user.user_id()?;
let grid_editor = ClientGridEditor::new(&user_id, grid_id, &token, pool, self.rev_web_socket.clone()).await?;
let user = self.grid_user.clone();
let rev_manager = self.make_grid_rev_manager(grid_id, pool.clone())?;
let kv_persistence = self.get_kv_persistence()?;
let grid_editor = ClientGridEditor::new(grid_id, user, rev_manager, kv_persistence).await?;
self.grid_editors.insert(grid_id, &grid_editor);
Ok(grid_editor)
}
fn make_grid_rev_manager(&self, grid_id: &str, pool: Arc<ConnectionPool>) -> FlowyResult<RevisionManager> {
let user_id = self.grid_user.user_id()?;
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, grid_id, pool));
let rev_manager = RevisionManager::new(&user_id, grid_id, rev_persistence);
Ok(rev_manager)
}
fn get_kv_persistence(&self) -> FlowyResult<Arc<GridKVPersistence>> {
let read_guard = self.kv_persistence.read();
if read_guard.is_some() {
return Ok(read_guard.clone().unwrap());
}
drop(read_guard);
let pool = self.grid_user.db_pool()?;
let kv_persistence = Arc::new(GridKVPersistence::new(pool));
*self.kv_persistence.write() = Some(kv_persistence.clone());
Ok(kv_persistence)
}
}
pub struct GridEditors {

View File

@ -25,11 +25,10 @@
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum GridEvent {
CreateGrid = 0,
OpenGrid = 1,
GetRows = 2,
GetFields = 3,
CreateRow = 4,
OpenGrid = 0,
GetRows = 1,
GetFields = 2,
CreateRow = 3,
}
impl ::protobuf::ProtobufEnum for GridEvent {
@ -39,18 +38,16 @@ impl ::protobuf::ProtobufEnum for GridEvent {
fn from_i32(value: i32) -> ::std::option::Option<GridEvent> {
match value {
0 => ::std::option::Option::Some(GridEvent::CreateGrid),
1 => ::std::option::Option::Some(GridEvent::OpenGrid),
2 => ::std::option::Option::Some(GridEvent::GetRows),
3 => ::std::option::Option::Some(GridEvent::GetFields),
4 => ::std::option::Option::Some(GridEvent::CreateRow),
0 => ::std::option::Option::Some(GridEvent::OpenGrid),
1 => ::std::option::Option::Some(GridEvent::GetRows),
2 => ::std::option::Option::Some(GridEvent::GetFields),
3 => ::std::option::Option::Some(GridEvent::CreateRow),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [GridEvent] = &[
GridEvent::CreateGrid,
GridEvent::OpenGrid,
GridEvent::GetRows,
GridEvent::GetFields,
@ -72,7 +69,7 @@ impl ::std::marker::Copy for GridEvent {
impl ::std::default::Default for GridEvent {
fn default() -> Self {
GridEvent::CreateGrid
GridEvent::OpenGrid
}
}
@ -83,9 +80,9 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0fevent_map.proto*T\n\tGridEvent\x12\x0e\n\nCreateGrid\x10\0\x12\x0c\
\n\x08OpenGrid\x10\x01\x12\x0b\n\x07GetRows\x10\x02\x12\r\n\tGetFields\
\x10\x03\x12\r\n\tCreateRow\x10\x04b\x06proto3\
\n\x0fevent_map.proto*D\n\tGridEvent\x12\x0c\n\x08OpenGrid\x10\0\x12\x0b\
\n\x07GetRows\x10\x01\x12\r\n\tGetFields\x10\x02\x12\r\n\tCreateRow\x10\
\x03b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,9 +1,8 @@
syntax = "proto3";
enum GridEvent {
CreateGrid = 0;
OpenGrid = 1;
GetRows = 2;
GetFields = 3;
CreateRow = 4;
OpenGrid = 0;
GetRows = 1;
GetFields = 2;
CreateRow = 3;
}

View File

@ -1,60 +1,64 @@
use crate::manager::GridUser;
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
use flowy_collaboration::client_grid::{GridChange, GridPad};
use flowy_collaboration::entities::revision::Revision;
use flowy_collaboration::util::make_delta_from_revisions;
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{Field, GridId, RawRow};
use flowy_grid_data_model::entities::{Field, Grid, GridId, RawRow};
use flowy_sync::{
RevisionCloudService, RevisionCompact, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
RevisionWebSocket, RevisionWebSocketManager,
};
use lib_infra::future::FutureResult;
use lib_infra::uuid;
use lib_ot::core::PlainTextAttributes;
use lib_sqlite::ConnectionPool;
use parking_lot::RwLock;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct ClientGridEditor {
user_id: String,
grid_id: String,
grid: Arc<RwLock<GridPad>>,
user: Arc<dyn GridUser>,
grid_pad: Arc<RwLock<GridPad>>,
rev_manager: Arc<RevisionManager>,
kv: Arc<GridKVPersistence>,
kv_persistence: Arc<GridKVPersistence>,
}
impl ClientGridEditor {
pub async fn new(
user_id: &str,
grid_id: &str,
token: &str,
pool: Arc<ConnectionPool>,
_web_socket: Arc<dyn RevisionWebSocket>,
user: Arc<dyn GridUser>,
mut rev_manager: RevisionManager,
kv_persistence: Arc<GridKVPersistence>,
) -> FlowyResult<Arc<Self>> {
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, grid_id, pool.clone()));
let mut rev_manager = RevisionManager::new(user_id, grid_id, rev_persistence);
let cloud = Arc::new(GridRevisionCloudService {
token: token.to_string(),
});
let grid = Arc::new(RwLock::new(
let token = user.token()?;
let cloud = Arc::new(GridRevisionCloudService { token });
let grid_pad = Arc::new(RwLock::new(
rev_manager.load::<GridPadBuilder, GridRevisionCompact>(cloud).await?,
));
let rev_manager = Arc::new(rev_manager);
let kv = Arc::new(GridKVPersistence::new(pool));
let user_id = user_id.to_owned();
let grid_id = grid_id.to_owned();
Ok(Arc::new(Self {
user_id,
grid_id,
grid,
grid_id: grid_id.to_owned(),
user,
grid_pad,
rev_manager,
kv,
kv_persistence,
}))
}
pub async fn create_row(&self, row: RawRow) -> FlowyResult<()> {
pub async fn create_empty_row(&self) -> FlowyResult<()> {
let row = RawRow {
id: uuid(),
grid_id: self.grid_id.clone(),
cell_by_field_id: Default::default(),
};
self.create_row(row).await?;
Ok(())
}
async fn create_row(&self, row: RawRow) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.create_row(&row)?)).await?;
let _ = self.kv.set(row)?;
let _ = self.kv_persistence.set(row)?;
Ok(())
}
@ -66,7 +70,7 @@ impl ClientGridEditor {
pub async fn create_field(&mut self, field: Field) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.create_field(&field)?)).await?;
let _ = self.kv.set(field)?;
let _ = self.kv_persistence.set(field)?;
Ok(())
}
@ -76,11 +80,15 @@ impl ClientGridEditor {
Ok(())
}
pub async fn grid_data(&self) -> Grid {
self.grid_pad.read().await.grid_data()
}
async fn modify<F>(&self, f: F) -> FlowyResult<()>
where
F: FnOnce(&mut GridPad) -> FlowyResult<Option<GridChange>>,
F: for<'a> FnOnce(&'a mut GridPad) -> FlowyResult<Option<GridChange>>,
{
let mut write_guard = self.grid.write();
let mut write_guard = self.grid_pad.write().await;
match f(&mut *write_guard)? {
None => {}
Some(change) => {
@ -92,6 +100,7 @@ impl ClientGridEditor {
async fn apply_change(&self, change: GridChange) -> FlowyResult<()> {
let GridChange { delta, md5 } = change;
let user_id = self.user.user_id()?;
let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair();
let delta_data = delta.to_bytes();
let revision = Revision::new(
@ -99,7 +108,7 @@ impl ClientGridEditor {
base_rev_id,
rev_id,
delta_data,
&self.user_id,
&user_id,
md5,
);
let _ = self
@ -114,8 +123,8 @@ struct GridPadBuilder();
impl RevisionObjectBuilder for GridPadBuilder {
type Output = GridPad;
fn build_object(_object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output> {
let pad = GridPad::from_revisions(revisions)?;
fn build_object(object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output> {
let pad = GridPad::from_revisions(object_id, revisions)?;
Ok(pad)
}
}

View File

@ -3,6 +3,6 @@ mod util;
pub mod cell_data;
pub mod grid_editor;
mod kv_persistence;
pub mod kv_persistence;
pub use stringify::*;

View File

@ -2,7 +2,7 @@ use crate::local_server::persistence::LocalDocumentCloudPersistence;
use async_stream::stream;
use bytes::Bytes;
use flowy_collaboration::{
client_document::default::initial_delta_string,
client_document::default::initial_quill_delta_string,
entities::{
document_info::{BlockId, BlockInfo, CreateBlockParams, ResetBlockParams},
ws_data::{ClientRevisionWSData, ClientRevisionWSDataType},
@ -420,7 +420,7 @@ impl BlockCloudService for LocalServer {
fn read_block(&self, _token: &str, params: BlockId) -> FutureResult<Option<BlockInfo>, FlowyError> {
let doc = BlockInfo {
block_id: params.value,
text: initial_delta_string(),
text: initial_quill_delta_string(),
rev_id: 0,
base_rev_id: 0,
};