From 3a27413dfcbfe6c92503ca939321218f03037654 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 17 Aug 2022 16:48:16 +0800 Subject: [PATCH 01/10] fix: row is not added into group when create a new row --- .../flowy-grid/src/entities/block_entities.rs | 10 +++ .../flowy-grid/src/services/block_editor.rs | 2 +- .../flowy-grid/src/services/block_manager.rs | 16 ++-- .../flowy-grid/src/services/grid_editor.rs | 8 +- .../src/services/grid_view_editor.rs | 51 +++++------- .../src/services/grid_view_manager.rs | 20 ++--- .../group/group_generator/checkbox_group.rs | 24 +++++- .../{generator.rs => group_controller.rs} | 34 +++++++- .../src/services/group/group_generator/mod.rs | 4 +- .../group_generator/select_option_group.rs | 81 ++++++++++++++++--- .../src/services/group/group_service.rs | 29 ++++++- 11 files changed, 207 insertions(+), 72 deletions(-) rename frontend/rust-lib/flowy-grid/src/services/group/group_generator/{generator.rs => group_controller.rs} (87%) diff --git a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs index 05750e7283..bb7eec9032 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs @@ -62,6 +62,16 @@ impl std::convert::From<&RowRevision> for RowPB { } } +impl std::convert::From<&mut RowRevision> for RowPB { + fn from(rev: &mut RowRevision) -> Self { + Self { + block_id: rev.block_id.clone(), + id: rev.id.clone(), + height: rev.height, + } + } +} + impl std::convert::From<&Arc> for RowPB { fn from(rev: &Arc) -> Self { Self { diff --git a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs index 64fcc87072..275ddef9fa 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs @@ -127,7 +127,7 @@ impl GridBlockRevisionEditor { Ok(cell_revs) } - pub async fn get_row_info(&self, row_id: &str) -> FlowyResult> { + pub async fn get_row_pb(&self, row_id: &str) -> FlowyResult> { let row_ids = Some(vec![Cow::Borrowed(row_id)]); Ok(self.get_row_infos(row_ids).await?.pop()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index 253ce65e8b..91348c76b5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -123,21 +123,23 @@ impl GridBlockManager { } #[tracing::instrument(level = "trace", skip_all, err)] - pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> { + pub async fn delete_row(&self, row_id: &str) -> FlowyResult>> { let row_id = row_id.to_owned(); let block_id = self.persistence.get_block_id(&row_id)?; let editor = self.get_block_editor(&block_id).await?; - match editor.get_row_info(&row_id).await? { - None => {} - Some(row_info) => { + match editor.get_row_rev(&row_id).await? { + None => Ok(None), + Some(row_rev) => { let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?; let _ = self - .notify_did_update_block(&block_id, GridBlockChangesetPB::delete(&block_id, vec![row_info.id])) + .notify_did_update_block( + &block_id, + GridBlockChangesetPB::delete(&block_id, vec![row_rev.id.clone()]), + ) .await?; + Ok(Some(row_rev)) } } - - Ok(()) } pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 7c1d706e33..2b0e83bada 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -289,7 +289,7 @@ impl GridRevisionEditor { pub async fn create_row(&self, params: CreateRowParams) -> FlowyResult { let mut row_rev = self.create_row_rev().await?; - self.view_manager.fill_row(&mut row_rev, ¶ms).await; + self.view_manager.will_create_row(&mut row_rev, ¶ms).await; let row_pb = self.create_row_pb(row_rev, params.start_row_id.clone()).await?; @@ -346,8 +346,10 @@ impl GridRevisionEditor { } pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> { - let _ = self.block_manager.delete_row(row_id).await?; - self.view_manager.did_delete_row(row_id).await; + let row_rev = self.block_manager.delete_row(row_id).await?; + if let Some(row_rev) = row_rev { + self.view_manager.did_delete_row(row_rev).await; + } Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 212febacf0..c396e79239 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -59,23 +59,18 @@ impl GridViewRevisionEditor { }) } - pub(crate) async fn fill_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { - match params.layout { - GridLayout::Table => { - // Table can be grouped too + pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { + match params.group_id.as_ref() { + None => {} + Some(group_id) => { + self.group_service + .read() + .await + .will_create_row(row_rev, group_id, |field_id| { + self.field_delegate.get_field_rev(&field_id) + }) + .await; } - GridLayout::Board => match params.group_id.as_ref() { - None => {} - Some(group_id) => { - self.group_service - .read() - .await - .fill_row(row_rev, group_id, |field_id| { - self.field_delegate.get_field_rev(&field_id) - }) - .await; - } - }, } } @@ -94,12 +89,16 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn did_delete_row(&self, row_id: &str) { + pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) { // Send the group notification if the current view has groups; - match self.group_id_of_row(row_id).await { - None => {} - Some(group_id) => { - let changeset = GroupRowsChangesetPB::delete(group_id, vec![row_id.to_owned()]); + if let Some(changesets) = self + .group_service + .write() + .await + .did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) + .await + { + for changeset in changesets { self.notify_did_update_group(changeset).await; } } @@ -119,16 +118,6 @@ impl GridViewRevisionEditor { } } - async fn group_id_of_row(&self, row_id: &str) -> Option { - let read_guard = &self.group_service.read().await.groups; - for group in read_guard.iter() { - if group.contains_row(row_id) { - return Some(group.id.clone()); - } - } - None - } - // async fn get_mut_group(&self, group_id: &str, f: F) -> FlowyResult<()> // where // F: Fn(&mut Group) -> FlowyResult<()>, diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index c2e13c1089..ceb02672b8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -66,9 +66,15 @@ impl GridViewManager { }) } - pub(crate) async fn fill_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { + pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { for view_editor in self.view_editors.iter() { - view_editor.fill_row(row_rev, params).await; + view_editor.will_create_row(row_rev, params).await; + } + } + + pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) { + for view_editor in self.view_editors.iter() { + view_editor.did_create_row(row_pb, params).await; } } @@ -85,15 +91,9 @@ impl GridViewManager { } } - pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) { + pub(crate) async fn did_delete_row(&self, row_rev: Arc) { for view_editor in self.view_editors.iter() { - view_editor.did_create_row(row_pb, params).await; - } - } - - pub(crate) async fn did_delete_row(&self, row_id: &str) { - for view_editor in self.view_editors.iter() { - view_editor.did_delete_row(row_id).await; + view_editor.did_delete_row(&row_rev).await; } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index 020a97e847..03fe4fe1c8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -19,13 +19,33 @@ impl Groupable for CheckboxGroupController { false } - fn group_row(&mut self, _row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec { + fn add_row_if_match( + &mut self, + _row_rev: &RowRevision, + _cell_data: &Self::CellDataType, + ) -> Vec { + todo!() + } + + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + todo!() + } + + fn move_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { todo!() } } impl GroupController for CheckboxGroupController { - fn fill_row(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) { + fn will_create_row(&mut self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) { todo!() } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs similarity index 87% rename from frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs rename to frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index becef0d784..851714a52a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -22,11 +22,19 @@ pub trait GroupGenerator { pub trait Groupable: Send + Sync { type CellDataType; fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; - fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec; + + fn move_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) + -> Vec; } pub trait GroupController: GroupControllerSharedAction + Send + Sync { - fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); } pub trait GroupControllerSharedAction: Send + Sync { @@ -39,6 +47,12 @@ pub trait GroupControllerSharedAction: Send + Sync { row_rev: &RowRevision, field_rev: &FieldRevision, ) -> FlowyResult>; + + fn did_delete_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + ) -> FlowyResult>; } const DEFAULT_GROUP_ID: &str = "default_group"; @@ -203,7 +217,21 @@ where if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; - Ok(self.group_row(row_rev, &cell_data)) + Ok(self.add_row_if_match(row_rev, &cell_data)) + } else { + Ok(vec![]) + } + } + + fn did_delete_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + ) -> FlowyResult> { + if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); + let cell_data = cell_bytes.parser::

()?; + Ok(self.remove_row_if_match(row_rev, &cell_data)) } else { Ok(vec![]) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs index 2225087fb8..08e691a75e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs @@ -1,7 +1,7 @@ mod checkbox_group; -mod generator; +mod group_controller; mod select_option_group; pub use checkbox_group::*; -pub use generator::*; +pub use group_controller::*; pub use select_option_group::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index ce39e59955..3083980986 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -21,23 +21,44 @@ impl Groupable for SingleSelectGroupController { cell_data.select_options.iter().any(|option| option.id == content) } - fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - group_select_option_row(group, &mut changesets, cell_data, row_rev); + add_row(group, &mut changesets, cell_data, row_rev); }); changesets } + + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + remove_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn move_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + todo!() + } } impl GroupController for SingleSelectGroupController { - fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&Group> = self.groups_map.get(group_id); + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + let group: Option<&mut Group> = self.groups_map.get_mut(group_id); match group { None => {} Some(group) => { let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); row_rev.cells.insert(field_rev.id.clone(), cell_rev); + group.add_row(RowPB::from(row_rev)); } } } @@ -77,18 +98,38 @@ impl Groupable for MultiSelectGroupController { cell_data.select_options.iter().any(|option| option.id == content) } - fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - group_select_option_row(group, &mut changesets, cell_data, row_rev); + add_row(group, &mut changesets, cell_data, row_rev); }); changesets } + + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + remove_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn move_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + todo!() + } } impl GroupController for MultiSelectGroupController { - fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { let group: Option<&Group> = self.groups_map.get(group_id); match group { None => tracing::warn!("Can not find the group: {}", group_id), @@ -120,7 +161,7 @@ impl GroupGenerator for MultiSelectGroupGenerator { } } -fn group_select_option_row( +fn add_row( group: &mut Group, changesets: &mut Vec, cell_data: &SelectOptionCellDataPB, @@ -136,9 +177,27 @@ fn group_select_option_row( )); group.add_row(row_pb); } - } else if group.contains_row(&row_rev.id) { - group.remove_row(&row_rev.id); - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + } + + // else if group.contains_row(&row_rev.id) { + // group.remove_row(&row_rev.id); + // changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + // } + }); +} + +fn remove_row( + group: &mut Group, + changesets: &mut Vec, + cell_data: &SelectOptionCellDataPB, + row_rev: &RowRevision, +) { + cell_data.select_options.iter().for_each(|option| { + if option.id == group.id { + if group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } } }); } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index d2e713cf9d..0bca6d8730 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -52,7 +52,7 @@ impl GroupService { } } - pub(crate) async fn fill_row(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) + pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) where F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, @@ -62,12 +62,37 @@ impl GroupService { match get_field_fn(field_id).await { None => {} Some(field_rev) => { - group_controller.write().await.fill_row(row_rev, &field_rev, group_id); + group_controller + .write() + .await + .will_create_row(row_rev, &field_rev, group_id); } } } } + pub(crate) async fn did_delete_row( + &self, + row_rev: &RowRevision, + get_field_fn: F, + ) -> Option> + where + F: FnOnce(String) -> O, + O: Future>> + Send + Sync + 'static, + { + let group_controller = self.group_controller.as_ref()?; + let field_id = group_controller.read().await.field_id().to_owned(); + let field_rev = get_field_fn(field_id).await?; + + match group_controller.write().await.did_delete_row(row_rev, &field_rev) { + Ok(changesets) => Some(changesets), + Err(e) => { + tracing::error!("Update group data failed, {:?}", e); + None + } + } + } + #[tracing::instrument(level = "trace", skip_all)] pub(crate) async fn did_update_row( &self, From f32068d64b7ca57674238f7ded17eef4181c754b Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 17 Aug 2022 19:29:14 +0800 Subject: [PATCH 02/10] refactor: move row params --- .../plugins/board/application/board_bloc.dart | 15 ++++-- .../board/application/group_controller.dart | 34 ++++++++++++-- .../grid/application/row/row_service.dart | 29 ++++++++++++ .../flowy-grid/src/entities/grid_entities.rs | 38 +++++++-------- .../group_entities/group_changeset.rs | 9 ++++ .../src/services/block_manager_trait_impl.rs | 9 +--- .../flowy-grid/src/services/grid_editor.rs | 38 ++++++++++++++- .../src/services/grid_view_editor.rs | 27 ++++++----- .../src/services/grid_view_manager.rs | 41 ++-------------- .../group/group_generator/checkbox_group.rs | 1 + .../group/group_generator/group_controller.rs | 42 ++++++++++++++++- .../group_generator/select_option_group.rs | 47 +++++++++++++++---- .../src/services/group/group_service.rs | 29 +++++++++++- .../src/client_grid/block_revision_pad.rs | 8 +++- 14 files changed, 268 insertions(+), 99 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index c837e4346f..e7668ffcc0 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -21,7 +21,7 @@ part 'board_bloc.freezed.dart'; class BoardBloc extends Bloc { final BoardDataController _dataController; late final AFBoardDataController afBoardDataController; - List groupControllers = []; + Map groupControllers = {}; GridFieldCache get fieldCache => _dataController.fieldCache; String get gridId => _dataController.gridId; @@ -38,13 +38,17 @@ class BoardBloc extends Bloc { columnId, fromIndex, toIndex, - ) {}, + ) { + groupControllers[columnId]?.moveRow(fromIndex, toIndex); + }, onMoveColumnItemToColumn: ( fromColumnId, fromIndex, toColumnId, toIndex, - ) {}, + ) { + // + }, ); on( @@ -84,7 +88,7 @@ class BoardBloc extends Bloc { @override Future close() async { await _dataController.dispose(); - for (final controller in groupControllers) { + for (final controller in groupControllers.values) { controller.dispose(); } return super.close(); @@ -94,11 +98,12 @@ class BoardBloc extends Bloc { for (final group in groups) { final delegate = GroupControllerDelegateImpl(afBoardDataController); final controller = GroupController( + gridId: state.gridId, group: group, delegate: delegate, ); controller.startListening(); - groupControllers.add(controller); + groupControllers[controller.group.groupId] = (controller); } } diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart index a0cd5c3ced..62d2130194 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart @@ -1,8 +1,12 @@ +import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'group_listener.dart'; +typedef OnGroupError = void Function(FlowyError); + abstract class GroupControllerDelegate { void removeRow(String groupId, String rowId); void insertRow(String groupId, RowPB row, int? index); @@ -12,12 +16,36 @@ abstract class GroupControllerDelegate { class GroupController { final GroupPB group; final GroupListener _listener; + final MoveRowFFIService _rowService; final GroupControllerDelegate delegate; + OnGroupError? _onError; - GroupController({required this.group, required this.delegate}) - : _listener = GroupListener(group); + GroupController({ + required String gridId, + required this.group, + required this.delegate, + }) : _rowService = MoveRowFFIService(gridId: gridId), + _listener = GroupListener(group); - void startListening() { + Future moveRow(int fromIndex, int toIndex) async { + if (fromIndex < group.rows.length && toIndex < group.rows.length) { + final fromRow = group.rows[fromIndex]; + final toRow = group.rows[toIndex]; + + final result = await _rowService.moveRow( + rowId: fromRow.id, + fromIndex: fromIndex, + toIndex: toIndex, + upperRowId: toRow.id, + layout: GridLayout.Board, + ); + + result.fold((l) => null, (r) => _onError?.call(r)); + } + } + + void startListening({OnGroupError? onError}) { + _onError = onError; _listener.start(onGroupChanged: (result) { result.fold( (GroupRowsChangesetPB changeset) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart index 52af18b296..594bd230f9 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart @@ -71,3 +71,32 @@ class RowFFIService { return GridEventDuplicateRow(payload).send(); } } + +class MoveRowFFIService { + final String gridId; + + MoveRowFFIService({ + required this.gridId, + }); + + Future> moveRow({ + required String rowId, + required int fromIndex, + required int toIndex, + required GridLayout layout, + String? upperRowId, + }) { + var payload = MoveRowPayloadPB.create() + ..viewId = gridId + ..rowId = rowId + ..layout = layout + ..fromIndex = fromIndex + ..toIndex = toIndex; + + if (upperRowId != null) { + payload.upperRowId = upperRowId; + } + + return GridEventMoveRow(payload).send(); + } +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs index f4200d81cf..b185f6702b 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs @@ -96,28 +96,27 @@ pub struct MoveRowPayloadPB { pub view_id: String, #[pb(index = 2)] - pub row_id: String, - - #[pb(index = 3)] - pub from_index: i32, - - #[pb(index = 4)] - pub to_index: i32, + pub from_row_id: String, + // #[pb(index = 3)] + // pub from_index: i32, + // + // #[pb(index = 4)] + // pub to_index: i32, #[pb(index = 5)] pub layout: GridLayout, - #[pb(index = 6, one_of)] - pub upper_row_id: Option, + #[pb(index = 6)] + pub to_row_id: String, } pub struct MoveRowParams { pub view_id: String, - pub row_id: String, - pub from_index: i32, - pub to_index: i32, + pub from_row_id: String, + // pub from_index: i32, + // pub to_index: i32, pub layout: GridLayout, - pub upper_row_id: Option, + pub to_row_id: String, } impl TryInto for MoveRowPayloadPB { @@ -125,18 +124,19 @@ impl TryInto for MoveRowPayloadPB { fn try_into(self) -> Result { let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::GridViewIdIsEmpty)?; - let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - let upper_row_id = match self.upper_row_id { + let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + let to_row_id = NotEmptyStr::parse(self.to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + let upper_row_id = match self.to_row_id { None => None, Some(upper_row_id) => Some(NotEmptyStr::parse(upper_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0), }; Ok(MoveRowParams { view_id: view_id.0, - row_id: row_id.0, - from_index: self.from_index, - to_index: self.to_index, + from_row_id: from_row_id.0, + // from_index: self.from_index, + // to_index: self.to_index, layout: self.layout, - upper_row_id, + to_row_id: upper_row_id, }) } } diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index f4602b9a50..96bb832323 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -1,5 +1,6 @@ use crate::entities::{InsertedRowPB, RowPB}; use flowy_derive::ProtoBuf; +use std::fmt::Formatter; #[derive(Debug, Default, ProtoBuf)] pub struct GroupRowsChangesetPB { @@ -16,6 +17,14 @@ pub struct GroupRowsChangesetPB { pub updated_rows: Vec, } +impl std::fmt::Display for GroupRowsChangesetPB { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let _ = f.write_fmt(format_args!("Group:{}", self.group_id))?; + let _ = f.write_fmt(format_args!("Insert:{:?}", self.inserted_rows))?; + f.write_fmt(format_args!("Delete:{:?}", self.deleted_rows)) + } +} + impl GroupRowsChangesetPB { pub fn is_empty(&self) -> bool { self.inserted_rows.is_empty() && self.deleted_rows.is_empty() && self.updated_rows.is_empty() diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs index 2696ef0b2c..1bb42310ff 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs @@ -1,5 +1,5 @@ use crate::services::block_manager::GridBlockManager; -use crate::services::grid_view_manager::{GridViewRowDelegate, GridViewRowOperation}; +use crate::services::grid_view_manager::GridViewRowDelegate; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::RowRevision; use lib_infra::future::{wrap_future, AFFuture}; @@ -36,10 +36,3 @@ impl GridViewRowDelegate for Arc { }) } } - -impl GridViewRowOperation for Arc { - fn gv_move_row(&self, row_rev: Arc, from: usize, to: usize) -> AFFuture> { - let block_manager = self.clone(); - wrap_future(async move { block_manager.move_row(row_rev, from, to).await }) - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 2b0e83bada..1f16f95475 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -72,7 +72,6 @@ impl GridRevisionEditor { user.clone(), Arc::new(grid_pad.clone()), Arc::new(block_manager.clone()), - Arc::new(block_manager.clone()), Arc::new(task_scheduler.clone()), ) .await?, @@ -494,7 +493,42 @@ impl GridRevisionEditor { } pub async fn move_row(&self, params: MoveRowParams) -> FlowyResult<()> { - self.view_manager.move_row(params).await + let MoveRowParams { + view_id: _, + from_row_id: row_id, + from_index, + to_index, + layout: _, + to_row_id: upper_row_id, + } = params; + + let from_index = from_index as usize; + let to_index = to_index as usize; + + match self.block_manager.get_row_rev(&row_id).await? { + None => tracing::warn!("Move row failed, can not find the row:{}", row_id), + Some(row_rev) => match upper_row_id { + None => { + tracing::trace!("Move row from {} to {}", from_index, to_index); + let _ = self + .block_manager + .move_row(row_rev.clone(), from_index, to_index) + .await?; + } + Some(to_row_id) => match self.block_manager.index_of_row(&to_row_id).await { + None => tracing::error!("Can not find the row: {} when moving the row", to_row_id), + Some(to_row_index) => { + tracing::trace!("Move row from {} to {}", from_index, to_row_index); + let _ = self + .block_manager + .move_row(row_rev.clone(), from_index, to_row_index) + .await?; + self.view_manager.move_row(row_rev, to_row_id).await; + } + }, + }, + } + Ok(()) } pub async fn move_field(&self, params: MoveFieldParams) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index c396e79239..c8f2babf9f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -118,17 +118,22 @@ impl GridViewRevisionEditor { } } - // async fn get_mut_group(&self, group_id: &str, f: F) -> FlowyResult<()> - // where - // F: Fn(&mut Group) -> FlowyResult<()>, - // { - // for group in self.groups.write().await.iter_mut() { - // if group.id == group_id { - // let _ = f(group)?; - // } - // } - // Ok(()) - // } + pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, upper_row_id: &str) { + if let Some(changesets) = self + .group_service + .write() + .await + .did_move_row(row_rev, upper_row_id, |field_id| { + self.field_delegate.get_field_rev(&field_id) + }) + .await + { + for changeset in changesets { + tracing::trace!("Group changeset: {}", changeset); + self.notify_did_update_group(changeset).await; + } + } + } pub(crate) async fn load_groups(&self) -> FlowyResult> { let field_revs = self.field_delegate.get_field_revs().await; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index ceb02672b8..4c320d527a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -31,17 +31,11 @@ pub trait GridViewRowDelegate: Send + Sync + 'static { fn gv_row_revs(&self) -> AFFuture>>; } -pub trait GridViewRowOperation: Send + Sync + 'static { - // Will be removed in the future. - fn gv_move_row(&self, row_rev: Arc, from: usize, to: usize) -> AFFuture>; -} - pub(crate) struct GridViewManager { grid_id: String, user: Arc, field_delegate: Arc, row_delegate: Arc, - row_operation: Arc, view_editors: DashMap>, scheduler: Arc, } @@ -52,7 +46,6 @@ impl GridViewManager { user: Arc, field_delegate: Arc, row_delegate: Arc, - row_operation: Arc, scheduler: Arc, ) -> FlowyResult { Ok(Self { @@ -61,7 +54,6 @@ impl GridViewManager { scheduler, field_delegate, row_delegate, - row_operation, view_editors: DashMap::default(), }) } @@ -119,37 +111,10 @@ impl GridViewManager { Ok(RepeatedGridGroupPB { items: groups }) } - pub(crate) async fn move_row(&self, params: MoveRowParams) -> FlowyResult<()> { - let MoveRowParams { - view_id: _, - row_id, - from_index, - to_index, - layout, - upper_row_id, - } = params; - - let from_index = from_index as usize; - - match self.row_delegate.gv_get_row_rev(&row_id).await { - None => tracing::warn!("Move row failed, can not find the row:{}", row_id), - Some(row_rev) => match layout { - GridLayout::Table => { - tracing::trace!("Move row from {} to {}", from_index, to_index); - let to_index = to_index as usize; - let _ = self.row_operation.gv_move_row(row_rev, from_index, to_index).await?; - } - GridLayout::Board => { - if let Some(upper_row_id) = upper_row_id { - if let Some(to_index) = self.row_delegate.gv_index_of_row(&upper_row_id).await { - tracing::trace!("Move row from {} to {}", from_index, to_index); - let _ = self.row_operation.gv_move_row(row_rev, from_index, to_index).await?; - } - } - } - }, + pub(crate) async fn move_row(&self, row_rev: Arc, to_row_id: String) { + for view_editor in self.view_editors.iter() { + view_editor.did_move_row(&row_rev, &to_row_id).await; } - Ok(()) } pub(crate) async fn get_view_editor(&self, view_id: &str) -> FlowyResult> { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index 03fe4fe1c8..ca6fd3a4bd 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -39,6 +39,7 @@ impl Groupable for CheckboxGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, + to_row_id: &str, ) -> Vec { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index 851714a52a..6135aabb7e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -29,8 +29,12 @@ pub trait Groupable: Send + Sync { cell_data: &Self::CellDataType, ) -> Vec; - fn move_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) - -> Vec; + fn move_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + to_row_id: &str, + ) -> Vec; } pub trait GroupController: GroupControllerSharedAction + Send + Sync { @@ -53,6 +57,13 @@ pub trait GroupControllerSharedAction: Send + Sync { row_rev: &RowRevision, field_rev: &FieldRevision, ) -> FlowyResult>; + + fn did_move_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + to_row_id: &str, + ) -> FlowyResult>; } const DEFAULT_GROUP_ID: &str = "default_group"; @@ -120,6 +131,18 @@ impl Group { Some(_) => {} } } + + pub fn insert_row(&mut self, index: usize, row_pb: RowPB) { + if index < self.rows.len() { + self.rows.insert(index, row_pb); + } else { + tracing::error!("Insert row index:{} beyond the bounds:{},", index, self.rows.len()); + } + } + + pub fn index_of_row(&self, row_id: &str) -> Option { + self.rows.iter().position(|row| row.id == row_id) + } } impl GenericGroupController @@ -236,6 +259,21 @@ where Ok(vec![]) } } + + fn did_move_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + to_row_id: &str, + ) -> FlowyResult> { + if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); + let cell_data = cell_bytes.parser::

()?; + Ok(self.move_row_if_match(row_rev, &cell_data, to_row_id)) + } else { + Ok(vec![]) + } + } } // impl GroupController diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 3083980986..efc2d4ff63 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -45,8 +45,13 @@ impl Groupable for SingleSelectGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, + to_row_id: &str, ) -> Vec { - todo!() + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + move_row(group, &mut changesets, cell_data, row_rev, to_row_id); + }); + changesets } } @@ -100,7 +105,6 @@ impl Groupable for MultiSelectGroupController { fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { add_row(group, &mut changesets, cell_data, row_rev); }); @@ -123,8 +127,13 @@ impl Groupable for MultiSelectGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, + to_row_id: &str, ) -> Vec { - todo!() + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + move_row(group, &mut changesets, cell_data, row_rev, to_row_id); + }); + changesets } } @@ -178,11 +187,6 @@ fn add_row( group.add_row(row_pb); } } - - // else if group.contains_row(&row_rev.id) { - // group.remove_row(&row_rev.id); - // changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - // } }); } @@ -201,3 +205,30 @@ fn remove_row( } }); } + +fn move_row( + group: &mut Group, + changesets: &mut Vec, + cell_data: &SelectOptionCellDataPB, + row_rev: &RowRevision, + upper_row_id: &str, +) { + cell_data.select_options.iter().for_each(|option| { + if option.id == group.id { + if group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } + } + + if let Some(index) = group.index_of_row(upper_row_id) { + let row_pb = RowPB::from(row_rev); + let inserted_row = InsertedRowPB { + row: row_pb.clone(), + index: Some(index as i32), + }; + changesets.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); + group.insert_row(index, row_pb); + } + }); +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index 0bca6d8730..e4bf92e22a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -87,7 +87,34 @@ impl GroupService { match group_controller.write().await.did_delete_row(row_rev, &field_rev) { Ok(changesets) => Some(changesets), Err(e) => { - tracing::error!("Update group data failed, {:?}", e); + tracing::error!("Delete group data failed, {:?}", e); + None + } + } + } + + pub(crate) async fn did_move_row( + &self, + row_rev: &RowRevision, + upper_row_id: &str, + get_field_fn: F, + ) -> Option> + where + F: FnOnce(String) -> O, + O: Future>> + Send + Sync + 'static, + { + let group_controller = self.group_controller.as_ref()?; + let field_id = group_controller.read().await.field_id().to_owned(); + let field_rev = get_field_fn(field_id).await?; + + match group_controller + .write() + .await + .did_move_row(row_rev, &field_rev, upper_row_id) + { + Ok(changesets) => Some(changesets), + Err(e) => { + tracing::error!("Move group data failed, {:?}", e); None } } diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index 142463b8fc..5902fda35c 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -178,8 +178,12 @@ impl GridBlockRevisionPad { if let Some(position) = row_revs.iter().position(|row_rev| row_rev.id == row_id) { debug_assert_eq!(from, position); let row_rev = row_revs.remove(position); - row_revs.insert(to, row_rev); - Ok(Some(())) + if to > row_revs.len() { + return Err(CollaborateError::out_of_bound()); + } else { + row_revs.insert(to, row_rev); + Ok(Some(())) + } } else { Ok(None) } From c4514e421a775e3bfa33ac18380dea934a6071da Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 17 Aug 2022 20:15:10 +0800 Subject: [PATCH 03/10] chore: move card from one column to another --- frontend/.vscode/launch.json | 2 +- .../plugins/board/application/board_bloc.dart | 32 ++++++++++++-- .../board/application/group_controller.dart | 28 +++--------- .../grid/application/row/row_service.dart | 39 ++--------------- .../appflowy_board/lib/src/utils/log.dart | 2 +- .../flowy-grid/src/entities/grid_entities.rs | 25 ++--------- .../src/services/block_manager_trait_impl.rs | 2 +- .../flowy-grid/src/services/grid_editor.rs | 43 ++++++++----------- .../src/services/grid_view_editor.rs | 3 +- .../src/services/grid_view_manager.rs | 4 +- .../group/group_generator/checkbox_group.rs | 10 ++--- .../group_generator/select_option_group.rs | 32 ++++++-------- .../src/client_grid/block_revision_pad.rs | 2 +- 13 files changed, 85 insertions(+), 139 deletions(-) diff --git a/frontend/.vscode/launch.json b/frontend/.vscode/launch.json index 0efc79b00e..e70b9ffb97 100644 --- a/frontend/.vscode/launch.json +++ b/frontend/.vscode/launch.json @@ -29,7 +29,7 @@ "program": "./lib/main.dart", "type": "dart", "env": { - "RUST_LOG": "debug" + "RUST_LOG": "trace" }, "cwd": "${workspaceRoot}/app_flowy" }, diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index e7668ffcc0..ac72b6e24e 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; +import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:appflowy_board/appflowy_board.dart'; import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; @@ -21,13 +22,15 @@ part 'board_bloc.freezed.dart'; class BoardBloc extends Bloc { final BoardDataController _dataController; late final AFBoardDataController afBoardDataController; + final MoveRowFFIService _rowService; Map groupControllers = {}; GridFieldCache get fieldCache => _dataController.fieldCache; String get gridId => _dataController.gridId; BoardBloc({required ViewPB view}) - : _dataController = BoardDataController(view: view), + : _rowService = MoveRowFFIService(gridId: view.id), + _dataController = BoardDataController(view: view), super(BoardState.initial(view.id)) { afBoardDataController = AFBoardDataController( onMoveColumn: ( @@ -39,7 +42,9 @@ class BoardBloc extends Bloc { fromIndex, toIndex, ) { - groupControllers[columnId]?.moveRow(fromIndex, toIndex); + final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex); + final toRow = groupControllers[columnId]?.rowAtIndex(toIndex); + _moveRow(fromRow, toRow); }, onMoveColumnItemToColumn: ( fromColumnId, @@ -47,7 +52,9 @@ class BoardBloc extends Bloc { toColumnId, toIndex, ) { - // + final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex); + final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex); + _moveRow(fromRow, toRow); }, ); @@ -80,11 +87,27 @@ class BoardBloc extends Bloc { didReceiveRows: (List rowInfos) { emit(state.copyWith(rowInfos: rowInfos)); }, + didReceiveError: (FlowyError error) { + emit(state.copyWith(noneOrError: some(error))); + }, ); }, ); } + void _moveRow(RowPB? fromRow, RowPB? toRow) { + if (fromRow != null && toRow != null) { + _rowService + .moveRow( + fromRowId: fromRow.id, + toRowId: toRow.id, + ) + .then((result) { + result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r))); + }); + } + } + @override Future close() async { await _dataController.dispose(); @@ -167,6 +190,7 @@ class BoardEvent with _$BoardEvent { const factory BoardEvent.initial() = InitialGrid; const factory BoardEvent.createRow(String groupId) = _CreateRow; const factory BoardEvent.endEditRow(String rowId) = _EndEditRow; + const factory BoardEvent.didReceiveError(FlowyError error) = _DidReceiveError; const factory BoardEvent.didReceiveRows(List rowInfos) = _DidReceiveRows; const factory BoardEvent.didReceiveGridUpdate( @@ -182,6 +206,7 @@ class BoardState with _$BoardState { required Option editingRow, required List rowInfos, required GridLoadingState loadingState, + required Option noneOrError, }) = _BoardState; factory BoardState.initial(String gridId) => BoardState( @@ -189,6 +214,7 @@ class BoardState with _$BoardState { grid: none(), gridId: gridId, editingRow: none(), + noneOrError: none(), loadingState: const _Loading(), ); } diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart index 62d2130194..3f545dae3b 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; @@ -16,36 +15,23 @@ abstract class GroupControllerDelegate { class GroupController { final GroupPB group; final GroupListener _listener; - final MoveRowFFIService _rowService; final GroupControllerDelegate delegate; - OnGroupError? _onError; GroupController({ required String gridId, required this.group, required this.delegate, - }) : _rowService = MoveRowFFIService(gridId: gridId), - _listener = GroupListener(group); + }) : _listener = GroupListener(group); - Future moveRow(int fromIndex, int toIndex) async { - if (fromIndex < group.rows.length && toIndex < group.rows.length) { - final fromRow = group.rows[fromIndex]; - final toRow = group.rows[toIndex]; - - final result = await _rowService.moveRow( - rowId: fromRow.id, - fromIndex: fromIndex, - toIndex: toIndex, - upperRowId: toRow.id, - layout: GridLayout.Board, - ); - - result.fold((l) => null, (r) => _onError?.call(r)); + RowPB? rowAtIndex(int index) { + if (index < group.rows.length) { + return group.rows[index]; + } else { + return null; } } - void startListening({OnGroupError? onError}) { - _onError = onError; + void startListening() { _listener.start(onGroupChanged: (result) { result.fold( (GroupRowsChangesetPB changeset) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart index 594bd230f9..a18c0c8e75 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart @@ -4,7 +4,6 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; class RowFFIService { final String gridId; @@ -23,27 +22,6 @@ class RowFFIService { return GridEventCreateTableRow(payload).send(); } - Future> moveRow({ - required String rowId, - required int fromIndex, - required int toIndex, - required GridLayout layout, - String? upperRowId, - }) { - var payload = MoveRowPayloadPB.create() - ..viewId = gridId - ..rowId = rowId - ..layout = layout - ..fromIndex = fromIndex - ..toIndex = toIndex; - - if (upperRowId != null) { - payload.upperRowId = upperRowId; - } - - return GridEventMoveRow(payload).send(); - } - Future> getRow(String rowId) { final payload = RowIdPB.create() ..gridId = gridId @@ -80,22 +58,13 @@ class MoveRowFFIService { }); Future> moveRow({ - required String rowId, - required int fromIndex, - required int toIndex, - required GridLayout layout, - String? upperRowId, + required String fromRowId, + required String toRowId, }) { var payload = MoveRowPayloadPB.create() ..viewId = gridId - ..rowId = rowId - ..layout = layout - ..fromIndex = fromIndex - ..toIndex = toIndex; - - if (upperRowId != null) { - payload.upperRowId = upperRowId; - } + ..fromRowId = fromRowId + ..toRowId = toRowId; return GridEventMoveRow(payload).send(); } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart index d11b5fd263..20f810a966 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart @@ -6,7 +6,7 @@ const DART_LOG = "Dart_LOG"; class Log { // static const enableLog = bool.hasEnvironment(DART_LOG); // static final shared = Log(); - static const enableLog = true; + static const enableLog = false; static void info(String? message) { if (enableLog) { diff --git a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs index b185f6702b..be8cfdeae1 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs @@ -1,4 +1,4 @@ -use crate::entities::{BlockPB, FieldIdPB, GridLayout}; +use crate::entities::{BlockPB, FieldIdPB}; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -98,24 +98,13 @@ pub struct MoveRowPayloadPB { #[pb(index = 2)] pub from_row_id: String, - // #[pb(index = 3)] - // pub from_index: i32, - // - // #[pb(index = 4)] - // pub to_index: i32, - #[pb(index = 5)] - pub layout: GridLayout, - - #[pb(index = 6)] + #[pb(index = 4)] pub to_row_id: String, } pub struct MoveRowParams { pub view_id: String, pub from_row_id: String, - // pub from_index: i32, - // pub to_index: i32, - pub layout: GridLayout, pub to_row_id: String, } @@ -126,17 +115,11 @@ impl TryInto for MoveRowPayloadPB { let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::GridViewIdIsEmpty)?; let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; let to_row_id = NotEmptyStr::parse(self.to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - let upper_row_id = match self.to_row_id { - None => None, - Some(upper_row_id) => Some(NotEmptyStr::parse(upper_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0), - }; + Ok(MoveRowParams { view_id: view_id.0, from_row_id: from_row_id.0, - // from_index: self.from_index, - // to_index: self.to_index, - layout: self.layout, - to_row_id: upper_row_id, + to_row_id: to_row_id.0, }) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs index 1bb42310ff..3adea9a853 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs @@ -1,6 +1,6 @@ use crate::services::block_manager::GridBlockManager; use crate::services::grid_view_manager::GridViewRowDelegate; -use flowy_error::FlowyResult; + use flowy_grid_data_model::revision::RowRevision; use lib_infra::future::{wrap_future, AFFuture}; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 1f16f95475..d099b5b269 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -495,38 +495,29 @@ impl GridRevisionEditor { pub async fn move_row(&self, params: MoveRowParams) -> FlowyResult<()> { let MoveRowParams { view_id: _, - from_row_id: row_id, - from_index, - to_index, - layout: _, - to_row_id: upper_row_id, + from_row_id, + to_row_id, } = params; - let from_index = from_index as usize; - let to_index = to_index as usize; - - match self.block_manager.get_row_rev(&row_id).await? { - None => tracing::warn!("Move row failed, can not find the row:{}", row_id), - Some(row_rev) => match upper_row_id { - None => { - tracing::trace!("Move row from {} to {}", from_index, to_index); - let _ = self - .block_manager - .move_row(row_rev.clone(), from_index, to_index) - .await?; - } - Some(to_row_id) => match self.block_manager.index_of_row(&to_row_id).await { - None => tracing::error!("Can not find the row: {} when moving the row", to_row_id), - Some(to_row_index) => { - tracing::trace!("Move row from {} to {}", from_index, to_row_index); + match self.block_manager.get_row_rev(&from_row_id).await? { + None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id), + Some(row_rev) => { + match ( + self.block_manager.index_of_row(&from_row_id).await, + self.block_manager.index_of_row(&to_row_id).await, + ) { + (Some(from_index), Some(to_index)) => { + tracing::trace!("Move row from {} to {}", from_index, to_index); let _ = self .block_manager - .move_row(row_rev.clone(), from_index, to_row_index) + .move_row(row_rev.clone(), from_index, to_index) .await?; - self.view_manager.move_row(row_rev, to_row_id).await; + self.view_manager.move_row(row_rev, to_row_id.clone()).await; } - }, - }, + (_, None) => tracing::error!("Can not find the from row id: {}", from_row_id), + (None, _) => tracing::error!("Can not find the to row id: {}", to_row_id), + } + } } Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index c8f2babf9f..5b4af736a3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -1,7 +1,6 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB, - RowPB, + CreateRowParams, GridFilterConfiguration, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB, RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 4c320d527a..a71ac5722c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -1,8 +1,7 @@ use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, MoveRowParams, RepeatedGridGroupPB, RowPB, + CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB, }; use crate::manager::GridUser; - use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_editor::GridViewRevisionEditor; use bytes::Bytes; @@ -11,7 +10,6 @@ use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use flowy_revision::disk::SQLiteGridViewRevisionPersistence; use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; - use flowy_sync::entities::grid::GridSettingChangesetParams; use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_text_delta_from_revisions; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index ca6fd3a4bd..bfe5552867 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -29,17 +29,17 @@ impl Groupable for CheckboxGroupController { fn remove_row_if_match( &mut self, - row_rev: &RowRevision, - cell_data: &Self::CellDataType, + _row_rev: &RowRevision, + _cell_data: &Self::CellDataType, ) -> Vec { todo!() } fn move_row_if_match( &mut self, - row_rev: &RowRevision, - cell_data: &Self::CellDataType, - to_row_id: &str, + _row_rev: &RowRevision, + _cell_data: &Self::CellDataType, + _to_row_id: &str, ) -> Vec { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index efc2d4ff63..086d87a0d2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -177,15 +177,13 @@ fn add_row( row_rev: &RowRevision, ) { cell_data.select_options.iter().for_each(|option| { - if option.id == group.id { - if !group.contains_row(&row_rev.id) { - let row_pb = RowPB::from(row_rev); - changesets.push(GroupRowsChangesetPB::insert( - group.id.clone(), - vec![InsertedRowPB::new(row_pb.clone())], - )); - group.add_row(row_pb); - } + if option.id == group.id && !group.contains_row(&row_rev.id) { + let row_pb = RowPB::from(row_rev); + changesets.push(GroupRowsChangesetPB::insert( + group.id.clone(), + vec![InsertedRowPB::new(row_pb.clone())], + )); + group.add_row(row_pb); } }); } @@ -197,11 +195,9 @@ fn remove_row( row_rev: &RowRevision, ) { cell_data.select_options.iter().for_each(|option| { - if option.id == group.id { - if group.contains_row(&row_rev.id) { - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } + if option.id == group.id && group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); } }); } @@ -214,11 +210,9 @@ fn move_row( upper_row_id: &str, ) { cell_data.select_options.iter().for_each(|option| { - if option.id == group.id { - if group.contains_row(&row_rev.id) { - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } + if option.id == group.id && group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); } if let Some(index) = group.index_of_row(upper_row_id) { diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index 5902fda35c..8abc1eaace 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -179,7 +179,7 @@ impl GridBlockRevisionPad { debug_assert_eq!(from, position); let row_rev = row_revs.remove(position); if to > row_revs.len() { - return Err(CollaborateError::out_of_bound()); + Err(CollaborateError::out_of_bound()) } else { row_revs.insert(to, row_rev); Ok(Some(())) From 4856a024a2a4f015ab57c02d53eb4d3f7e409d1f Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 15:02:44 +0800 Subject: [PATCH 04/10] chore: Update row when moving row caused cell data changed --- .../presentation/card/board_text_cell.dart | 2 + .../board_column/board_column_data.dart | 31 +++++--- .../flowy-grid/src/entities/cell_entities.rs | 6 +- .../flowy-grid/src/services/block_editor.rs | 4 +- .../flowy-grid/src/services/block_manager.rs | 18 ++--- .../flowy-grid/src/services/grid_editor.rs | 28 ++++---- .../src/services/grid_view_editor.rs | 6 +- .../src/services/grid_view_manager.rs | 23 ++++-- .../group/group_generator/checkbox_group.rs | 19 ++++- .../group/group_generator/group_controller.rs | 59 ++++----------- .../group_generator/select_option_group.rs | 71 +++++++++++++++---- .../src/services/group/group_service.rs | 5 +- .../tests/grid/block_test/row_test.rs | 4 +- .../tests/grid/block_test/script.rs | 4 +- .../src/revision/grid_block.rs | 17 ++++- .../src/client_grid/block_revision_pad.rs | 4 +- 16 files changed, 181 insertions(+), 120 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart index 2da156ded8..5148b2c438 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart @@ -1,8 +1,10 @@ import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; class BoardTextCell extends StatefulWidget { final GridCellControllerBuilder cellControllerBuilder; diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart index 4a04f4b662..6e184761c5 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart @@ -84,20 +84,28 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { Log.debug( '[$AFBoardColumnDataController] $columnData insert $item at $index'); - if (columnData._items.length > index) { - columnData._items.insert(index, item); + if (_containsItem(item)) { + return false; } else { - columnData._items.add(item); - } + if (columnData._items.length > index) { + columnData._items.insert(index, item); + } else { + columnData._items.add(item); + } - if (notify) notifyListeners(); - return true; + if (notify) notifyListeners(); + return true; + } } bool add(AFColumnItem item, {bool notify = true}) { - columnData._items.add(item); - if (notify) notifyListeners(); - return true; + if (_containsItem(item)) { + return false; + } else { + columnData._items.add(item); + if (notify) notifyListeners(); + return true; + } } /// Replace the item at index with the [newItem]. @@ -114,6 +122,11 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { notifyListeners(); } + + bool _containsItem(AFColumnItem item) { + return columnData._items.indexWhere((element) => element.id == item.id) != + -1; + } } /// [AFBoardColumnData] represents the data of each Column of the Board. diff --git a/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs index 1b86eb1e65..f7aa30649c 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs @@ -1,7 +1,7 @@ use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; -use flowy_grid_data_model::revision::{CellRevision, RowMetaChangeset}; +use flowy_grid_data_model::revision::{CellRevision, RowChangeset}; use std::collections::HashMap; #[derive(ProtoBuf, Default)] @@ -135,7 +135,7 @@ pub struct CellChangesetPB { pub content: Option, } -impl std::convert::From for RowMetaChangeset { +impl std::convert::From for RowChangeset { fn from(changeset: CellChangesetPB) -> Self { let mut cell_by_field_id = HashMap::with_capacity(1); let field_id = changeset.field_id; @@ -144,7 +144,7 @@ impl std::convert::From for RowMetaChangeset { }; cell_by_field_id.insert(field_id, cell_rev); - RowMetaChangeset { + RowChangeset { row_id: changeset.row_id, height: None, visibility: None, diff --git a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs index 275ddef9fa..f576742c90 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs @@ -1,7 +1,7 @@ use crate::entities::RowPB; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision}; +use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowChangeset, RowRevision}; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridBlockRevisionChangeset, GridBlockRevisionPad}; use flowy_sync::entities::revision::Revision; @@ -88,7 +88,7 @@ impl GridBlockRevisionEditor { Ok(row_count) } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { + pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> { let _ = self.modify(|block_pad| Ok(block_pad.update_row(changeset)?)).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index 91348c76b5..3d31f99676 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -7,7 +7,7 @@ use crate::services::row::{block_from_row_orders, make_row_from_row_rev, GridBlo use dashmap::DashMap; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision, + GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowChangeset, RowRevision, }; use flowy_revision::disk::SQLiteGridBlockRevisionPersistence; use flowy_revision::{RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; @@ -103,17 +103,15 @@ impl GridBlockManager { Ok(changesets) } - pub async fn update_row(&self, changeset: RowMetaChangeset, row_builder: F) -> FlowyResult<()> - where - F: FnOnce(Arc) -> RowPB, - { + pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; match editor.get_row_rev(&changeset.row_id).await? { None => tracing::error!("Internal error: can't find the row with id: {}", changeset.row_id), Some(row_rev) => { + let row_pb = make_row_from_row_rev(row_rev.clone()); let block_order_changeset = - GridBlockChangesetPB::update(&editor.block_id, vec![row_builder(row_rev.clone())]); + GridBlockChangesetPB::update(&editor.block_id, vec![row_pb]); let _ = self .notify_did_update_block(&editor.block_id, block_order_changeset) .await?; @@ -191,12 +189,10 @@ impl GridBlockManager { } } - pub async fn update_cell(&self, changeset: CellChangesetPB, row_builder: F) -> FlowyResult<()> - where - F: FnOnce(Arc) -> RowPB, + pub async fn update_cell(&self, changeset: CellChangesetPB ) -> FlowyResult<()> { - let row_changeset: RowMetaChangeset = changeset.clone().into(); - let _ = self.update_row(row_changeset, row_builder).await?; + let row_changeset: RowChangeset = changeset.clone().into(); + let _ = self.update_row(row_changeset, ).await?; self.notify_did_update_cell(changeset).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index d099b5b269..e796929ce6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -314,9 +314,9 @@ impl GridRevisionEditor { Ok(row_orders) } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { + pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> { let row_id = changeset.row_id.clone(); - let _ = self.block_manager.update_row(changeset, make_row_from_row_rev).await?; + let _ = self.block_manager.update_row(changeset).await?; self.view_manager.did_update_row(&row_id).await; Ok(()) } @@ -395,12 +395,11 @@ impl GridRevisionEditor { match self.grid_pad.read().await.get_field_rev(&field_id) { None => { - let msg = format!("Field not found with id: {}", &field_id); + let msg = format!("Field:{} not found", &field_id); Err(FlowyError::internal().context(msg)) } Some((_, field_rev)) => { tracing::trace!("field changeset: id:{} / value:{:?}", &field_id, content); - let cell_rev = self.get_cell_rev(&row_id, &field_id).await?; // Update the changeset.data property with the return value. content = Some(apply_cell_data_changeset(content.unwrap(), cell_rev, field_rev)?); @@ -410,11 +409,7 @@ impl GridRevisionEditor { field_id, content, }; - let _ = self - .block_manager - .update_cell(cell_changeset, make_row_from_row_rev) - .await?; - + let _ = self.block_manager.update_cell(cell_changeset).await?; self.view_manager.did_update_row(&row_id).await; Ok(()) } @@ -512,10 +507,19 @@ impl GridRevisionEditor { .block_manager .move_row(row_rev.clone(), from_index, to_index) .await?; - self.view_manager.move_row(row_rev, to_row_id.clone()).await; + + if let Some(row_changeset) = self.view_manager.move_row(row_rev, to_row_id.clone()).await { + tracing::trace!("Receive row changeset after moving the row"); + match self.block_manager.update_row(row_changeset).await { + Ok(_) => {} + Err(e) => { + tracing::error!("Apply row changeset error:{:?}", e); + } + } + } } - (_, None) => tracing::error!("Can not find the from row id: {}", from_row_id), - (None, _) => tracing::error!("Can not find the to row id: {}", to_row_id), + (_, None) => tracing::warn!("Can not find the from row id: {}", from_row_id), + (None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id), } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 5b4af736a3..e972745dfe 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -7,7 +7,7 @@ use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDeleg use crate::services::group::{default_group_configuration, GroupConfigurationDelegate, GroupService}; use crate::services::setting::make_grid_setting; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowRevision}; +use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision}; use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad}; use flowy_sync::entities::grid::GridSettingChangesetParams; @@ -117,12 +117,12 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, upper_row_id: &str) { + pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, upper_row_id: &str) { if let Some(changesets) = self .group_service .write() .await - .did_move_row(row_rev, upper_row_id, |field_id| { + .did_move_row(row_rev, row_changeset, upper_row_id, |field_id| { self.field_delegate.get_field_rev(&field_id) }) .await diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index a71ac5722c..17c5e93569 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -1,13 +1,11 @@ -use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB, -}; +use crate::entities::{CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB}; use crate::manager::GridUser; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_editor::GridViewRevisionEditor; use bytes::Bytes; use dashmap::DashMap; use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; use flowy_revision::disk::SQLiteGridViewRevisionPersistence; use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; use flowy_sync::entities::grid::GridSettingChangesetParams; @@ -56,18 +54,21 @@ impl GridViewManager { }) } + /// When the row was created, we may need to modify the [RowRevision] according to the [CreateRowParams]. pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { for view_editor in self.view_editors.iter() { view_editor.will_create_row(row_rev, params).await; } } + /// Notify the view that the row was created. For the moment, the view is just sending notifications. pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) { for view_editor in self.view_editors.iter() { view_editor.did_create_row(row_pb, params).await; } } + /// Insert/Delete the group's row if the corresponding data was changed. pub(crate) async fn did_update_row(&self, row_id: &str) { match self.row_delegate.gv_get_row_rev(row_id).await { None => { @@ -109,9 +110,19 @@ impl GridViewManager { Ok(RepeatedGridGroupPB { items: groups }) } - pub(crate) async fn move_row(&self, row_rev: Arc, to_row_id: String) { + /// It may generate a RowChangeset when the Row was moved from one group to another. + /// The return value, [RowChangeset], contains the changes made by the groups. + /// + pub(crate) async fn move_row(&self, row_rev: Arc, to_row_id: String) -> Option { + let mut row_changeset = RowChangeset::new(row_rev.id.clone()); for view_editor in self.view_editors.iter() { - view_editor.did_move_row(&row_rev, &to_row_id).await; + view_editor.did_move_row(&row_rev, &mut row_changeset, &to_row_id).await; + } + + if row_changeset.has_changed() { + Some(row_changeset) + } else { + None } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index bfe5552867..c1f4261bb5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -1,6 +1,6 @@ use crate::entities::{CheckboxGroupConfigurationPB, GroupRowsChangesetPB}; -use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable}; @@ -37,7 +37,9 @@ impl Groupable for CheckboxGroupController { fn move_row_if_match( &mut self, + field_rev: &FieldRevision, _row_rev: &RowRevision, + row_changeset: &mut RowChangeset, _cell_data: &Self::CellDataType, _to_row_id: &str, ) -> Vec { @@ -57,11 +59,22 @@ impl GroupGenerator for CheckboxGroupGenerator { type TypeOptionType = CheckboxTypeOptionPB; fn generate_groups( + field_id: &str, _configuration: &Option, _type_option: &Option, ) -> Vec { - let check_group = Group::new("true".to_string(), "".to_string(), CHECK.to_string()); - let uncheck_group = Group::new("false".to_string(), "".to_string(), UNCHECK.to_string()); + let check_group = Group::new( + "true".to_string(), + field_id.to_owned(), + "".to_string(), + CHECK.to_string(), + ); + let uncheck_group = Group::new( + "false".to_string(), + field_id.to_owned(), + "".to_string(), + UNCHECK.to_string(), + ); vec![check_group, uncheck_group] } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index 6135aabb7e..f088bb2176 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -3,7 +3,7 @@ use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use bytes::Bytes; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; use indexmap::IndexMap; use std::marker::PhantomData; @@ -14,6 +14,7 @@ pub trait GroupGenerator { type TypeOptionType; fn generate_groups( + field_id: &str, configuration: &Option, type_option: &Option, ) -> Vec; @@ -31,7 +32,9 @@ pub trait Groupable: Send + Sync { fn move_row_if_match( &mut self, + field_rev: &FieldRevision, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, to_row_id: &str, ) -> Vec; @@ -61,6 +64,7 @@ pub trait GroupControllerSharedAction: Send + Sync { fn did_move_row( &mut self, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, field_rev: &FieldRevision, to_row_id: &str, ) -> FlowyResult>; @@ -85,6 +89,7 @@ pub struct GenericGroupController { #[derive(Clone)] pub struct Group { pub id: String, + pub field_id: String, pub desc: String, rows: Vec, pub content: String, @@ -101,9 +106,10 @@ impl std::convert::From for GroupPB { } impl Group { - pub fn new(id: String, desc: String, content: String) -> Self { + pub fn new(id: String, field_id: String, desc: String, content: String) -> Self { Self { id, + field_id, desc, rows: vec![], content, @@ -158,10 +164,11 @@ where }; let field_type_rev = field_rev.field_type_rev; let type_option = field_rev.get_type_option_entry::(field_type_rev); - let groups = G::generate_groups(&configuration, &type_option); + let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); let default_group = Group::new( DEFAULT_GROUP_ID.to_owned(), + field_rev.id.clone(), format!("No {}", field_rev.name), "".to_string(), ); @@ -263,62 +270,20 @@ where fn did_move_row( &mut self, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, field_rev: &FieldRevision, to_row_id: &str, ) -> FlowyResult> { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; - Ok(self.move_row_if_match(row_rev, &cell_data, to_row_id)) + Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id)) } else { Ok(vec![]) } } } -// impl GroupController -// where -// P: CellBytesParser, -// Self: Groupable, -// { -// pub fn handle_rows(&mut self, rows: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { -// // The field_rev might be None if corresponding field_rev is deleted. -// if self.configuration.is_none() { -// return Ok(()); -// } -// -// for row in rows { -// if let Some(cell_rev) = row.cells.get(&self.field_id) { -// let mut records: Vec = vec![]; -// let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); -// let cell_data = cell_bytes.parser::

()?; -// for group in self.groups_map.values() { -// if self.can_group(&group.content, &cell_data) { -// records.push(GroupRecord { -// row: row.into(), -// group_id: group.id.clone(), -// }); -// } -// } -// -// if records.is_empty() { -// self.default_group.rows.push(row.into()); -// } else { -// for record in records { -// if let Some(group) = self.groups_map.get_mut(&record.group_id) { -// group.rows.push(record.row); -// } -// } -// } -// } else { -// self.default_group.rows.push(row.into()); -// } -// } -// -// Ok(()) -// } -// } - struct GroupRecord { row: RowPB, group_id: String, diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 086d87a0d2..71c1c9ef97 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -5,7 +5,7 @@ use crate::services::field::{ }; use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable}; -use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; // SingleSelect pub type SingleSelectGroupController = GenericGroupController< @@ -43,15 +43,25 @@ impl Groupable for SingleSelectGroupController { fn move_row_if_match( &mut self, + field_rev: &FieldRevision, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, to_row_id: &str, ) -> Vec { - let mut changesets = vec![]; + let mut group_changeset = vec![]; self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - move_row(group, &mut changesets, cell_data, row_rev, to_row_id); + move_row( + group, + &mut group_changeset, + field_rev, + row_rev, + row_changeset, + cell_data, + to_row_id, + ); }); - changesets + group_changeset } } @@ -74,6 +84,7 @@ impl GroupGenerator for SingleSelectGroupGenerator { type ConfigurationType = SelectOptionGroupConfigurationPB; type TypeOptionType = SingleSelectTypeOptionPB; fn generate_groups( + field_id: &str, _configuration: &Option, type_option: &Option, ) -> Vec { @@ -82,7 +93,14 @@ impl GroupGenerator for SingleSelectGroupGenerator { Some(type_option) => type_option .options .iter() - .map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone())) + .map(|option| { + Group::new( + option.id.clone(), + field_id.to_owned(), + option.name.clone(), + option.id.clone(), + ) + }) .collect(), } } @@ -125,15 +143,25 @@ impl Groupable for MultiSelectGroupController { fn move_row_if_match( &mut self, + field_rev: &FieldRevision, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, to_row_id: &str, ) -> Vec { - let mut changesets = vec![]; + let mut group_changeset = vec![]; self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - move_row(group, &mut changesets, cell_data, row_rev, to_row_id); + move_row( + group, + &mut group_changeset, + field_rev, + row_rev, + row_changeset, + cell_data, + to_row_id, + ); }); - changesets + group_changeset } } @@ -156,6 +184,7 @@ impl GroupGenerator for MultiSelectGroupGenerator { type TypeOptionType = MultiSelectTypeOptionPB; fn generate_groups( + field_id: &str, _configuration: &Option, type_option: &Option, ) -> Vec { @@ -164,7 +193,14 @@ impl GroupGenerator for MultiSelectGroupGenerator { Some(type_option) => type_option .options .iter() - .map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone())) + .map(|option| { + Group::new( + option.id.clone(), + field_id.to_owned(), + option.name.clone(), + option.id.clone(), + ) + }) .collect(), } } @@ -204,25 +240,30 @@ fn remove_row( fn move_row( group: &mut Group, - changesets: &mut Vec, - cell_data: &SelectOptionCellDataPB, + group_changeset: &mut Vec, + field_rev: &FieldRevision, row_rev: &RowRevision, - upper_row_id: &str, + row_changeset: &mut RowChangeset, + cell_data: &SelectOptionCellDataPB, + to_row_id: &str, ) { cell_data.select_options.iter().for_each(|option| { if option.id == group.id && group.contains_row(&row_rev.id) { - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); group.remove_row(&row_rev.id); } - if let Some(index) = group.index_of_row(upper_row_id) { + if let Some(index) = group.index_of_row(to_row_id) { let row_pb = RowPB::from(row_rev); let inserted_row = InsertedRowPB { row: row_pb.clone(), index: Some(index as i32), }; - changesets.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); group.insert_row(index, row_pb); + + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); } }); } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index e4bf92e22a..af0ec90ba4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -7,7 +7,7 @@ use crate::services::group::{ }; use bytes::Bytes; use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision}; +use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision, RowChangeset}; use lib_infra::future::AFFuture; use std::future::Future; use std::sync::Arc; @@ -96,6 +96,7 @@ impl GroupService { pub(crate) async fn did_move_row( &self, row_rev: &RowRevision, + row_changeset: &mut RowChangeset, upper_row_id: &str, get_field_fn: F, ) -> Option> @@ -110,7 +111,7 @@ impl GroupService { match group_controller .write() .await - .did_move_row(row_rev, &field_rev, upper_row_id) + .did_move_row(row_rev, row_changeset, &field_rev, upper_row_id) { Ok(changesets) => Some(changesets), Err(e) => { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/row_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/row_test.rs index 85bfed576d..72b3a288a1 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/row_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/row_test.rs @@ -3,7 +3,7 @@ use crate::grid::block_test::script::{CreateRowScriptBuilder, GridRowTest}; use crate::grid::grid_editor::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, TWITTER}; use flowy_grid::entities::FieldType; use flowy_grid::services::field::{SELECTION_IDS_SEPARATOR, UNCHECK}; -use flowy_grid_data_model::revision::RowMetaChangeset; +use flowy_grid_data_model::revision::RowChangeset; #[tokio::test] async fn grid_create_row_count_test() { @@ -24,7 +24,7 @@ async fn grid_create_row_count_test() { async fn grid_update_row() { let mut test = GridRowTest::new().await; let row_rev = test.row_builder().build(); - let changeset = RowMetaChangeset { + let changeset = RowChangeset { row_id: row_rev.id.clone(), height: None, visibility: None, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs index 54a022e0d6..3830d7f1fe 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs @@ -5,7 +5,7 @@ use crate::grid::grid_editor::GridEditorTest; use flowy_grid::entities::{CreateRowParams, FieldType, GridCellIdParams, GridLayout, RowPB}; use flowy_grid::services::field::*; use flowy_grid_data_model::revision::{ - GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision, + GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowChangeset, RowRevision, }; use std::collections::HashMap; use std::sync::Arc; @@ -17,7 +17,7 @@ pub enum RowScript { row_rev: RowRevision, }, UpdateRow { - changeset: RowMetaChangeset, + changeset: RowChangeset, }, AssertRow { expected_row: RowRevision, diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs index def044f439..99737dc4d6 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs @@ -42,13 +42,28 @@ impl RowRevision { } } #[derive(Debug, Clone, Default)] -pub struct RowMetaChangeset { +pub struct RowChangeset { pub row_id: String, pub height: Option, pub visibility: Option, pub cell_by_field_id: HashMap, } +impl RowChangeset { + pub fn new(row_id: String) -> Self { + Self { + row_id, + height: None, + visibility: None, + cell_by_field_id: Default::default() + } + } + + pub fn has_changed(&self) -> bool { + self.height.is_some() || self.visibility.is_some() || !self.cell_by_field_id.is_empty() + } +} + #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct CellRevision { pub data: String, diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index 8abc1eaace..fa587d6a8c 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -2,7 +2,7 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_text_delta_from_revisions}; use flowy_grid_data_model::revision::{ - gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision, + gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowChangeset, RowRevision, }; use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder}; use std::borrow::Cow; @@ -143,7 +143,7 @@ impl GridBlockRevisionPad { self.block.rows.iter().position(|row| row.id == row_id) } - pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult> { + pub fn update_row(&mut self, changeset: RowChangeset) -> CollaborateResult> { let row_id = changeset.row_id.clone(); self.modify_row(&row_id, |row| { let mut is_changed = None; From 3e4e8679ce82f5e2b055521b53aefb6f609d5e9c Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 15:38:55 +0800 Subject: [PATCH 05/10] fix: debounce causes save cell data fail --- .../grid/application/cell/select_option_editor_bloc.dart | 2 +- .../grid/application/cell/select_option_service.dart | 2 +- .../grid/presentation/widgets/cell/number_cell.dart | 9 +++------ .../grid/presentation/widgets/cell/text_cell.dart | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart index 6ee7fe9f32..8d52252e2a 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart @@ -111,7 +111,7 @@ class SelectOptionCellEditorBloc void _loadOptions() { _delayOperation?.cancel(); _delayOperation = Timer(const Duration(milliseconds: 10), () { - _selectOptionService.getOpitonContext().then((result) { + _selectOptionService.getOptionContext().then((result) { if (isClosed) { return; } diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart index da1fc47170..44d4bdd4be 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart @@ -55,7 +55,7 @@ class SelectOptionService { return GridEventUpdateSelectOption(payload).send(); } - Future> getOpitonContext() { + Future> getOptionContext() { final payload = GridCellIdPB.create() ..gridId = gridId ..fieldId = fieldId diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart index 2926972f95..cd5151d750 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart @@ -65,6 +65,8 @@ class _NumberCellState extends GridFocusNodeCellState { @override Future dispose() async { + _delayOperation = null; + _cellBloc.close(); super.dispose(); } @@ -72,15 +74,10 @@ class _NumberCellState extends GridFocusNodeCellState { Future focusChanged() async { if (mounted) { _delayOperation?.cancel(); - _delayOperation = Timer(const Duration(milliseconds: 300), () { + _delayOperation = Timer(const Duration(milliseconds: 30), () { if (_cellBloc.isClosed == false && _controller.text != contentFromState(_cellBloc.state)) { _cellBloc.add(NumberCellEvent.updateCell(_controller.text)); - - if (!mounted) { - _delayOperation = null; - _cellBloc.close(); - } } }); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart index 04be48b9ea..0052ad5e70 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart @@ -76,7 +76,7 @@ class _GridTextCellState extends GridFocusNodeCellState { @override Future dispose() async { - _delayOperation?.cancel(); + _delayOperation = null; _cellBloc.close(); super.dispose(); } @@ -85,7 +85,7 @@ class _GridTextCellState extends GridFocusNodeCellState { Future focusChanged() async { if (mounted) { _delayOperation?.cancel(); - _delayOperation = Timer(const Duration(milliseconds: 300), () { + _delayOperation = Timer(const Duration(milliseconds: 30), () { if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) { _cellBloc.add(TextCellEvent.updateText(_controller.text)); From d3cd60e527b663504f81396e3be764057020df6a Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 17:40:23 +0800 Subject: [PATCH 06/10] refactor: rename structs --- .../app_flowy/lib/startup/plugin/plugin.dart | 2 +- .../workspace/application/app/app_bloc.dart | 2 +- .../home/menu/app/header/header.dart | 2 +- .../flowy-folder/src/entities/view.rs | 42 ++++++++------- frontend/rust-lib/flowy-folder/src/manager.rs | 6 +-- .../persistence/version_1/view_sql.rs | 8 +-- .../src/services/view/controller.rs | 49 +++++++++++------ .../tests/workspace/folder_test.rs | 8 +-- .../flowy-folder/tests/workspace/script.rs | 12 ++--- .../group_entities/group_changeset.rs | 15 ++++-- .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- .../single_select_type_option.rs | 2 - .../src/services/grid_view_editor.rs | 9 +++- .../group/group_generator/group_controller.rs | 1 + .../group_generator/select_option_group.rs | 18 +++++-- .../tests/grid/filter_test/script.rs | 2 +- .../flowy-grid/tests/grid/group_test/mod.rs | 1 + .../tests/grid/group_test/script.rs | 54 +++++++++++++++++++ .../rust-lib/flowy-grid/tests/grid/mod.rs | 1 + .../flowy-net/src/local_server/server.rs | 2 +- .../flowy-sdk/src/deps_resolve/folder_deps.rs | 14 ++--- frontend/rust-lib/flowy-sdk/src/lib.rs | 2 +- frontend/rust-lib/flowy-test/src/helper.rs | 29 +++++++--- .../src/revision/view_rev.rs | 8 +-- .../src/user_default.rs | 4 +- .../src/client_folder/folder_pad.rs | 10 ++-- .../src/client_grid/block_revision_pad.rs | 4 -- 27 files changed, 212 insertions(+), 97 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs diff --git a/frontend/app_flowy/lib/startup/plugin/plugin.dart b/frontend/app_flowy/lib/startup/plugin/plugin.dart index 2879af42cb..4b5cb4200b 100644 --- a/frontend/app_flowy/lib/startup/plugin/plugin.dart +++ b/frontend/app_flowy/lib/startup/plugin/plugin.dart @@ -56,7 +56,7 @@ abstract class PluginBuilder { ViewDataTypePB get dataType => ViewDataTypePB.TextBlock; - SubViewDataTypePB? get subDataType => null; + SubViewDataTypePB get subDataType; } abstract class PluginConfig { diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index c593c52679..f081716ea4 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -140,7 +140,7 @@ class AppEvent with _$AppEvent { String name, String desc, ViewDataTypePB dataType, - SubViewDataTypePB? subDataType, + SubViewDataTypePB subDataType, PluginType pluginType, ) = CreateView; const factory AppEvent.delete() = Delete; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart index 0cfac08628..9d02f1a013 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart @@ -114,7 +114,7 @@ class MenuAppHeader extends StatelessWidget { LocaleKeys.menuAppHeader_defaultNewPageName.tr(), "", pluginBuilder.dataType, - pluginBuilder.subDataType, + pluginBuilder.subDataType!, pluginBuilder.pluginType, )); }, diff --git a/frontend/rust-lib/flowy-folder/src/entities/view.rs b/frontend/rust-lib/flowy-folder/src/entities/view.rs index ae77017947..e62f0245a5 100644 --- a/frontend/rust-lib/flowy-folder/src/entities/view.rs +++ b/frontend/rust-lib/flowy-folder/src/entities/view.rs @@ -16,7 +16,7 @@ pub struct ViewPB { pub id: String, #[pb(index = 2)] - pub belong_to_id: String, + pub app_id: String, #[pb(index = 3)] pub name: String, @@ -38,7 +38,7 @@ impl std::convert::From for ViewPB { fn from(rev: ViewRevision) -> Self { ViewPB { id: rev.id, - belong_to_id: rev.belong_to_id, + app_id: rev.app_id, name: rev.name, data_type: rev.data_type.into(), modified_time: rev.modified_time, @@ -50,16 +50,10 @@ impl std::convert::From for ViewPB { #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] pub enum ViewDataTypePB { - TextBlock = 0, + Document = 0, Database = 1, } -#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] -pub enum SubViewDataTypePB { - Grid = 0, - Board = 1, -} - impl std::default::Default for ViewDataTypePB { fn default() -> Self { ViewDataTypeRevision::default().into() @@ -69,7 +63,7 @@ impl std::default::Default for ViewDataTypePB { impl std::convert::From for ViewDataTypePB { fn from(rev: ViewDataTypeRevision) -> Self { match rev { - ViewDataTypeRevision::TextBlock => ViewDataTypePB::TextBlock, + ViewDataTypeRevision::Document => ViewDataTypePB::Document, ViewDataTypeRevision::Database => ViewDataTypePB::Database, } } @@ -78,12 +72,24 @@ impl std::convert::From for ViewDataTypePB { impl std::convert::From for ViewDataTypeRevision { fn from(ty: ViewDataTypePB) -> Self { match ty { - ViewDataTypePB::TextBlock => ViewDataTypeRevision::TextBlock, + ViewDataTypePB::Document => ViewDataTypeRevision::Document, ViewDataTypePB::Database => ViewDataTypeRevision::Database, } } } +#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] +pub enum ViewLayoutTypePB { + Grid = 0, + Board = 1, +} + +impl std::default::Default for ViewLayoutTypePB { + fn default() -> Self { + ViewLayoutTypePB::Grid + } +} + #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)] pub struct RepeatedViewPB { #[pb(index = 1)] @@ -121,14 +127,14 @@ pub struct CreateViewPayloadPB { #[pb(index = 5)] pub data_type: ViewDataTypePB, - #[pb(index = 6, one_of)] - pub sub_data_type: Option, + #[pb(index = 6)] + pub layout: ViewLayoutTypePB, #[pb(index = 7)] pub plugin_type: i32, #[pb(index = 8)] - pub data: Vec, + pub view_content_data: Vec, } #[derive(Debug, Clone)] @@ -138,9 +144,9 @@ pub struct CreateViewParams { pub desc: String, pub thumbnail: String, pub data_type: ViewDataTypePB, - pub sub_data_type: Option, + pub layout: ViewLayoutTypePB, pub view_id: String, - pub data: Vec, + pub view_content_data: Vec, pub plugin_type: i32, } @@ -161,10 +167,10 @@ impl TryInto for CreateViewPayloadPB { name, desc: self.desc, data_type: self.data_type, - sub_data_type: self.sub_data_type, + layout: self.layout, thumbnail, view_id, - data: self.data, + view_content_data: self.view_content_data, plugin_type: self.plugin_type, }) } diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 96e35ba547..e09bfbabaf 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -1,5 +1,5 @@ use crate::entities::view::ViewDataTypePB; -use crate::entities::SubViewDataTypePB; +use crate::entities::ViewLayoutTypePB; use crate::services::folder_editor::FolderRevisionCompactor; use crate::{ dart_notification::{send_dart_notification, FolderNotification}, @@ -222,7 +222,7 @@ impl DefaultFolderBuilder { }; let _ = view_controller.set_latest_view(&view.id); let _ = view_controller - .create_view(&view.id, ViewDataTypePB::TextBlock, Bytes::from(view_data)) + .create_view(&view.id, ViewDataTypePB::Document, Bytes::from(view_data)) .await?; } } @@ -261,7 +261,7 @@ pub trait ViewDataProcessor { &self, user_id: &str, view_id: &str, - sub_data_type: Option, + sub_data_type: ViewLayoutTypePB, ) -> FutureResult; fn create_view_from_delta_data( diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index 245bd32f83..85f308130f 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -87,13 +87,13 @@ pub(crate) struct ViewTable { impl ViewTable { pub fn new(view_rev: ViewRevision) -> Self { let data_type = match view_rev.data_type { - ViewDataTypeRevision::TextBlock => SqlViewDataType::Block, + ViewDataTypeRevision::Document => SqlViewDataType::Block, ViewDataTypeRevision::Database => SqlViewDataType::Grid, }; ViewTable { id: view_rev.id, - belong_to_id: view_rev.belong_to_id, + belong_to_id: view_rev.app_id, name: view_rev.name, desc: view_rev.desc, modified_time: view_rev.modified_time, @@ -110,13 +110,13 @@ impl ViewTable { impl std::convert::From for ViewRevision { fn from(table: ViewTable) -> Self { let data_type = match table.view_type { - SqlViewDataType::Block => ViewDataTypeRevision::TextBlock, + SqlViewDataType::Block => ViewDataTypeRevision::Document, SqlViewDataType::Grid => ViewDataTypeRevision::Database, }; ViewRevision { id: table.id, - belong_to_id: table.belong_to_id, + app_id: table.belong_to_id, name: table.name, desc: table.desc, data_type, diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 4284d34b7c..3525e558a2 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -1,5 +1,5 @@ pub use crate::entities::view::ViewDataTypePB; -use crate::entities::ViewInfoPB; +use crate::entities::{ViewInfoPB, ViewLayoutTypePB}; use crate::manager::{ViewDataProcessor, ViewDataProcessorMap}; use crate::{ dart_notification::{send_dart_notification, FolderNotification}, @@ -19,6 +19,7 @@ use flowy_database::kv::KV; use flowy_folder_data_model::revision::{gen_view_id, ViewRevision}; use flowy_sync::entities::text_block::TextBlockIdPB; use futures::{FutureExt, StreamExt}; +use lib_infra::util::timestamp; use std::{collections::HashSet, sync::Arc}; const LATEST_VIEW_ID: &str = "latest_view_id"; @@ -60,14 +61,14 @@ impl ViewController { ) -> Result { let processor = self.get_data_processor(params.data_type.clone())?; let user_id = self.user.user_id()?; - if params.data.is_empty() { + if params.view_content_data.is_empty() { let view_data = processor - .create_default_view(&user_id, ¶ms.view_id, params.sub_data_type.clone()) + .create_default_view(&user_id, ¶ms.view_id, params.layout.clone()) .await?; - params.data = view_data.to_vec(); + params.view_content_data = view_data.to_vec(); } else { let delta_data = processor - .create_view_from_delta_data(&user_id, ¶ms.view_id, params.data.clone()) + .create_view_from_delta_data(&user_id, ¶ms.view_id, params.view_content_data.clone()) .await?; let _ = self .create_view(¶ms.view_id, params.data_type.clone(), delta_data) @@ -99,7 +100,7 @@ impl ViewController { let trash_controller = self.trash_controller.clone(); self.persistence .begin_transaction(|transaction| { - let belong_to_id = view_rev.belong_to_id.clone(); + let belong_to_id = view_rev.app_id.clone(); let _ = transaction.create_view(view_rev)?; let _ = notify_views_changed(&belong_to_id, trash_controller, &transaction)?; Ok(()) @@ -139,7 +140,7 @@ impl ViewController { let view_info = ViewInfoPB { id: view_rev.id, - belong_to_id: view_rev.belong_to_id, + belong_to_id: view_rev.app_id, name: view_rev.name, desc: view_rev.desc, data_type: view_rev.data_type.into(), @@ -197,7 +198,7 @@ impl ViewController { .begin_transaction(|transaction| { let _ = transaction.move_view(view_id, from, to)?; let view = transaction.read_view(view_id)?; - let _ = notify_views_changed(&view.belong_to_id, self.trash_controller.clone(), &transaction)?; + let _ = notify_views_changed(&view.app_id, self.trash_controller.clone(), &transaction)?; Ok(()) }) .await?; @@ -214,13 +215,13 @@ impl ViewController { let processor = self.get_data_processor(view_rev.data_type.clone())?; let delta_bytes = processor.get_delta_data(view_id).await?; let duplicate_params = CreateViewParams { - belong_to_id: view_rev.belong_to_id.clone(), + belong_to_id: view_rev.app_id.clone(), name: format!("{} (copy)", &view_rev.name), desc: view_rev.desc, thumbnail: view_rev.thumbnail, data_type: view_rev.data_type.into(), - sub_data_type: None, - data: delta_bytes.to_vec(), + layout: ViewLayoutTypePB::Board, + view_content_data: delta_bytes.to_vec(), view_id: gen_view_id(), plugin_type: view_rev.plugin_type, }; @@ -252,7 +253,7 @@ impl ViewController { send_dart_notification(&view_id, FolderNotification::ViewUpdated) .payload(view) .send(); - let _ = notify_views_changed(&view_rev.belong_to_id, self.trash_controller.clone(), &transaction)?; + let _ = notify_views_changed(&view_rev.app_id, self.trash_controller.clone(), &transaction)?; Ok(view_rev) }) .await?; @@ -395,7 +396,7 @@ async fn handle_trash_event( .begin_transaction(|transaction| { let view_revs = read_local_views_with_transaction(identifiers, &transaction)?; for view_rev in view_revs { - let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?; + let _ = notify_views_changed(&view_rev.app_id, trash_can.clone(), &transaction)?; notify_dart(view_rev.into(), FolderNotification::ViewDeleted); } Ok(()) @@ -408,7 +409,7 @@ async fn handle_trash_event( .begin_transaction(|transaction| { let view_revs = read_local_views_with_transaction(identifiers, &transaction)?; for view_rev in view_revs { - let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?; + let _ = notify_views_changed(&view_rev.app_id, trash_can.clone(), &transaction)?; notify_dart(view_rev.into(), FolderNotification::ViewRestored); } Ok(()) @@ -425,7 +426,7 @@ async fn handle_trash_event( for identifier in identifiers.items { let view = transaction.read_view(&identifier.id)?; let _ = transaction.delete_view(&view.id)?; - notify_ids.insert(view.belong_to_id.clone()); + notify_ids.insert(view.app_id.clone()); views.push(view); } for notify_id in notify_ids { @@ -453,6 +454,24 @@ async fn handle_trash_event( } } +fn make_view_rev_from(params: CreateViewParams) -> ViewRevision { + let time = timestamp(); + ViewRevision { + id: params.view_id, + app_id: params.belong_to_id, + name: params.name, + desc: params.desc, + data_type: params.data_type.into(), + version: 0, + belongings: vec![], + modified_time: time, + create_time: time, + ext_data: "".to_string(), + thumbnail: params.thumbnail, + plugin_type: params.plugin_type, + } +} + fn get_data_processor( data_processors: ViewDataProcessorMap, data_type: &ViewDataTypePB, diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs index 15af0cb8d9..69e3db1d38 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs @@ -134,7 +134,7 @@ async fn app_create_with_view() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::TextBlock, + data_type: ViewDataTypePB::Document, }, CreateView { name: "Grid".to_owned(), @@ -198,7 +198,7 @@ async fn view_delete_all() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::TextBlock, + data_type: ViewDataTypePB::Document, }, CreateView { name: "Grid".to_owned(), @@ -231,7 +231,7 @@ async fn view_delete_all_permanent() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::TextBlock, + data_type: ViewDataTypePB::Document, }, ReadApp(app.id.clone()), ]) @@ -330,7 +330,7 @@ async fn folder_sync_revision_with_new_view() { CreateView { name: view_name.clone(), desc: view_desc.clone(), - data_type: ViewDataTypePB::TextBlock, + data_type: ViewDataTypePB::Document, }, AssertCurrentRevId(3), AssertNextSyncRevId(Some(3)), diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index 528ffbcafb..e553744860 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -5,7 +5,7 @@ use flowy_folder::entities::{ trash::{RepeatedTrashPB, TrashIdPB, TrashType}, view::{CreateViewPayloadPB, UpdateViewPayloadPB}, workspace::{CreateWorkspacePayloadPB, RepeatedWorkspacePB}, - SubViewDataTypePB, + ViewLayoutTypePB, }; use flowy_folder::entities::{ app::{AppPB, RepeatedAppPB}, @@ -99,7 +99,7 @@ impl FolderTest { &app.id, "Folder View", "Folder test view", - ViewDataTypePB::TextBlock, + ViewDataTypePB::Document, ) .await; app.belongings = RepeatedViewPB { @@ -355,8 +355,8 @@ pub async fn create_view( data_type: ViewDataTypePB, ) -> ViewPB { let sub_data_type = match data_type { - ViewDataTypePB::TextBlock => None, - ViewDataTypePB::Database => Some(SubViewDataTypePB::Grid), + ViewDataTypePB::Document => None, + ViewDataTypePB::Database => Some(ViewLayoutTypePB::Grid), }; let request = CreateViewPayloadPB { @@ -365,9 +365,9 @@ pub async fn create_view( desc: desc.to_string(), thumbnail: None, data_type, - sub_data_type, + layout: sub_data_type, plugin_type: 0, - data: vec![], + view_content_data: vec![], }; let view = FolderEventBuilder::new(sdk.clone()) .event(CreateView) diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index 96bb832323..743da70444 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -19,9 +19,18 @@ pub struct GroupRowsChangesetPB { impl std::fmt::Display for GroupRowsChangesetPB { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let _ = f.write_fmt(format_args!("Group:{}", self.group_id))?; - let _ = f.write_fmt(format_args!("Insert:{:?}", self.inserted_rows))?; - f.write_fmt(format_args!("Delete:{:?}", self.deleted_rows)) + for inserted_row in &self.inserted_rows { + let _ = f.write_fmt(format_args!( + "Insert: {} row at {:?}", + inserted_row.row.id, inserted_row.index + ))?; + } + + for deleted_row in &self.deleted_rows { + let _ = f.write_fmt(format_args!("Delete: {} row", deleted_row))?; + } + + Ok(()) } } diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index df86f18fe3..b9484ad40d 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -225,7 +225,7 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType) Ok(type_option_data) } -#[tracing::instrument(level = "debug", skip(data, manager), err)] +// #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_row_handler( data: Data, manager: AppData>, diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs index 2380079a7f..803b175a84 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs @@ -65,10 +65,8 @@ impl CellDataOperation for SingleSel let select_option_changeset = changeset.try_into_inner()?; let new_cell_data: String; if let Some(insert_option_id) = select_option_changeset.insert_option_id { - tracing::trace!("Insert single select option: {}", &insert_option_id); new_cell_data = insert_option_id; } else { - tracing::trace!("Delete single select option"); new_cell_data = "".to_string() } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index e972745dfe..40a96a7255 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -117,7 +117,12 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, upper_row_id: &str) { + pub(crate) async fn did_move_row( + &self, + row_rev: &RowRevision, + row_changeset: &mut RowChangeset, + upper_row_id: &str, + ) { if let Some(changesets) = self .group_service .write() @@ -128,7 +133,7 @@ impl GridViewRevisionEditor { .await { for changeset in changesets { - tracing::trace!("Group changeset: {}", changeset); + tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset); self.notify_did_update_group(changeset).await; } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index f088bb2176..67d4ad0f9b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -277,6 +277,7 @@ where if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; + tracing::trace!("Move row:{} to row:{}", row_rev.id, to_row_id); Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id)) } else { Ok(vec![]) diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 71c1c9ef97..ffee185ea4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -248,11 +248,15 @@ fn move_row( to_row_id: &str, ) { cell_data.select_options.iter().for_each(|option| { - if option.id == group.id && group.contains_row(&row_rev.id) { - group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); + // Remove the row in which group contains the row + if option.id == group.id { + if group.contains_row(&row_rev.id) { + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } } + // Find the inserted group if let Some(index) = group.index_of_row(to_row_id) { let row_pb = RowPB::from(row_rev); let inserted_row = InsertedRowPB { @@ -262,8 +266,12 @@ fn move_row( group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); group.insert_row(index, row_pb); - let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); - row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); + // If the inserted row comes from other group, it needs to update the corresponding cell content. + if option.id != group.id { + // Update the corresponding row's cell content. + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); + } } }); } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index 3320204ae3..cfbc8c8926 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -36,7 +36,7 @@ pub struct GridFilterTest { impl GridFilterTest { pub async fn new() -> Self { - let editor_test = GridEditorTest::new().await; + let editor_test = GridEditorTest::new().await; Self { inner: editor_test } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs new file mode 100644 index 0000000000..1e31e92a96 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs @@ -0,0 +1 @@ +mod script; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs new file mode 100644 index 0000000000..f338770324 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs @@ -0,0 +1,54 @@ +use crate::grid::grid_editor::GridEditorTest; +use flowy_grid::entities::MoveRowParams; + +pub enum GroupScript { + MoveCard { from_row_id: String, to_row_id: String }, + AssertGroupCount(usize), +} + +pub struct GridGroupTest { + inner: GridEditorTest, +} + +impl GridGroupTest { + pub async fn new() -> Self { + let editor_test = GridEditorTest::new().await; + Self { inner: editor_test } + } + + pub async fn run_scripts(&mut self, scripts: Vec) { + for script in scripts { + self.run_script(script).await; + } + } + + pub async fn run_script(&mut self, script: GroupScript) { + match script { + GroupScript::MoveCard { from_row_id, to_row_id } => { + let params = MoveRowParams { + view_id: self.inner.grid_id.clone(), + from_row_id, + to_row_id, + }; + let _ = self.editor.move_row(params).await.unwrap(); + } + GroupScript::AssertGroupCount(count) => { + // + } + } + } +} + +impl std::ops::Deref for GridGroupTest { + type Target = GridEditorTest; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl std::ops::DerefMut for GridGroupTest { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/mod.rs b/frontend/rust-lib/flowy-grid/tests/grid/mod.rs index 8865bf01c2..4b250b9524 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/mod.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/mod.rs @@ -3,3 +3,4 @@ mod cell_test; mod field_test; mod filter_test; mod grid_editor; +mod group_test; diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 338697f432..39f7ce36f6 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -305,7 +305,7 @@ impl FolderCouldServiceV1 for LocalServer { let time = timestamp(); let view = ViewRevision { id: params.view_id, - belong_to_id: params.belong_to_id, + app_id: params.belong_to_id, name: params.name, desc: params.desc, data_type: params.data_type.into(), diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index cb1d90409e..5d424ead12 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -1,6 +1,6 @@ use bytes::Bytes; use flowy_database::ConnectionPool; -use flowy_folder::entities::{SubViewDataTypePB, ViewDataTypePB}; +use flowy_folder::entities::{ViewDataTypePB, ViewLayoutTypePB}; use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap}; use flowy_folder::{ errors::{internal_error, FlowyError}, @@ -184,7 +184,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { &self, user_id: &str, view_id: &str, - _sub_data_type: Option, + sub_data_type: ViewLayoutTypePB, ) -> FutureResult { let user_id = user_id.to_string(); let view_id = view_id.to_string(); @@ -209,7 +209,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { } fn data_type(&self) -> ViewDataTypePB { - ViewDataTypePB::TextBlock + ViewDataTypePB::Document } } @@ -261,11 +261,11 @@ impl ViewDataProcessor for GridViewDataProcessor { &self, user_id: &str, view_id: &str, - sub_data_type: Option, + sub_data_type: ViewLayoutTypePB, ) -> FutureResult { - let build_context = match sub_data_type.unwrap() { - SubViewDataTypePB::Grid => make_default_grid(), - SubViewDataTypePB::Board => make_default_board(), + let build_context = match sub_data_type { + ViewLayoutTypePB::Grid => make_default_grid(), + ViewLayoutTypePB::Board => make_default_board(), }; let user_id = user_id.to_string(); let view_id = view_id.to_string(); diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index e0bd601987..ce5920e532 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -74,7 +74,7 @@ fn crate_log_filter(level: String) -> String { filters.push(format!("lib_ot={}", level)); filters.push(format!("lib_ws={}", level)); filters.push(format!("lib_infra={}", level)); - filters.push(format!("flowy_sync={}", level)); + // filters.push(format!("flowy_sync={}", level)); // filters.push(format!("flowy_revision={}", level)); // filters.push(format!("lib_dispatch={}", level)); diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index d7155965e8..41f3b2a583 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -25,11 +25,16 @@ pub struct ViewTest { impl ViewTest { #[allow(dead_code)] - pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataTypePB, data: Vec) -> Self { + pub async fn new( + sdk: &FlowySDKTest, + data_type: ViewDataTypePB, + sub_data_type: ViewLayoutTypePB, + data: Vec, + ) -> Self { let workspace = create_workspace(sdk, "Workspace", "").await; open_workspace(sdk, &workspace.id).await; let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; - let view = create_view(sdk, &app.id, data_type, data).await; + let view = create_view(sdk, &app.id, data_type, sub_data_type, data).await; Self { sdk: sdk.clone(), workspace, @@ -39,11 +44,15 @@ impl ViewTest { } pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec) -> Self { - Self::new(sdk, ViewDataTypePB::Database, data).await + Self::new(sdk, ViewDataTypePB::Database, ViewLayoutTypePB::Grid, data).await + } + + pub async fn new_board_view(sdk: &FlowySDKTest, data: Vec) -> Self { + Self::new(sdk, ViewDataTypePB::Database, ViewLayoutTypePB::Board, data).await } pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self { - Self::new(sdk, ViewDataTypePB::TextBlock, vec![]).await + Self::new(sdk, ViewDataTypePB::Document, ViewLayoutTypePB::Grid, vec![]).await } } @@ -90,16 +99,22 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s app } -async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataTypePB, data: Vec) -> ViewPB { +async fn create_view( + sdk: &FlowySDKTest, + app_id: &str, + data_type: ViewDataTypePB, + sub_data_type: ViewLayoutTypePB, + data: Vec, +) -> ViewPB { let request = CreateViewPayloadPB { belong_to_id: app_id.to_string(), name: "View A".to_string(), desc: "".to_string(), thumbnail: Some("http://1.png".to_string()), data_type, - sub_data_type: None, + layout: sub_data_type, plugin_type: 0, - data, + view_content_data: data, }; let view = FolderEventBuilder::new(sdk.clone()) diff --git a/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs b/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs index 84b447a384..5f8aa006b0 100644 --- a/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs +++ b/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs @@ -9,7 +9,9 @@ pub fn gen_view_id() -> String { pub struct ViewRevision { pub id: String, - pub belong_to_id: String, + // Maybe app_id or vi + #[serde(rename = "belong_to_id")] + pub app_id: String, pub name: String, @@ -52,12 +54,12 @@ impl std::convert::From for TrashRevision { #[derive(Eq, PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum ViewDataTypeRevision { - TextBlock = 0, + Document = 0, Database = 1, } impl std::default::Default for ViewDataTypeRevision { fn default() -> Self { - ViewDataTypeRevision::TextBlock + ViewDataTypeRevision::Document } } diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 166bc32508..6072150e15 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -46,10 +46,10 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> ViewRevis ViewRevision { id: view_id, - belong_to_id: app_id, + app_id: app_id, name, desc: "".to_string(), - data_type: ViewDataTypeRevision::TextBlock, + data_type: ViewDataTypeRevision::Document, version: 0, belongings: vec![], modified_time: time.timestamp(), diff --git a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs index acef097250..22296f95d8 100644 --- a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs @@ -202,7 +202,7 @@ impl FolderPad { #[tracing::instrument(level = "trace", skip(self), fields(view_name=%view_rev.name), err)] pub fn create_view(&mut self, view_rev: ViewRevision) -> CollaborateResult> { - let app_id = view_rev.belong_to_id.clone(); + let app_id = view_rev.app_id.clone(); self.with_app(&app_id, move |app| { if app.belongings.contains(&view_rev) { tracing::warn!("[RootFolder]: Duplicate view"); @@ -243,7 +243,7 @@ impl FolderPad { modified_time: i64, ) -> CollaborateResult> { let view = self.read_view(view_id)?; - self.with_view(&view.belong_to_id, view_id, |view| { + self.with_view(&view.app_id, view_id, |view| { if let Some(name) = name { view.name = name; } @@ -260,7 +260,7 @@ impl FolderPad { #[tracing::instrument(level = "trace", skip(self), err)] pub fn delete_view(&mut self, view_id: &str) -> CollaborateResult> { let view = self.read_view(view_id)?; - self.with_app(&view.belong_to_id, |app| { + self.with_app(&view.app_id, |app| { app.belongings.retain(|view| view.id != view_id); Ok(Some(())) }) @@ -269,7 +269,7 @@ impl FolderPad { #[tracing::instrument(level = "trace", skip(self), err)] pub fn move_view(&mut self, view_id: &str, from: usize, to: usize) -> CollaborateResult> { let view = self.read_view(view_id)?; - self.with_app(&view.belong_to_id, |app| { + self.with_app(&view.app_id, |app| { match move_vec_element(&mut app.belongings, |view| view.id == view_id, from, to).map_err(internal_error)? { true => Ok(Some(())), false => Ok(None), @@ -807,7 +807,7 @@ mod tests { fn test_view_folder() -> (FolderPad, FolderDelta, ViewRevision) { let (mut folder, mut initial_delta, app) = test_app_folder(); let mut view_rev = ViewRevision::default(); - view_rev.belong_to_id = app.id.clone(); + view_rev.app_id = app.id.clone(); view_rev.name = "🎃 my first view".to_owned(); initial_delta = initial_delta diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index fa587d6a8c..f563f4b6fc 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -204,10 +204,6 @@ impl GridBlockRevisionPad { None => Ok(None), Some(delta) => { tracing::trace!("[GridBlockRevision] Composing delta {}", delta.json_str()); - // tracing::debug!( - // "[GridBlockMeta] current delta: {}", - // self.delta.to_str().unwrap_or_else(|_| "".to_string()) - // ); self.delta = self.delta.compose(&delta)?; Ok(Some(GridBlockRevisionChangeset { delta, From af23e3e8036cffe075fa2cfd988fb5e8790ac999 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 19:32:08 +0800 Subject: [PATCH 07/10] refactor: replace plugin type with layout type --- .../app_flowy/lib/plugins/blank/blank.dart | 2 +- .../app_flowy/lib/plugins/board/board.dart | 4 +- .../app_flowy/lib/plugins/doc/document.dart | 4 +- frontend/app_flowy/lib/plugins/grid/grid.dart | 4 +- .../app_flowy/lib/plugins/trash/menu.dart | 2 +- .../app_flowy/lib/plugins/trash/trash.dart | 2 +- .../app_flowy/lib/startup/plugin/plugin.dart | 40 +++++++++--------- .../lib/startup/plugin/src/sandbox.dart | 20 +++++---- .../workspace/application/app/app_bloc.dart | 4 +- .../application/app/app_service.dart | 8 +--- .../workspace/application/menu/menu_bloc.dart | 2 +- .../workspace/application/view/view_ext.dart | 13 ++++++ .../presentation/home/home_screen.dart | 1 + .../presentation/home/home_stack.dart | 2 +- .../flowy-folder/src/entities/view.rs | 42 +++++++++++++------ frontend/rust-lib/flowy-folder/src/manager.rs | 2 +- .../persistence/version_1/view_sql.rs | 10 ++--- .../src/services/view/controller.rs | 5 +-- .../tests/workspace/folder_test.rs | 8 ++-- .../flowy-folder/tests/workspace/script.rs | 22 +++++----- .../flowy-net/src/local_server/server.rs | 2 +- .../flowy-sdk/src/deps_resolve/folder_deps.rs | 12 ++++-- frontend/rust-lib/flowy-test/src/helper.rs | 7 ++-- .../src/revision/view_rev.rs | 24 +++++++++-- .../src/user_default.rs | 9 ++-- 25 files changed, 152 insertions(+), 99 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/blank/blank.dart b/frontend/app_flowy/lib/plugins/blank/blank.dart index 11f779eeb0..350a30ed50 100644 --- a/frontend/app_flowy/lib/plugins/blank/blank.dart +++ b/frontend/app_flowy/lib/plugins/blank/blank.dart @@ -16,7 +16,7 @@ class BlankPluginBuilder extends PluginBuilder { String get menuName => "Blank"; @override - PluginType get pluginType => DefaultPlugin.blank.type(); + PluginType get pluginType => PluginType.blank; } class BlankPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index 2954a7cbf9..c55d7f2e17 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -20,13 +20,13 @@ class BoardPluginBuilder implements PluginBuilder { String get menuName => "Board"; @override - PluginType get pluginType => DefaultPlugin.board.type(); + PluginType get pluginType => PluginType.board; @override ViewDataTypePB get dataType => ViewDataTypePB.Database; @override - SubViewDataTypePB get subDataType => SubViewDataTypePB.Board; + ViewLayoutTypePB? get subDataType => ViewLayoutTypePB.Board; } class BoardPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/plugins/doc/document.dart b/frontend/app_flowy/lib/plugins/doc/document.dart index 0deaedbb75..ba209ddbb7 100644 --- a/frontend/app_flowy/lib/plugins/doc/document.dart +++ b/frontend/app_flowy/lib/plugins/doc/document.dart @@ -42,10 +42,10 @@ class DocumentPluginBuilder extends PluginBuilder { String get menuName => LocaleKeys.document_menuName.tr(); @override - PluginType get pluginType => DefaultPlugin.editor.type(); + PluginType get pluginType => PluginType.editor; @override - ViewDataTypePB get dataType => ViewDataTypePB.TextBlock; + ViewDataTypePB get dataType => ViewDataTypePB.Text; } class DocumentPlugin implements Plugin { diff --git a/frontend/app_flowy/lib/plugins/grid/grid.dart b/frontend/app_flowy/lib/plugins/grid/grid.dart index 9ac539929a..f7d23d3891 100644 --- a/frontend/app_flowy/lib/plugins/grid/grid.dart +++ b/frontend/app_flowy/lib/plugins/grid/grid.dart @@ -22,13 +22,13 @@ class GridPluginBuilder implements PluginBuilder { String get menuName => LocaleKeys.grid_menuName.tr(); @override - PluginType get pluginType => DefaultPlugin.grid.type(); + PluginType get pluginType => PluginType.grid; @override ViewDataTypePB get dataType => ViewDataTypePB.Database; @override - SubViewDataTypePB? get subDataType => SubViewDataTypePB.Grid; + ViewLayoutTypePB? get subDataType => ViewLayoutTypePB.Grid; } class GridPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/plugins/trash/menu.dart b/frontend/app_flowy/lib/plugins/trash/menu.dart index e0a6c5ce49..15cfc398a1 100644 --- a/frontend/app_flowy/lib/plugins/trash/menu.dart +++ b/frontend/app_flowy/lib/plugins/trash/menu.dart @@ -23,7 +23,7 @@ class MenuTrash extends StatelessWidget { onTap: () { getIt().latestOpenView = null; getIt() - .setPlugin(makePlugin(pluginType: DefaultPlugin.trash.type())); + .setPlugin(makePlugin(pluginType: PluginType.trash)); }, child: _render(context), ), diff --git a/frontend/app_flowy/lib/plugins/trash/trash.dart b/frontend/app_flowy/lib/plugins/trash/trash.dart index 18a2c4aa8e..0d17091581 100644 --- a/frontend/app_flowy/lib/plugins/trash/trash.dart +++ b/frontend/app_flowy/lib/plugins/trash/trash.dart @@ -34,7 +34,7 @@ class TrashPluginBuilder extends PluginBuilder { String get menuName => "TrashPB"; @override - PluginType get pluginType => DefaultPlugin.trash.type(); + PluginType get pluginType => PluginType.trash; } class TrashPluginConfig implements PluginConfig { diff --git a/frontend/app_flowy/lib/startup/plugin/plugin.dart b/frontend/app_flowy/lib/startup/plugin/plugin.dart index 4b5cb4200b..6e06450295 100644 --- a/frontend/app_flowy/lib/startup/plugin/plugin.dart +++ b/frontend/app_flowy/lib/startup/plugin/plugin.dart @@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart'; export "./src/sandbox.dart"; -enum DefaultPlugin { +enum PluginType { editor, blank, trash, @@ -17,24 +17,24 @@ enum DefaultPlugin { board, } -extension FlowyDefaultPluginExt on DefaultPlugin { - int type() { - switch (this) { - case DefaultPlugin.editor: - return 0; - case DefaultPlugin.blank: - return 1; - case DefaultPlugin.trash: - return 2; - case DefaultPlugin.grid: - return 3; - case DefaultPlugin.board: - return 4; - } - } -} +// extension FlowyDefaultPluginExt on DefaultPlugin { +// int type() { +// switch (this) { +// case DefaultPlugin.editor: +// return 0; +// case DefaultPlugin.blank: +// return 1; +// case DefaultPlugin.trash: +// return 2; +// case DefaultPlugin.grid: +// return 3; +// case DefaultPlugin.board: +// return 4; +// } +// } +// } -typedef PluginType = int; +// typedef PluginType = int; typedef PluginId = String; abstract class Plugin { @@ -54,9 +54,9 @@ abstract class PluginBuilder { PluginType get pluginType; - ViewDataTypePB get dataType => ViewDataTypePB.TextBlock; + ViewDataTypePB get dataType => ViewDataTypePB.Text; - SubViewDataTypePB get subDataType; + ViewLayoutTypePB? get subDataType => null; } abstract class PluginConfig { diff --git a/frontend/app_flowy/lib/startup/plugin/src/sandbox.dart b/frontend/app_flowy/lib/startup/plugin/src/sandbox.dart index 5f1d63c287..ca32ec4217 100644 --- a/frontend/app_flowy/lib/startup/plugin/src/sandbox.dart +++ b/frontend/app_flowy/lib/startup/plugin/src/sandbox.dart @@ -6,8 +6,10 @@ import '../plugin.dart'; import 'runner.dart'; class PluginSandbox { - final LinkedHashMap _pluginBuilders = LinkedHashMap(); - final Map _pluginConfigs = {}; + final LinkedHashMap _pluginBuilders = + LinkedHashMap(); + final Map _pluginConfigs = + {}; late PluginRunner pluginRunner; PluginSandbox() { @@ -15,9 +17,11 @@ class PluginSandbox { } int indexOf(PluginType pluginType) { - final index = _pluginBuilders.keys.toList().indexWhere((ty) => ty == pluginType); + final index = + _pluginBuilders.keys.toList().indexWhere((ty) => ty == pluginType); if (index == -1) { - throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType"); + throw PlatformException( + code: '-1', message: "Can't find the flowy plugin type: $pluginType"); } return index; } @@ -27,9 +31,11 @@ class PluginSandbox { return plugin; } - void registerPlugin(PluginType pluginType, PluginBuilder builder, {PluginConfig? config}) { + void registerPlugin(PluginType pluginType, PluginBuilder builder, + {PluginConfig? config}) { if (_pluginBuilders.containsKey(pluginType)) { - throw PlatformException(code: '-1', message: "$pluginType was registered before"); + throw PlatformException( + code: '-1', message: "$pluginType was registered before"); } _pluginBuilders[pluginType] = builder; @@ -38,7 +44,7 @@ class PluginSandbox { } } - List get supportPluginTypes => _pluginBuilders.keys.toList(); + List get supportPluginTypes => _pluginBuilders.keys.toList(); List get builders => _pluginBuilders.values.toList(); diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index f081716ea4..61db9a0cdf 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -86,7 +86,7 @@ class AppBloc extends Bloc { desc: value.desc, dataType: value.dataType, pluginType: value.pluginType, - subDataType: value.subDataType, + layout: value.layout, ); viewOrFailed.fold( (view) => emit(state.copyWith( @@ -140,7 +140,7 @@ class AppEvent with _$AppEvent { String name, String desc, ViewDataTypePB dataType, - SubViewDataTypePB subDataType, + ViewLayoutTypePB layout, PluginType pluginType, ) = CreateView; const factory AppEvent.delete() = Delete; diff --git a/frontend/app_flowy/lib/workspace/application/app/app_service.dart b/frontend/app_flowy/lib/workspace/application/app/app_service.dart index b05c64dd23..e2a6896066 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_service.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_service.dart @@ -26,18 +26,14 @@ class AppService { required String desc, required ViewDataTypePB dataType, required PluginType pluginType, - SubViewDataTypePB? subDataType, + required ViewLayoutTypePB layout, }) { var payload = CreateViewPayloadPB.create() ..belongToId = appId ..name = name ..desc = desc ..dataType = dataType - ..pluginType = pluginType; - - if (subDataType != null) { - payload.subDataType = subDataType; - } + ..layout = layout; return FolderEventCreateView(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index 4b699570e6..debb1e71c3 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -113,6 +113,6 @@ class MenuState with _$MenuState { factory MenuState.initial() => MenuState( apps: [], successOrFailure: left(unit), - plugin: makePlugin(pluginType: DefaultPlugin.blank.type()), + plugin: makePlugin(pluginType: PluginType.blank), ); } diff --git a/frontend/app_flowy/lib/workspace/application/view/view_ext.dart b/frontend/app_flowy/lib/workspace/application/view/view_ext.dart index 79a27b64ce..3684d9670c 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_ext.dart @@ -40,6 +40,19 @@ extension ViewExtension on ViewPB { return widget; } + PluginType get pluginType { + switch (layout) { + case ViewLayoutTypePB.Board: + return PluginType.board; + case ViewLayoutTypePB.Document: + return PluginType.editor; + case ViewLayoutTypePB.Grid: + return PluginType.grid; + } + + throw UnimplementedError; + } + Plugin plugin() { final plugin = makePlugin(pluginType: pluginType, data: this); return plugin; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index 3259e3d843..dce1c71f29 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/plugin/plugin.dart'; import 'package:app_flowy/workspace/application/home/home_bloc.dart'; +import 'package:app_flowy/workspace/application/view/view_ext.dart'; import 'package:app_flowy/workspace/presentation/widgets/edit_panel/panel_animation.dart'; import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart'; import 'package:app_flowy/startup/startup.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart index 73ebde5141..5099dcddfc 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart @@ -107,7 +107,7 @@ class HomeStackNotifier extends ChangeNotifier { Widget get titleWidget => _plugin.display.leftBarItem; HomeStackNotifier({Plugin? plugin}) - : _plugin = plugin ?? makePlugin(pluginType: DefaultPlugin.blank.type()); + : _plugin = plugin ?? makePlugin(pluginType: PluginType.blank); set plugin(Plugin newPlugin) { if (newPlugin.id == _plugin.id) { diff --git a/frontend/rust-lib/flowy-folder/src/entities/view.rs b/frontend/rust-lib/flowy-folder/src/entities/view.rs index e62f0245a5..af66502907 100644 --- a/frontend/rust-lib/flowy-folder/src/entities/view.rs +++ b/frontend/rust-lib/flowy-folder/src/entities/view.rs @@ -7,7 +7,7 @@ use crate::{ impl_def_and_def_mut, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_folder_data_model::revision::{gen_view_id, ViewDataTypeRevision, ViewRevision}; +use flowy_folder_data_model::revision::{gen_view_id, ViewDataTypeRevision, ViewLayoutTypeRevision, ViewRevision}; use std::convert::TryInto; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] @@ -31,7 +31,7 @@ pub struct ViewPB { pub create_time: i64, #[pb(index = 7)] - pub plugin_type: i32, + pub layout: ViewLayoutTypePB, } impl std::convert::From for ViewPB { @@ -43,14 +43,14 @@ impl std::convert::From for ViewPB { data_type: rev.data_type.into(), modified_time: rev.modified_time, create_time: rev.create_time, - plugin_type: rev.plugin_type, + layout: rev.layout.into(), } } } #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] pub enum ViewDataTypePB { - Document = 0, + Text = 0, Database = 1, } @@ -63,7 +63,7 @@ impl std::default::Default for ViewDataTypePB { impl std::convert::From for ViewDataTypePB { fn from(rev: ViewDataTypeRevision) -> Self { match rev { - ViewDataTypeRevision::Document => ViewDataTypePB::Document, + ViewDataTypeRevision::Text => ViewDataTypePB::Text, ViewDataTypeRevision::Database => ViewDataTypePB::Database, } } @@ -72,7 +72,7 @@ impl std::convert::From for ViewDataTypePB { impl std::convert::From for ViewDataTypeRevision { fn from(ty: ViewDataTypePB) -> Self { match ty { - ViewDataTypePB::Document => ViewDataTypeRevision::Document, + ViewDataTypePB::Text => ViewDataTypeRevision::Text, ViewDataTypePB::Database => ViewDataTypeRevision::Database, } } @@ -80,8 +80,9 @@ impl std::convert::From for ViewDataTypeRevision { #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] pub enum ViewLayoutTypePB { - Grid = 0, - Board = 1, + Document = 0, + Grid = 3, + Board = 4, } impl std::default::Default for ViewLayoutTypePB { @@ -90,6 +91,26 @@ impl std::default::Default for ViewLayoutTypePB { } } +impl std::convert::From for ViewLayoutTypePB { + fn from(rev: ViewLayoutTypeRevision) -> Self { + match rev { + ViewLayoutTypeRevision::Grid => ViewLayoutTypePB::Grid, + ViewLayoutTypeRevision::Board => ViewLayoutTypePB::Board, + ViewLayoutTypeRevision::Document => ViewLayoutTypePB::Document, + } + } +} + +impl std::convert::From for ViewLayoutTypeRevision { + fn from(rev: ViewLayoutTypePB) -> Self { + match rev { + ViewLayoutTypePB::Grid => ViewLayoutTypeRevision::Grid, + ViewLayoutTypePB::Board => ViewLayoutTypeRevision::Board, + ViewLayoutTypePB::Document => ViewLayoutTypeRevision::Document, + } + } +} + #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)] pub struct RepeatedViewPB { #[pb(index = 1)] @@ -131,9 +152,6 @@ pub struct CreateViewPayloadPB { pub layout: ViewLayoutTypePB, #[pb(index = 7)] - pub plugin_type: i32, - - #[pb(index = 8)] pub view_content_data: Vec, } @@ -147,7 +165,6 @@ pub struct CreateViewParams { pub layout: ViewLayoutTypePB, pub view_id: String, pub view_content_data: Vec, - pub plugin_type: i32, } impl TryInto for CreateViewPayloadPB { @@ -171,7 +188,6 @@ impl TryInto for CreateViewPayloadPB { thumbnail, view_id, view_content_data: self.view_content_data, - plugin_type: self.plugin_type, }) } } diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index e09bfbabaf..69d1f618d5 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -222,7 +222,7 @@ impl DefaultFolderBuilder { }; let _ = view_controller.set_latest_view(&view.id); let _ = view_controller - .create_view(&view.id, ViewDataTypePB::Document, Bytes::from(view_data)) + .create_view(&view.id, ViewDataTypePB::Text, Bytes::from(view_data)) .await?; } } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs index 85f308130f..c1b21cbe32 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs @@ -13,7 +13,7 @@ use flowy_database::{ SqliteConnection, }; -use flowy_folder_data_model::revision::{ViewDataTypeRevision, ViewRevision}; +use flowy_folder_data_model::revision::{ViewDataTypeRevision, ViewLayoutTypeRevision, ViewRevision}; use lib_infra::util::timestamp; pub struct ViewTableSql(); @@ -87,7 +87,7 @@ pub(crate) struct ViewTable { impl ViewTable { pub fn new(view_rev: ViewRevision) -> Self { let data_type = match view_rev.data_type { - ViewDataTypeRevision::Document => SqlViewDataType::Block, + ViewDataTypeRevision::Text => SqlViewDataType::Block, ViewDataTypeRevision::Database => SqlViewDataType::Grid, }; @@ -110,7 +110,7 @@ impl ViewTable { impl std::convert::From for ViewRevision { fn from(table: ViewTable) -> Self { let data_type = match table.view_type { - SqlViewDataType::Block => ViewDataTypeRevision::Document, + SqlViewDataType::Block => ViewDataTypeRevision::Text, SqlViewDataType::Grid => ViewDataTypeRevision::Database, }; @@ -127,8 +127,8 @@ impl std::convert::From for ViewRevision { ext_data: "".to_string(), thumbnail: table.thumbnail, // Store the view in ViewTable was deprecated since v0.0.2. - // No need to worry about plugin_type. - plugin_type: 0, + // No need to worry about layout. + layout: ViewLayoutTypeRevision::Document, } } } diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 3525e558a2..b8a028b293 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -220,10 +220,9 @@ impl ViewController { desc: view_rev.desc, thumbnail: view_rev.thumbnail, data_type: view_rev.data_type.into(), - layout: ViewLayoutTypePB::Board, + layout: view_rev.layout.into(), view_content_data: delta_bytes.to_vec(), view_id: gen_view_id(), - plugin_type: view_rev.plugin_type, }; let _ = self.create_view_from_params(duplicate_params).await?; @@ -468,7 +467,7 @@ fn make_view_rev_from(params: CreateViewParams) -> ViewRevision { create_time: time, ext_data: "".to_string(), thumbnail: params.thumbnail, - plugin_type: params.plugin_type, + layout: params.layout.into(), } } diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs index 69e3db1d38..ea2322cf94 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs @@ -134,7 +134,7 @@ async fn app_create_with_view() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::Document, + data_type: ViewDataTypePB::Text, }, CreateView { name: "Grid".to_owned(), @@ -198,7 +198,7 @@ async fn view_delete_all() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::Document, + data_type: ViewDataTypePB::Text, }, CreateView { name: "Grid".to_owned(), @@ -231,7 +231,7 @@ async fn view_delete_all_permanent() { CreateView { name: "View A".to_owned(), desc: "View A description".to_owned(), - data_type: ViewDataTypePB::Document, + data_type: ViewDataTypePB::Text, }, ReadApp(app.id.clone()), ]) @@ -330,7 +330,7 @@ async fn folder_sync_revision_with_new_view() { CreateView { name: view_name.clone(), desc: view_desc.clone(), - data_type: ViewDataTypePB::Document, + data_type: ViewDataTypePB::Text, }, AssertCurrentRevId(3), AssertNextSyncRevId(Some(3)), diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index e553744860..2c53d5e2a4 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -53,6 +53,7 @@ pub enum FolderScript { name: String, desc: String, data_type: ViewDataTypePB, + layout: ViewLayoutTypePB, }, AssertView(ViewPB), ReadView(String), @@ -99,7 +100,8 @@ impl FolderTest { &app.id, "Folder View", "Folder test view", - ViewDataTypePB::Document, + ViewDataTypePB::Text, + ViewLayoutTypePB::Document, ) .await; app.belongings = RepeatedViewPB { @@ -179,8 +181,13 @@ impl FolderTest { delete_app(sdk, &self.app.id).await; } - FolderScript::CreateView { name, desc, data_type } => { - let view = create_view(sdk, &self.app.id, &name, &desc, data_type).await; + FolderScript::CreateView { + name, + desc, + data_type, + layout, + } => { + let view = create_view(sdk, &self.app.id, &name, &desc, data_type, layout).await; self.view = view; } FolderScript::AssertView(view) => { @@ -353,20 +360,15 @@ pub async fn create_view( name: &str, desc: &str, data_type: ViewDataTypePB, + layout: ViewLayoutTypePB, ) -> ViewPB { - let sub_data_type = match data_type { - ViewDataTypePB::Document => None, - ViewDataTypePB::Database => Some(ViewLayoutTypePB::Grid), - }; - let request = CreateViewPayloadPB { belong_to_id: app_id.to_string(), name: name.to_string(), desc: desc.to_string(), thumbnail: None, data_type, - layout: sub_data_type, - plugin_type: 0, + layout, view_content_data: vec![], }; let view = FolderEventBuilder::new(sdk.clone()) diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 39f7ce36f6..387ff4e885 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -315,7 +315,7 @@ impl FolderCouldServiceV1 for LocalServer { create_time: time, ext_data: "".to_string(), thumbnail: params.thumbnail, - plugin_type: params.plugin_type, + layout: params.layout.into(), }; FutureResult::new(async { Ok(view) }) } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index 5d424ead12..d997d71be4 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -209,7 +209,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { } fn data_type(&self) -> ViewDataTypePB { - ViewDataTypePB::Document + ViewDataTypePB::Text } } @@ -261,16 +261,20 @@ impl ViewDataProcessor for GridViewDataProcessor { &self, user_id: &str, view_id: &str, - sub_data_type: ViewLayoutTypePB, + layout: ViewLayoutTypePB, ) -> FutureResult { - let build_context = match sub_data_type { + let build_context = match layout { ViewLayoutTypePB::Grid => make_default_grid(), ViewLayoutTypePB::Board => make_default_board(), + ViewLayoutTypePB::Document => { + return FutureResult::new(async move { + Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout))) + }); + } }; let user_id = user_id.to_string(); let view_id = view_id.to_string(); let grid_manager = self.0.clone(); - FutureResult::new(async move { make_grid_view_data(&user_id, &view_id, grid_manager, build_context).await }) } diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 41f3b2a583..e55b4fdbeb 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -52,7 +52,7 @@ impl ViewTest { } pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self { - Self::new(sdk, ViewDataTypePB::Document, ViewLayoutTypePB::Grid, vec![]).await + Self::new(sdk, ViewDataTypePB::Text, ViewLayoutTypePB::Grid, vec![]).await } } @@ -103,7 +103,7 @@ async fn create_view( sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataTypePB, - sub_data_type: ViewLayoutTypePB, + layout: ViewLayoutTypePB, data: Vec, ) -> ViewPB { let request = CreateViewPayloadPB { @@ -112,8 +112,7 @@ async fn create_view( desc: "".to_string(), thumbnail: Some("http://1.png".to_string()), data_type, - layout: sub_data_type, - plugin_type: 0, + layout, view_content_data: data, }; diff --git a/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs b/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs index 5f8aa006b0..f5bf1d7ffc 100644 --- a/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs +++ b/shared-lib/flowy-folder-data-model/src/revision/view_rev.rs @@ -35,9 +35,10 @@ pub struct ViewRevision { pub thumbnail: String, #[serde(default = "DEFAULT_PLUGIN_TYPE")] - pub plugin_type: i32, + #[serde(rename = "plugin_type")] + pub layout: ViewLayoutTypeRevision, } -const DEFAULT_PLUGIN_TYPE: fn() -> i32 = || 0; +const DEFAULT_PLUGIN_TYPE: fn() -> ViewLayoutTypeRevision = || ViewLayoutTypeRevision::Document; impl std::convert::From for TrashRevision { fn from(view_rev: ViewRevision) -> Self { @@ -54,12 +55,27 @@ impl std::convert::From for TrashRevision { #[derive(Eq, PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum ViewDataTypeRevision { - Document = 0, + Text = 0, Database = 1, } impl std::default::Default for ViewDataTypeRevision { fn default() -> Self { - ViewDataTypeRevision::Document + ViewDataTypeRevision::Text + } +} + +#[derive(Eq, PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum ViewLayoutTypeRevision { + Document = 0, + // The for historical reasons, the value of Grid is not 1. + Grid = 3, + Board = 4, +} + +impl std::default::Default for ViewLayoutTypeRevision { + fn default() -> Self { + ViewLayoutTypeRevision::Document } } diff --git a/shared-lib/flowy-folder-data-model/src/user_default.rs b/shared-lib/flowy-folder-data-model/src/user_default.rs index 6072150e15..bb4eacc4dc 100644 --- a/shared-lib/flowy-folder-data-model/src/user_default.rs +++ b/shared-lib/flowy-folder-data-model/src/user_default.rs @@ -1,5 +1,6 @@ use crate::revision::{ - gen_app_id, gen_view_id, gen_workspace_id, AppRevision, ViewDataTypeRevision, ViewRevision, WorkspaceRevision, + gen_app_id, gen_view_id, gen_workspace_id, AppRevision, ViewDataTypeRevision, ViewLayoutTypeRevision, ViewRevision, + WorkspaceRevision, }; use chrono::Utc; @@ -46,16 +47,16 @@ fn create_default_view(app_id: String, time: chrono::DateTime) -> ViewRevis ViewRevision { id: view_id, - app_id: app_id, + app_id, name, desc: "".to_string(), - data_type: ViewDataTypeRevision::Document, + data_type: ViewDataTypeRevision::Text, version: 0, belongings: vec![], modified_time: time.timestamp(), create_time: time.timestamp(), ext_data: "".to_string(), thumbnail: "".to_string(), - plugin_type: 0, + layout: ViewLayoutTypeRevision::Document, } } From 0680b2057961bc7083273b7be735792cff8cf82e Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 21:43:05 +0800 Subject: [PATCH 08/10] chore: add group unit test --- .../presentation/card/board_text_cell.dart | 2 - .../src/services/view/controller.rs | 2 +- .../tests/workspace/folder_test.rs | 7 +++ .../src/entities/group_entities/group.rs | 15 ++++- .../flowy-grid/src/services/grid_editor.rs | 4 +- .../src/services/grid_view_editor.rs | 34 ++++++---- .../group/group_generator/checkbox_group.rs | 4 +- .../group/group_generator/group_controller.rs | 4 +- .../group_generator/select_option_group.rs | 8 +-- .../src/services/group/group_service.rs | 21 ++++--- .../tests/grid/block_test/script.rs | 2 +- .../flowy-grid/tests/grid/cell_test/script.rs | 2 +- .../tests/grid/field_test/script.rs | 2 +- .../tests/grid/filter_test/script.rs | 2 +- .../flowy-grid/tests/grid/grid_editor.rs | 17 ++++- .../flowy-grid/tests/grid/group_test/mod.rs | 1 + .../tests/grid/group_test/script.rs | 63 ++++++++++++++++--- .../flowy-grid/tests/grid/group_test/test.rs | 51 +++++++++++++++ .../flowy-sdk/src/deps_resolve/folder_deps.rs | 2 +- .../src/client_grid/block_revision_pad.rs | 4 +- 20 files changed, 192 insertions(+), 55 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart index 5148b2c438..2da156ded8 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart @@ -1,10 +1,8 @@ import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_svg/svg.dart'; class BoardTextCell extends StatefulWidget { final GridCellControllerBuilder cellControllerBuilder; diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index b8a028b293..8ad370916e 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -1,5 +1,5 @@ pub use crate::entities::view::ViewDataTypePB; -use crate::entities::{ViewInfoPB, ViewLayoutTypePB}; +use crate::entities::ViewInfoPB; use crate::manager::{ViewDataProcessor, ViewDataProcessorMap}; use crate::{ dart_notification::{send_dart_notification, FolderNotification}, diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs index ea2322cf94..9872641d9a 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs @@ -1,6 +1,7 @@ use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest}; use flowy_folder::entities::view::ViewDataTypePB; use flowy_folder::entities::workspace::CreateWorkspacePayloadPB; +use flowy_folder::entities::ViewLayoutTypePB; use flowy_revision::disk::RevisionState; use flowy_test::{event_builder::*, FlowySDKTest}; @@ -135,11 +136,13 @@ async fn app_create_with_view() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, + layout: ViewLayoutTypePB::Document, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, + layout: ViewLayoutTypePB::Document, }, ReadApp(app.id), ]) @@ -199,11 +202,13 @@ async fn view_delete_all() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, + layout: ViewLayoutTypePB::Document, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, + layout: ViewLayoutTypePB::Document, }, ReadApp(app.id.clone()), ]) @@ -232,6 +237,7 @@ async fn view_delete_all_permanent() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, + layout: ViewLayoutTypePB::Document, }, ReadApp(app.id.clone()), ]) @@ -331,6 +337,7 @@ async fn folder_sync_revision_with_new_view() { name: view_name.clone(), desc: view_desc.clone(), data_type: ViewDataTypePB::Text, + layout: ViewLayoutTypePB::Document, }, AssertCurrentRevId(3), AssertNextSyncRevId(Some(3)), diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs index 4a0f56e425..fc32cb79ba 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs @@ -28,7 +28,20 @@ impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationP #[derive(ProtoBuf, Debug, Default, Clone)] pub struct RepeatedGridGroupPB { #[pb(index = 1)] - pub(crate) items: Vec, + pub items: Vec, +} + +impl std::ops::Deref for RepeatedGridGroupPB { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.items + } +} + +impl std::ops::DerefMut for RepeatedGridGroupPB { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.items + } } #[derive(ProtoBuf, Debug, Default, Clone)] diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index e796929ce6..7c7ef00c2e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -9,9 +9,7 @@ use crate::services::field::{default_type_option_builder_from_type, type_option_ use crate::services::filter::GridFilterService; use crate::services::grid_view_manager::GridViewManager; use crate::services::persistence::block_index::BlockIndexCache; -use crate::services::row::{ - make_grid_blocks, make_row_from_row_rev, make_rows_from_row_revs, GridBlockSnapshot, RowRevisionBuilder, -}; +use crate::services::row::{make_grid_blocks, make_rows_from_row_revs, GridBlockSnapshot, RowRevisionBuilder}; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::revision::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 40a96a7255..ee121913cc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -13,6 +13,7 @@ use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad}; use flowy_sync::entities::grid::GridSettingChangesetParams; use flowy_sync::entities::revision::Revision; use lib_infra::future::{wrap_future, AFFuture, FutureResult}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; @@ -26,6 +27,7 @@ pub struct GridViewRevisionEditor { row_delegate: Arc, group_service: Arc>, scheduler: Arc, + did_load_group: AtomicBool, } impl GridViewRevisionEditor { @@ -46,6 +48,7 @@ impl GridViewRevisionEditor { let rev_manager = Arc::new(rev_manager); let group_service = GroupService::new(Box::new(pad.clone())).await; let user_id = user_id.to_owned(); + let did_load_group = AtomicBool::new(false); Ok(Self { pad, user_id, @@ -55,6 +58,7 @@ impl GridViewRevisionEditor { field_delegate, row_delegate, group_service: Arc::new(RwLock::new(group_service)), + did_load_group, }) } @@ -140,19 +144,25 @@ impl GridViewRevisionEditor { } pub(crate) async fn load_groups(&self) -> FlowyResult> { - let field_revs = self.field_delegate.get_field_revs().await; - let row_revs = self.row_delegate.gv_row_revs().await; + let groups = if !self.did_load_group.load(Ordering::SeqCst) { + self.did_load_group.store(true, Ordering::SeqCst); + let field_revs = self.field_delegate.get_field_revs().await; + let row_revs = self.row_delegate.gv_row_revs().await; + match self + .group_service + .write() + .await + .load_groups(&field_revs, row_revs) + .await + { + None => vec![], + Some(groups) => groups, + } + } else { + self.group_service.read().await.groups().await + }; - match self - .group_service - .write() - .await - .load_groups(&field_revs, row_revs) - .await - { - None => Ok(vec![]), - Some(groups) => Ok(groups.into_iter().map(GroupPB::from).collect()), - } + Ok(groups.into_iter().map(GroupPB::from).collect()) } pub(crate) async fn get_setting(&self) -> GridSettingPB { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index c1f4261bb5..c1284dd659 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -37,9 +37,9 @@ impl Groupable for CheckboxGroupController { fn move_row_if_match( &mut self, - field_rev: &FieldRevision, + _field_rev: &FieldRevision, _row_rev: &RowRevision, - row_changeset: &mut RowChangeset, + _row_changeset: &mut RowChangeset, _cell_data: &Self::CellDataType, _to_row_id: &str, ) -> Vec { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index 67d4ad0f9b..05924bcfef 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -47,7 +47,7 @@ pub trait GroupController: GroupControllerSharedAction + Send + Sync { pub trait GroupControllerSharedAction: Send + Sync { // The field that is used for grouping the rows fn field_id(&self) -> &str; - fn build_groups(&self) -> Vec; + fn groups(&self) -> Vec; fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()>; fn did_update_row( &mut self, @@ -194,7 +194,7 @@ where &self.field_id } - fn build_groups(&self) -> Vec { + fn groups(&self) -> Vec { let default_group = self.default_group.clone(); let mut groups: Vec = self.groups_map.values().cloned().collect(); if !default_group.rows.is_empty() { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index ffee185ea4..625f1fa643 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -249,11 +249,9 @@ fn move_row( ) { cell_data.select_options.iter().for_each(|option| { // Remove the row in which group contains the row - if option.id == group.id { - if group.contains_row(&row_rev.id) { - group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } + if option.id == group.id && group.contains_row(&row_rev.id) { + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); } // Find the inserted group diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index af0ec90ba4..4424b0edcc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -7,7 +7,9 @@ use crate::services::group::{ }; use bytes::Bytes; use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision, RowChangeset}; +use flowy_grid_data_model::revision::{ + gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision, +}; use lib_infra::future::AFFuture; use std::future::Future; use std::sync::Arc; @@ -18,7 +20,6 @@ pub trait GroupConfigurationDelegate: Send + Sync + 'static { } pub(crate) struct GroupService { - pub groups: Vec, delegate: Box, group_controller: Option>>, } @@ -26,12 +27,19 @@ pub(crate) struct GroupService { impl GroupService { pub(crate) async fn new(delegate: Box) -> Self { Self { - groups: vec![], delegate, group_controller: None, } } + pub(crate) async fn groups(&self) -> Vec { + if let Some(group_action_handler) = self.group_controller.as_ref() { + group_action_handler.read().await.groups() + } else { + vec![] + } + } + pub(crate) async fn load_groups( &mut self, field_revs: &[Arc], @@ -44,10 +52,7 @@ impl GroupService { .build_groups(&field_type, &field_rev, row_revs, configuration) .await { - Ok(groups) => { - self.groups = groups.clone(); - Some(groups) - } + Ok(groups) => Some(groups), Err(_) => None, } } @@ -183,7 +188,7 @@ impl GroupService { if let Some(group_action_handler) = self.group_controller.as_ref() { let mut write_guard = group_action_handler.write().await; let _ = write_guard.group_rows(&row_revs, field_rev)?; - groups = write_guard.build_groups(); + groups = write_guard.groups(); drop(write_guard); } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs index 3830d7f1fe..3aa22cc488 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs @@ -56,7 +56,7 @@ pub struct GridRowTest { impl GridRowTest { pub async fn new() -> Self { - let editor_test = GridEditorTest::new().await; + let editor_test = GridEditorTest::new_table().await; Self { inner: editor_test } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/script.rs index 4def72696d..670ba6327c 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/script.rs @@ -11,7 +11,7 @@ pub struct GridCellTest { impl GridCellTest { pub async fn new() -> Self { - let inner = GridEditorTest::new().await; + let inner = GridEditorTest::new_table().await; Self { inner } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs index 6d910f3516..ebe3d3adf2 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs @@ -26,7 +26,7 @@ pub struct GridFieldTest { impl GridFieldTest { pub async fn new() -> Self { - let editor_test = GridEditorTest::new().await; + let editor_test = GridEditorTest::new_table().await; Self { inner: editor_test } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index cfbc8c8926..d629b78fb0 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -36,7 +36,7 @@ pub struct GridFilterTest { impl GridFilterTest { pub async fn new() -> Self { - let editor_test = GridEditorTest::new().await; + let editor_test = GridEditorTest::new_table().await; Self { inner: editor_test } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs index a83c3121a5..7300c524bb 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -36,12 +36,25 @@ pub struct GridEditorTest { } impl GridEditorTest { - pub async fn new() -> Self { + pub async fn new_table() -> Self { + Self::new(GridLayout::Table).await + } + + pub async fn new_board() -> Self { + Self::new(GridLayout::Board).await + } + + pub async fn new(layout: GridLayout) -> Self { let sdk = FlowySDKTest::default(); let _ = sdk.init_user().await; let build_context = make_test_grid(); let view_data: Bytes = build_context.into(); - let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await; + + let test = match layout { + GridLayout::Table => ViewTest::new_grid_view(&sdk, view_data.to_vec()).await, + GridLayout::Board => ViewTest::new_board_view(&sdk, view_data.to_vec()).await, + }; + let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap(); let field_revs = editor.get_field_revs(None).await.unwrap(); let block_meta_revs = editor.get_block_meta_revs().await.unwrap(); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs index 1e31e92a96..63d424afaf 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs @@ -1 +1,2 @@ mod script; +mod test; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs index f338770324..7c3bc3b629 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs @@ -1,9 +1,23 @@ use crate::grid::grid_editor::GridEditorTest; -use flowy_grid::entities::MoveRowParams; +use flowy_grid::entities::{GroupPB, MoveRowParams, RowPB}; pub enum GroupScript { - MoveCard { from_row_id: String, to_row_id: String }, + AssertGroup { + group_index: usize, + row_count: usize, + }, AssertGroupCount(usize), + AssertGroupRow { + group_index: usize, + row_index: usize, + row: RowPB, + }, + MoveRow { + from_group_index: usize, + from_row_index: usize, + to_group_index: usize, + to_row_index: usize, + }, } pub struct GridGroupTest { @@ -12,7 +26,7 @@ pub struct GridGroupTest { impl GridGroupTest { pub async fn new() -> Self { - let editor_test = GridEditorTest::new().await; + let editor_test = GridEditorTest::new_board().await; Self { inner: editor_test } } @@ -24,19 +38,48 @@ impl GridGroupTest { pub async fn run_script(&mut self, script: GroupScript) { match script { - GroupScript::MoveCard { from_row_id, to_row_id } => { - let params = MoveRowParams { - view_id: self.inner.grid_id.clone(), - from_row_id, - to_row_id, - }; - let _ = self.editor.move_row(params).await.unwrap(); + GroupScript::AssertGroup { group_index, row_count } => { + assert_eq!(row_count, self.group_at_index(group_index).await.rows.len()); } GroupScript::AssertGroupCount(count) => { + let groups = self.editor.load_groups().await.unwrap(); + assert_eq!(count, groups.len()); + } + GroupScript::MoveRow { + from_group_index, + from_row_index, + to_group_index, + to_row_index, + } => { + let groups: Vec = self.editor.load_groups().await.unwrap().items; + let from_row = groups.get(from_group_index).unwrap().rows.get(from_row_index).unwrap(); + let to_row = groups.get(to_group_index).unwrap().rows.get(to_row_index).unwrap(); + let params = MoveRowParams { + view_id: self.inner.grid_id.clone(), + from_row_id: from_row.id.clone(), + to_row_id: to_row.id.clone(), + }; + + self.editor.move_row(params).await.unwrap(); + } + GroupScript::AssertGroupRow { + group_index, + row_index, + row, + } => { // + let group = self.group_at_index(group_index).await; + let compare_row = group.rows.get(row_index).unwrap().clone(); + + assert_eq!(row.id, compare_row.id); } } } + + pub async fn group_at_index(&self, index: usize) -> GroupPB { + let groups = self.editor.load_groups().await.unwrap().items; + groups.get(index).unwrap().clone() + } } impl std::ops::Deref for GridGroupTest { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs new file mode 100644 index 0000000000..f568dfb816 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs @@ -0,0 +1,51 @@ +use crate::grid::group_test::script::GridGroupTest; +use crate::grid::group_test::script::GroupScript::*; + +#[tokio::test] +async fn board_init_test() { + let mut test = GridGroupTest::new().await; + let scripts = vec![ + AssertGroupCount(3), + AssertGroup { + group_index: 0, + row_count: 2, + }, + AssertGroup { + group_index: 1, + row_count: 2, + }, + AssertGroup { + group_index: 2, + row_count: 1, + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn board_move_row_test() { + let mut test = GridGroupTest::new().await; + let group = test.group_at_index(0).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + AssertGroup { + group_index: 0, + row_count: 1, + }, + AssertGroup { + group_index: 1, + row_count: 3, + }, + AssertGroupRow { + group_index: 1, + row_index: 1, + row: group.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index d997d71be4..3fb08e484a 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -184,7 +184,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { &self, user_id: &str, view_id: &str, - sub_data_type: ViewLayoutTypePB, + _sub_data_type: ViewLayoutTypePB, ) -> FutureResult { let user_id = user_id.to_string(); let view_id = view_id.to_string(); diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index f563f4b6fc..edb6ef37e5 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -275,7 +275,7 @@ impl std::default::Default for GridBlockRevisionPad { #[cfg(test)] mod tests { use crate::client_grid::GridBlockRevisionPad; - use flowy_grid_data_model::revision::{RowMetaChangeset, RowRevision}; + use flowy_grid_data_model::revision::{RowChangeset, RowRevision}; use lib_ot::core::TextDelta; use std::borrow::Cow; @@ -400,7 +400,7 @@ mod tests { visibility: false, }; - let changeset = RowMetaChangeset { + let changeset = RowChangeset { row_id: row.id.clone(), height: Some(100), visibility: Some(true), From 3a7c3815b02e14f3235a0aa8cd71c93e73de765d Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 21:52:47 +0800 Subject: [PATCH 09/10] chore: fix test error --- frontend/app_flowy/pubspec.lock | 2 +- frontend/rust-lib/flowy-folder/src/manager.rs | 2 +- .../flowy-folder/tests/workspace/folder_test.rs | 12 ++++++------ .../flowy-sdk/src/deps_resolve/folder_deps.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index 0348536cb8..0f9421a563 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -35,7 +35,7 @@ packages: path: "packages/appflowy_editor" relative: true source: path - version: "0.0.1" + version: "0.0.2" args: dependency: transitive description: diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 69d1f618d5..008476a397 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -261,7 +261,7 @@ pub trait ViewDataProcessor { &self, user_id: &str, view_id: &str, - sub_data_type: ViewLayoutTypePB, + layout: ViewLayoutTypePB, ) -> FutureResult; fn create_view_from_delta_data( diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs index 9872641d9a..068619f785 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs @@ -136,13 +136,13 @@ async fn app_create_with_view() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id), ]) @@ -202,13 +202,13 @@ async fn view_delete_all() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id.clone()), ]) @@ -237,7 +237,7 @@ async fn view_delete_all_permanent() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id.clone()), ]) @@ -337,7 +337,7 @@ async fn folder_sync_revision_with_new_view() { name: view_name.clone(), desc: view_desc.clone(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutTypePB::Grid, }, AssertCurrentRevId(3), AssertNextSyncRevId(Some(3)), diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index 3fb08e484a..150ff831a2 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -184,7 +184,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { &self, user_id: &str, view_id: &str, - _sub_data_type: ViewLayoutTypePB, + layout: ViewLayoutTypePB, ) -> FutureResult { let user_id = user_id.to_string(); let view_id = view_id.to_string(); From da485c6df9800a2ebb1793d611c265a4e88413bc Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 18 Aug 2022 23:12:26 +0800 Subject: [PATCH 10/10] chore: add more test --- .../src/services/view/controller.rs | 19 ------- .../tests/workspace/folder_test.rs | 8 --- .../flowy-folder/tests/workspace/script.rs | 12 ++--- .../flowy-grid/src/services/block_manager.rs | 8 ++- .../group/group_generator/group_controller.rs | 4 ++ .../group_generator/select_option_group.rs | 27 ++++++---- .../flowy-grid/tests/grid/group_test/test.rs | 50 +++++++++++++++++++ .../flowy-revision/src/rev_persistence.rs | 4 +- .../flowy-sdk/src/deps_resolve/folder_deps.rs | 1 + frontend/rust-lib/flowy-test/src/helper.rs | 11 ++-- .../src/revision/grid_block.rs | 2 +- 11 files changed, 85 insertions(+), 61 deletions(-) diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 8ad370916e..ab0783cec0 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -19,7 +19,6 @@ use flowy_database::kv::KV; use flowy_folder_data_model::revision::{gen_view_id, ViewRevision}; use flowy_sync::entities::text_block::TextBlockIdPB; use futures::{FutureExt, StreamExt}; -use lib_infra::util::timestamp; use std::{collections::HashSet, sync::Arc}; const LATEST_VIEW_ID: &str = "latest_view_id"; @@ -453,24 +452,6 @@ async fn handle_trash_event( } } -fn make_view_rev_from(params: CreateViewParams) -> ViewRevision { - let time = timestamp(); - ViewRevision { - id: params.view_id, - app_id: params.belong_to_id, - name: params.name, - desc: params.desc, - data_type: params.data_type.into(), - version: 0, - belongings: vec![], - modified_time: time, - create_time: time, - ext_data: "".to_string(), - thumbnail: params.thumbnail, - layout: params.layout.into(), - } -} - fn get_data_processor( data_processors: ViewDataProcessorMap, data_type: &ViewDataTypePB, diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs index 068619f785..33564c923d 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs @@ -1,8 +1,6 @@ use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest}; use flowy_folder::entities::view::ViewDataTypePB; use flowy_folder::entities::workspace::CreateWorkspacePayloadPB; -use flowy_folder::entities::ViewLayoutTypePB; - use flowy_revision::disk::RevisionState; use flowy_test::{event_builder::*, FlowySDKTest}; @@ -136,13 +134,11 @@ async fn app_create_with_view() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Grid, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, - layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id), ]) @@ -202,13 +198,11 @@ async fn view_delete_all() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Grid, }, CreateView { name: "Grid".to_owned(), desc: "Grid description".to_owned(), data_type: ViewDataTypePB::Database, - layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id.clone()), ]) @@ -237,7 +231,6 @@ async fn view_delete_all_permanent() { name: "View A".to_owned(), desc: "View A description".to_owned(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Grid, }, ReadApp(app.id.clone()), ]) @@ -337,7 +330,6 @@ async fn folder_sync_revision_with_new_view() { name: view_name.clone(), desc: view_desc.clone(), data_type: ViewDataTypePB::Text, - layout: ViewLayoutTypePB::Grid, }, AssertCurrentRevId(3), AssertNextSyncRevId(Some(3)), diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs index 2c53d5e2a4..74b90ce654 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/script.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/script.rs @@ -53,7 +53,6 @@ pub enum FolderScript { name: String, desc: String, data_type: ViewDataTypePB, - layout: ViewLayoutTypePB, }, AssertView(ViewPB), ReadView(String), @@ -181,12 +180,11 @@ impl FolderTest { delete_app(sdk, &self.app.id).await; } - FolderScript::CreateView { - name, - desc, - data_type, - layout, - } => { + FolderScript::CreateView { name, desc, data_type } => { + let layout = match data_type { + ViewDataTypePB::Text => ViewLayoutTypePB::Document, + ViewDataTypePB::Database => ViewLayoutTypePB::Grid, + }; let view = create_view(sdk, &self.app.id, &name, &desc, data_type, layout).await; self.view = view; } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index 3d31f99676..1bc9b9dc42 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -110,8 +110,7 @@ impl GridBlockManager { None => tracing::error!("Internal error: can't find the row with id: {}", changeset.row_id), Some(row_rev) => { let row_pb = make_row_from_row_rev(row_rev.clone()); - let block_order_changeset = - GridBlockChangesetPB::update(&editor.block_id, vec![row_pb]); + let block_order_changeset = GridBlockChangesetPB::update(&editor.block_id, vec![row_pb]); let _ = self .notify_did_update_block(&editor.block_id, block_order_changeset) .await?; @@ -189,10 +188,9 @@ impl GridBlockManager { } } - pub async fn update_cell(&self, changeset: CellChangesetPB ) -> FlowyResult<()> - { + pub async fn update_cell(&self, changeset: CellChangesetPB) -> FlowyResult<()> { let row_changeset: RowChangeset = changeset.clone().into(); - let _ = self.update_row(row_changeset, ).await?; + let _ = self.update_row(row_changeset).await?; self.notify_did_update_cell(changeset).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index 05924bcfef..de9d93bba1 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -149,6 +149,10 @@ impl Group { pub fn index_of_row(&self, row_id: &str) -> Option { self.rows.iter().position(|row| row.id == row_id) } + + pub fn number_of_row(&self) -> usize { + self.rows.len() + } } impl GenericGroupController diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 625f1fa643..029c64b578 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -249,27 +249,34 @@ fn move_row( ) { cell_data.select_options.iter().for_each(|option| { // Remove the row in which group contains the row - if option.id == group.id && group.contains_row(&row_rev.id) { + let is_group_contains = group.contains_row(&row_rev.id); + let to_index = group.index_of_row(to_row_id); + + if option.id == group.id && is_group_contains { group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); group.remove_row(&row_rev.id); } // Find the inserted group - if let Some(index) = group.index_of_row(to_row_id) { + if let Some(to_index) = to_index { let row_pb = RowPB::from(row_rev); let inserted_row = InsertedRowPB { row: row_pb.clone(), - index: Some(index as i32), + index: Some(to_index as i32), }; group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); - group.insert_row(index, row_pb); - - // If the inserted row comes from other group, it needs to update the corresponding cell content. - if option.id != group.id { - // Update the corresponding row's cell content. - let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); - row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); + if group.number_of_row() == to_index { + group.add_row(row_pb); + } else { + group.insert_row(to_index, row_pb); } } + + // If the inserted row comes from other group, it needs to update the corresponding cell content. + if to_index.is_some() && option.id != group.id { + // Update the corresponding row's cell content. + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); + } }); } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs index f568dfb816..317c852b5d 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs @@ -24,6 +24,30 @@ async fn board_init_test() { #[tokio::test] async fn board_move_row_test() { + let mut test = GridGroupTest::new().await; + let group = test.group_at_index(0).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 0, + to_row_index: 1, + }, + AssertGroup { + group_index: 0, + row_count: 2, + }, + AssertGroupRow { + group_index: 0, + row_index: 1, + row: group.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn board_move_row_to_other_group_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -49,3 +73,29 @@ async fn board_move_row_test() { ]; test.run_scripts(scripts).await; } + +#[tokio::test] +async fn board_move_row_to_other_group_and_reorder_test() { + let mut test = GridGroupTest::new().await; + let group = test.group_at_index(0).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + MoveRow { + from_group_index: 1, + from_row_index: 1, + to_group_index: 1, + to_row_index: 2, + }, + AssertGroupRow { + group_index: 1, + row_index: 2, + row: group.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs index cf672368ed..2124598400 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs @@ -320,9 +320,7 @@ impl RevisionSyncSequence { fn compact(&self) -> Option<(RevisionRange, VecDeque)> { // Make sure there are two rev_id going to sync. No need to compact if there is only // one rev_id in queue. - if self.next_rev_id().is_none() { - return None; - } + self.next_rev_id()?; let mut new_seq = self.0.clone(); let mut drained = new_seq.drain(1..).collect::>(); diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index 150ff831a2..0dc51c1a09 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -186,6 +186,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { view_id: &str, layout: ViewLayoutTypePB, ) -> FutureResult { + debug_assert_eq!(layout, ViewLayoutTypePB::Document); let user_id = user_id.to_string(); let view_id = view_id.to_string(); let manager = self.0.clone(); diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index e55b4fdbeb..ef530b3888 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -25,16 +25,11 @@ pub struct ViewTest { impl ViewTest { #[allow(dead_code)] - pub async fn new( - sdk: &FlowySDKTest, - data_type: ViewDataTypePB, - sub_data_type: ViewLayoutTypePB, - data: Vec, - ) -> Self { + pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataTypePB, layout: ViewLayoutTypePB, data: Vec) -> Self { let workspace = create_workspace(sdk, "Workspace", "").await; open_workspace(sdk, &workspace.id).await; let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; - let view = create_view(sdk, &app.id, data_type, sub_data_type, data).await; + let view = create_view(sdk, &app.id, data_type, layout, data).await; Self { sdk: sdk.clone(), workspace, @@ -52,7 +47,7 @@ impl ViewTest { } pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self { - Self::new(sdk, ViewDataTypePB::Text, ViewLayoutTypePB::Grid, vec![]).await + Self::new(sdk, ViewDataTypePB::Text, ViewLayoutTypePB::Document, vec![]).await } } diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs index 99737dc4d6..5464d83877 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs @@ -55,7 +55,7 @@ impl RowChangeset { row_id, height: None, visibility: None, - cell_by_field_id: Default::default() + cell_by_field_id: Default::default(), } }