From ed10ebac7a89e019406499c1c98bbb30acabe104 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 9 Apr 2022 20:45:33 +0800 Subject: [PATCH 1/9] fix: add new select option tag from textfield --- .../grid/cell_bloc/selection_editor_bloc.dart | 14 ++- .../workspace/application/grid/grid_bloc.dart | 45 +------- .../application/grid/row/row_service.dart | 32 +++++- .../plugins/grid/src/grid_page.dart | 1 + .../cell/selection_cell/extension.dart | 96 ----------------- .../cell/selection_cell/selection_editor.dart | 5 +- .../cell/selection_cell/text_field.dart | 101 ++++++++++++++++++ .../type_options/selection_type_option.rs | 61 +++++------ 8 files changed, 174 insertions(+), 181 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index d2606b0fdb..5b6ba78bd5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -110,7 +110,7 @@ class SelectOptionEditorBloc extends Bloc add(SelectOptionEditorEvent.didReceiveOptions( - selectOptionContext.options, - selectOptionContext.selectOptions, - )), + (selectOptionContext) { + if (!isClosed) { + add(SelectOptionEditorEvent.didReceiveOptions( + selectOptionContext.options, + selectOptionContext.selectOptions, + )); + } + }, (err) => Log.error(err), ); }, diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 01db1f1300..33d3cbe40c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; @@ -6,7 +7,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:equatable/equatable.dart'; import 'grid_block_service.dart'; import 'field/grid_listenr.dart'; import 'grid_service.dart'; @@ -154,46 +154,3 @@ class GridLoadingState with _$GridLoadingState { const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.finish(Either successOrFail) = _Finish; } - -class GridBlockRow { - final String gridId; - final String rowId; - final String blockId; - final double height; - - const GridBlockRow({ - required this.gridId, - required this.rowId, - required this.blockId, - required this.height, - }); -} - -class RowData extends Equatable { - final String gridId; - final String rowId; - final String blockId; - final List fields; - final double height; - - const RowData({ - required this.gridId, - required this.rowId, - required this.blockId, - required this.fields, - required this.height, - }); - - factory RowData.fromBlockRow(GridBlockRow row, List fields) { - return RowData( - gridId: row.gridId, - rowId: row.rowId, - blockId: row.blockId, - fields: fields, - height: row.height, - ); - } - - @override - List get props => [rowId, fields]; -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 72c25e022b..7ed5477364 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -1,5 +1,4 @@ import 'package:dartz/dartz.dart'; -import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; @@ -41,3 +40,34 @@ class CellData with _$CellData { Cell? cell, }) = _CellData; } + +@freezed +class RowData with _$RowData { + const factory RowData({ + required String gridId, + required String rowId, + required String blockId, + required List fields, + required double height, + }) = _RowData; + + factory RowData.fromBlockRow(GridBlockRow row, List fields) { + return RowData( + gridId: row.gridId, + rowId: row.rowId, + blockId: row.blockId, + fields: fields, + height: row.height, + ); + } +} + +@freezed +class GridBlockRow with _$GridBlockRow { + const factory GridBlockRow({ + required String gridId, + required String rowId, + required String blockId, + required double height, + }) = _GridBlockRow; +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 936ad68c44..5de9cc75a6 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index d94e11dde0..bdf4d01158 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -1,6 +1,3 @@ -import 'dart:collection'; - -import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; @@ -8,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:textfield_tags/textfield_tags.dart'; extension SelectOptionColorExtension on SelectOptionColor { Color make(BuildContext context) { @@ -63,98 +59,6 @@ extension SelectOptionColorExtension on SelectOptionColor { } } -class SelectOptionTextField extends StatelessWidget { - final FocusNode _focusNode; - final TextEditingController _controller; - final TextfieldTagsController tagController; - final List options; - final LinkedHashMap selectedOptionMap; - - final double distanceToText; - - final Function(String) onNewTag; - - SelectOptionTextField({ - required this.options, - required this.selectedOptionMap, - required this.distanceToText, - required this.tagController, - required this.onNewTag, - TextEditingController? controller, - FocusNode? focusNode, - Key? key, - }) : _controller = controller ?? TextEditingController(), - _focusNode = focusNode ?? FocusNode(), - super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - - return TextFieldTags( - textEditingController: _controller, - textfieldTagsController: tagController, - initialTags: selectedOptionMap.keys.toList(), - focusNode: _focusNode, - textSeparators: const [' ', ','], - inputfieldBuilder: (BuildContext context, editController, focusNode, error, onChanged, onSubmitted) { - return ((context, sc, tags, onTagDelegate) { - tags.retainWhere((name) { - return options.where((option) => option.name == name).isEmpty; - }); - if (tags.isNotEmpty) { - assert(tags.length == 1); - onNewTag(tags.first); - } - - return TextField( - autofocus: true, - controller: editController, - focusNode: focusNode, - onChanged: onChanged, - onSubmitted: onSubmitted, - maxLines: 1, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), - decoration: InputDecoration( - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: theme.main1, width: 1.0), - borderRadius: Corners.s10Border, - ), - isDense: true, - prefixIcon: _renderTags(sc), - hintText: LocaleKeys.grid_selectOption_searchOption.tr(), - prefixIconConstraints: BoxConstraints(maxWidth: distanceToText), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: theme.main1, - width: 1.0, - ), - borderRadius: Corners.s10Border, - ), - ), - ); - }); - }, - ); - } - - Widget? _renderTags(ScrollController sc) { - if (selectedOptionMap.isEmpty) { - return null; - } - - final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList(); - return Padding( - padding: const EdgeInsets.all(8.0), - child: SingleChildScrollView( - controller: sc, - scrollDirection: Axis.horizontal, - child: Row(children: children), - ), - ); - } -} - class SelectOptionTag extends StatelessWidget { final SelectOption option; final bool isSelected; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 1685473a65..ebaabbfb0b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -1,5 +1,4 @@ import 'dart:collection'; - import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; @@ -21,6 +20,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:textfield_tags/textfield_tags.dart'; import 'extension.dart'; +import 'text_field.dart'; const double _editorPannelWidth = 300; @@ -135,8 +135,7 @@ class _TextField extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocConsumer( - listener: (context, state) {}, + return BlocBuilder( builder: (context, state) { final optionMap = LinkedHashMap.fromIterable(state.selectedOptions, key: (option) => option.name, value: (option) => option); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart new file mode 100644 index 0000000000..e7f4e98851 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart @@ -0,0 +1,101 @@ +import 'dart:collection'; + +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:textfield_tags/textfield_tags.dart'; + +import 'extension.dart'; + +class SelectOptionTextField extends StatelessWidget { + final FocusNode _focusNode; + final TextEditingController _controller; + final TextfieldTagsController tagController; + final List options; + final LinkedHashMap selectedOptionMap; + + final double distanceToText; + + final Function(String) onNewTag; + + SelectOptionTextField({ + required this.options, + required this.selectedOptionMap, + required this.distanceToText, + required this.tagController, + required this.onNewTag, + TextEditingController? controller, + FocusNode? focusNode, + Key? key, + }) : _controller = controller ?? TextEditingController(), + _focusNode = focusNode ?? FocusNode(), + super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return TextFieldTags( + textEditingController: _controller, + textfieldTagsController: tagController, + initialTags: selectedOptionMap.keys.toList(), + focusNode: _focusNode, + textSeparators: const [' ', ','], + inputfieldBuilder: (BuildContext context, editController, focusNode, error, onChanged, onSubmitted) { + return ((context, sc, tags, onTagDelegate) { + return TextField( + autofocus: true, + controller: editController, + focusNode: focusNode, + onChanged: onChanged, + onSubmitted: (text) { + if (onSubmitted != null) { + onSubmitted(text); + } + + if (text.isNotEmpty) { + onNewTag(text); + } + }, + maxLines: 1, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: theme.main1, width: 1.0), + borderRadius: Corners.s10Border, + ), + isDense: true, + prefixIcon: _renderTags(sc), + hintText: LocaleKeys.grid_selectOption_searchOption.tr(), + prefixIconConstraints: BoxConstraints(maxWidth: distanceToText), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: theme.main1, width: 1.0), + borderRadius: Corners.s10Border, + ), + ), + ); + }); + }, + ); + } + + Widget? _renderTags(ScrollController sc) { + if (selectedOptionMap.isEmpty) { + return null; + } + + final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList(); + return Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + controller: sc, + scrollDirection: Axis.horizontal, + child: Row(children: children), + ), + ); + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index bcf21972ce..30cd36b122 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -16,9 +16,28 @@ use std::str::FromStr; pub const SELECTION_IDS_SEPARATOR: &str = ","; pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync { - fn insert_option(&mut self, new_option: SelectOption); - fn delete_option(&mut self, delete_option: SelectOption); + fn insert_option(&mut self, new_option: SelectOption) { + let options = self.mut_options(); + if let Some(index) = options + .iter() + .position(|option| option.id == new_option.id || option.name == new_option.name) + { + options.remove(index); + options.insert(index, new_option); + } else { + options.insert(0, new_option); + } + } + + fn delete_option(&mut self, delete_option: SelectOption) { + let options = self.mut_options(); + if let Some(index) = options.iter().position(|option| option.id == delete_option.id) { + options.remove(index); + } + } + fn option_context(&self, cell_meta: &Option) -> SelectOptionContext; + fn mut_options(&mut self) -> &mut Vec; } // Single select @@ -33,21 +52,6 @@ pub struct SingleSelectTypeOption { impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl SelectOptionOperation for SingleSelectTypeOption { - fn insert_option(&mut self, new_option: SelectOption) { - if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) { - self.options.remove(index); - self.options.insert(index, new_option); - } else { - self.options.insert(0, new_option); - } - } - - fn delete_option(&mut self, delete_option: SelectOption) { - if let Some(index) = self.options.iter().position(|option| option.id == delete_option.id) { - self.options.remove(index); - } - } - fn option_context(&self, cell_meta: &Option) -> SelectOptionContext { let select_options = make_select_context_from(cell_meta, &self.options); SelectOptionContext { @@ -55,6 +59,10 @@ impl SelectOptionOperation for SingleSelectTypeOption { select_options, } } + + fn mut_options(&mut self) -> &mut Vec { + &mut self.options + } } impl CellDataOperation for SingleSelectTypeOption { @@ -139,21 +147,6 @@ impl MultiSelectTypeOption { } impl SelectOptionOperation for MultiSelectTypeOption { - fn insert_option(&mut self, new_option: SelectOption) { - if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) { - self.options.remove(index); - self.options.insert(index, new_option); - } else { - self.options.insert(0, new_option); - } - } - - fn delete_option(&mut self, delete_option: SelectOption) { - if let Some(index) = self.options.iter().position(|option| option.id == delete_option.id) { - self.options.remove(index); - } - } - fn option_context(&self, cell_meta: &Option) -> SelectOptionContext { let select_options = make_select_context_from(cell_meta, &self.options); SelectOptionContext { @@ -161,6 +154,10 @@ impl SelectOptionOperation for MultiSelectTypeOption { select_options, } } + + fn mut_options(&mut self) -> &mut Vec { + &mut self.options + } } impl CellDataOperation for MultiSelectTypeOption { From b93feb49c32aebdcee2902b2679bb7a604262422 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 9 Apr 2022 22:07:48 +0800 Subject: [PATCH 2/9] chore: config row action sheet --- .../app_flowy/assets/translations/en.json | 4 + .../app_flowy/lib/startup/deps_resolver.dart | 1 - ...bloc.dart => field_action_sheet_bloc.dart} | 28 ++-- .../workspace/application/grid/grid_bloc.dart | 1 - .../workspace/application/grid/prelude.dart | 2 +- .../grid/row/row_action_sheet_bloc.dart | 58 ++++++++ .../application/grid/row/row_bloc.dart | 52 +++---- .../application/grid/row/row_service.dart | 22 ++- .../plugins/grid/src/grid_page.dart | 30 ++-- .../plugins/grid/src/layout/sizes.dart | 2 +- .../header/field_cell_action_sheet.dart | 20 +-- .../grid/src/widgets/row/grid_row.dart | 36 ++++- .../src/widgets/row/row_action_sheet.dart | 133 ++++++++++++++++++ .../dart_event/flowy-grid/dart_event.dart | 34 +++++ .../protobuf/flowy-grid/event_map.pbenum.dart | 4 + .../protobuf/flowy-grid/event_map.pbjson.dart | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 16 +++ frontend/rust-lib/flowy-grid/src/event_map.rs | 8 ++ .../src/protobuf/model/event_map.rs | 13 +- .../src/protobuf/proto/event_map.proto | 2 + 20 files changed, 379 insertions(+), 91 deletions(-) rename frontend/app_flowy/lib/workspace/application/grid/field/{action_sheet_bloc.dart => field_action_sheet_bloc.dart} (67%) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 7e20a947dc..83a7826918 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -174,6 +174,10 @@ "addOption": "Add option", "editProperty": "Edit property" }, + "row": { + "duplicate": "Duplicate", + "delete": "Delete" + }, "selectOption": { "purpleColor": "Purple", "pinkColor": "Pink", diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index f54a7d0a27..5f69ab1ad4 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -154,7 +154,6 @@ void _resolveGridDeps(GetIt getIt) { getIt.registerFactoryParam( (data, _) => RowBloc( rowData: data, - rowlistener: RowListener(rowId: data.rowId), ), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart similarity index 67% rename from frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart index 5e8cb5a932..40ac699e7f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart @@ -5,14 +5,14 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'field_service.dart'; -part 'action_sheet_bloc.freezed.dart'; +part 'field_action_sheet_bloc.freezed.dart'; -class FieldActionSheetBloc extends Bloc { +class FieldActionSheetBloc extends Bloc { final FieldService service; FieldActionSheetBloc({required Field field, required this.service}) - : super(ActionSheetState.initial(EditFieldContext.create()..gridField = field)) { - on( + : super(FieldActionSheetState.initial(EditFieldContext.create()..gridField = field)) { + on( (event, emit) async { await event.map( updateFieldName: (_UpdateFieldName value) async { @@ -56,23 +56,23 @@ class FieldActionSheetBloc extends Bloc { } @freezed -class ActionSheetEvent with _$ActionSheetEvent { - const factory ActionSheetEvent.updateFieldName(String name) = _UpdateFieldName; - const factory ActionSheetEvent.hideField() = _HideField; - const factory ActionSheetEvent.duplicateField() = _DuplicateField; - const factory ActionSheetEvent.deleteField() = _DeleteField; - const factory ActionSheetEvent.saveField() = _SaveField; +class FieldActionSheetEvent with _$FieldActionSheetEvent { + const factory FieldActionSheetEvent.updateFieldName(String name) = _UpdateFieldName; + const factory FieldActionSheetEvent.hideField() = _HideField; + const factory FieldActionSheetEvent.duplicateField() = _DuplicateField; + const factory FieldActionSheetEvent.deleteField() = _DeleteField; + const factory FieldActionSheetEvent.saveField() = _SaveField; } @freezed -class ActionSheetState with _$ActionSheetState { - const factory ActionSheetState({ +class FieldActionSheetState with _$FieldActionSheetState { + const factory FieldActionSheetState({ required EditFieldContext editContext, required String errorText, required String fieldName, - }) = _ActionSheetState; + }) = _FieldActionSheetState; - factory ActionSheetState.initial(EditFieldContext editContext) => ActionSheetState( + factory FieldActionSheetState.initial(EditFieldContext editContext) => FieldActionSheetState( editContext: editContext, errorText: '', fieldName: editContext.gridField.name, diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 33d3cbe40c..a46136a6b5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -111,7 +111,6 @@ class GridBloc extends Bloc { rows.addAll(gridBlock.rowOrders.map( (rowOrder) => GridBlockRow( gridId: view.id, - blockId: gridBlock.id, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), ), diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index f941b01056..a795e23fb2 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -7,7 +7,7 @@ export 'data.dart'; // Field export 'field/field_service.dart'; export 'field/grid_header_bloc.dart'; -export 'field/action_sheet_bloc.dart'; +export 'field/field_action_sheet_bloc.dart'; export 'field/field_editor_bloc.dart'; export 'field/field_switch_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart new file mode 100644 index 0000000000..93ee70afa0 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart @@ -0,0 +1,58 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'row_action_sheet_bloc.freezed.dart'; + +class RowActionSheetBloc extends Bloc { + final RowService _rowService; + + RowActionSheetBloc({required RowData rowData}) + : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId), + super(RowActionSheetState.initial(rowData)) { + on( + (event, emit) async { + await event.map( + deleteRow: (_DeleteRow value) async { + final result = await _rowService.deleteRow(); + logResult(result); + }, + duplicateRow: (_DuplicateRow value) async { + final result = await _rowService.duplicateRow(); + logResult(result); + }, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } + + void logResult(Either result) { + result.fold((l) => null, (err) => Log.error(err)); + } +} + +@freezed +class RowActionSheetEvent with _$RowActionSheetEvent { + const factory RowActionSheetEvent.duplicateRow() = _DuplicateRow; + const factory RowActionSheetEvent.deleteRow() = _DeleteRow; +} + +@freezed +class RowActionSheetState with _$RowActionSheetState { + const factory RowActionSheetState({ + required RowData rowData, + }) = _RowActionSheetState; + + factory RowActionSheetState.initial(RowData rowData) => RowActionSheetState( + rowData: rowData, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 418cb23e88..6c0037d289 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -1,7 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; -import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -16,19 +15,14 @@ part 'row_bloc.freezed.dart'; typedef CellDataMap = LinkedHashMap; class RowBloc extends Bloc { - final RowService rowService; - final RowListener rowlistener; - final GridFieldsListener fieldListener; + final RowService _rowService; + final RowListener _rowlistener; + final GridFieldsListener _fieldListener; - RowBloc({required RowData rowData, required this.rowlistener}) - : rowService = RowService( - gridId: rowData.gridId, - blockId: rowData.blockId, - rowId: rowData.rowId, - ), - fieldListener = GridFieldsListener( - gridId: rowData.gridId, - ), + RowBloc({required RowData rowData}) + : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId), + _fieldListener = GridFieldsListener(gridId: rowData.gridId), + _rowlistener = RowListener(rowId: rowData.rowId), super(RowState.initial(rowData)) { on( (event, emit) async { @@ -38,7 +32,7 @@ class RowBloc extends Bloc { await _loadRow(emit); }, createRow: (_CreateRow value) { - rowService.createRow(); + _rowService.createRow(); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) async { await _handleFieldUpdate(emit, value); @@ -52,7 +46,7 @@ class RowBloc extends Bloc { } void _handleRowUpdate(_DidUpdateRow value, Emitter emit) { - final CellDataMap cellDataMap = _makeCellDatas(value.row, state.fields); + final CellDataMap cellDataMap = _makeCellDatas(value.row, state.rowData.fields); emit(state.copyWith( row: Future(() => Some(value.row)), cellDataMap: Some(cellDataMap), @@ -67,39 +61,39 @@ class RowBloc extends Bloc { ); emit(state.copyWith( - fields: value.fields, + rowData: state.rowData.copyWith(fields: value.fields), cellDataMap: Some(cellDataMap), )); } @override Future close() async { - await rowlistener.stop(); - await fieldListener.stop(); + await _rowlistener.stop(); + await _fieldListener.stop(); return super.close(); } Future _startListening() async { - rowlistener.updateRowNotifier.addPublishListener((result) { + _rowlistener.updateRowNotifier.addPublishListener((result) { result.fold( (row) => add(RowEvent.didUpdateRow(row)), (err) => Log.error(err), ); }); - fieldListener.updateFieldsNotifier.addPublishListener((result) { + _fieldListener.updateFieldsNotifier.addPublishListener((result) { result.fold( (fields) => add(RowEvent.didReceiveFieldUpdate(fields)), (err) => Log.error(err), ); }); - rowlistener.start(); - fieldListener.start(); + _rowlistener.start(); + _fieldListener.start(); } Future _loadRow(Emitter emit) async { - rowService.getRow().then((result) { + _rowService.getRow().then((result) { return result.fold( (row) => add(RowEvent.didUpdateRow(row)), (err) => Log.error(err), @@ -113,7 +107,7 @@ class RowBloc extends Bloc { if (field.visibility) { map[field.id] = CellData( rowId: row.id, - gridId: rowService.gridId, + gridId: _rowService.gridId, cell: row.cellByFieldId[field.id], field: field, ); @@ -134,17 +128,13 @@ class RowEvent with _$RowEvent { @freezed class RowState with _$RowState { const factory RowState({ - required String rowId, - required double rowHeight, - required List fields, + required RowData rowData, required Future> row, required Option cellDataMap, }) = _RowState; - factory RowState.initial(RowData data) => RowState( - rowId: data.rowId, - rowHeight: data.height, - fields: data.fields, + factory RowState.initial(RowData rowData) => RowState( + rowData: rowData, row: Future(() => none()), cellDataMap: none(), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 7ed5477364..f87d9f8574 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -10,9 +10,8 @@ part 'row_service.freezed.dart'; class RowService { final String gridId; final String rowId; - final String blockId; - RowService({required this.gridId, required this.rowId, required this.blockId}); + RowService({required this.gridId, required this.rowId}); Future> createRow() { CreateRowPayload payload = CreateRowPayload.create() @@ -29,6 +28,22 @@ class RowService { return GridEventGetRow(payload).send(); } + + Future> deleteRow() { + final payload = RowIdentifierPayload.create() + ..gridId = gridId + ..rowId = rowId; + + return GridEventDeleteRow(payload).send(); + } + + Future> duplicateRow() { + final payload = RowIdentifierPayload.create() + ..gridId = gridId + ..rowId = rowId; + + return GridEventDuplicateRow(payload).send(); + } } @freezed @@ -46,7 +61,6 @@ class RowData with _$RowData { const factory RowData({ required String gridId, required String rowId, - required String blockId, required List fields, required double height, }) = _RowData; @@ -55,7 +69,6 @@ class RowData with _$RowData { return RowData( gridId: row.gridId, rowId: row.rowId, - blockId: row.blockId, fields: fields, height: row.height, ); @@ -67,7 +80,6 @@ class GridBlockRow with _$GridBlockRow { const factory GridBlockRow({ required String gridId, required String rowId, - required String blockId, required double height, }) = _GridBlockRow; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 5de9cc75a6..b96b89ba2e 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -73,6 +73,7 @@ class FlowyGrid extends StatefulWidget { class _FlowyGridState extends State { final _scrollController = GridScrollController(); + final _key = GlobalKey(); @override void dispose() { @@ -91,6 +92,7 @@ class _FlowyGridState extends State { return const Center(child: CircularProgressIndicator.adaptive()); } +// _key.currentState.insertItem(index) final child = BlocBuilder( builder: (context, state) { return SizedBox( @@ -153,20 +155,24 @@ class _FlowyGridState extends State { return rowChanged; }, builder: (context, state) { - return SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - final blockRow = context.read().state.rows[index]; - final fields = context.read().state.fields; - final rowData = RowData.fromBlockRow(blockRow, fields); - return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)); - }, - childCount: context.read().state.rows.length, - addRepaintBoundaries: true, - addAutomaticKeepAlives: true, - ), + return SliverAnimatedList( + key: _key, + initialItemCount: context.read().state.rows.length, + itemBuilder: (BuildContext context, int index, Animation animation) { + final blockRow = context.read().state.rows[index]; + final fields = context.read().state.fields; + final rowData = RowData.fromBlockRow(blockRow, fields); + return _renderRow(rowData, animation); + }, ); }, ); } + + Widget _renderRow(RowData rowData, Animation animation) { + return SizeTransition( + sizeFactor: animation, + child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)), + ); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart index 23a541e610..8dc0b20263 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart @@ -6,7 +6,7 @@ class GridSize { static double get scrollBarSize => 12 * scale; static double get headerHeight => 40 * scale; static double get footerHeight => 40 * scale; - static double get leadingHeaderPadding => 30 * scale; + static double get leadingHeaderPadding => 50 * scale; static double get trailHeaderPadding => 140 * scale; static double get headerContainerPadding => 0 * scale; static double get cellHPadding => 10 * scale; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart index 42d49b69fe..2dc1e2976b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart @@ -23,7 +23,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate child: this, constraints: BoxConstraints.loose(const Size(240, 200)), ), - identifier: identifier(), + identifier: GridFieldCellActionSheet.identifier(), anchorContext: overlayContext, anchorDirection: AnchorDirection.bottomWithLeftAligned, delegate: this, @@ -68,7 +68,7 @@ class _EditFieldButton extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); - return BlocBuilder( + return BlocBuilder( builder: (context, state) { return SizedBox( height: GridSize.typeOptionItemHeight, @@ -100,16 +100,6 @@ class _FieldOperationList extends StatelessWidget { ) .toList(); - return FieldOperationList(actions: actions); - } -} - -class FieldOperationList extends StatelessWidget { - final List actions; - const FieldOperationList({required this.actions, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { return GridView( // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html shrinkWrap: true, @@ -182,13 +172,13 @@ extension _FieldActionExtension on FieldAction { void run(BuildContext context) { switch (this) { case FieldAction.hide: - context.read().add(const ActionSheetEvent.hideField()); + context.read().add(const FieldActionSheetEvent.hideField()); break; case FieldAction.duplicate: - context.read().add(const ActionSheetEvent.duplicateField()); + context.read().add(const FieldActionSheetEvent.duplicateField()); break; case FieldAction.delete: - context.read().add(const ActionSheetEvent.deleteField()); + context.read().add(const FieldActionSheetEvent.deleteField()); break; } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index 08d68f197a..a5b6a405a6 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -5,10 +5,13 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/p import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; +import 'row_action_sheet.dart'; + class GridRowWidget extends StatefulWidget { final RowData data; const GridRowWidget({required this.data, Key? key}) : super(key: key); @@ -39,10 +42,10 @@ class _GridRowWidgetState extends State { onEnter: (p) => _rowStateNotifier.onEnter = true, onExit: (p) => _rowStateNotifier.onEnter = false, child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, + buildWhen: (p, c) => p.rowData.height != c.rowData.height, builder: (context, state) { return SizedBox( - height: _rowBloc.state.rowHeight, + height: _rowBloc.state.rowData.height, child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: const [ @@ -83,7 +86,8 @@ class _RowLeading extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.center, children: const [ - AppendRowButton(), + _InsertRowButton(), + _DeleteRowButton(), ], ); } @@ -98,15 +102,16 @@ class _RowTrailing extends StatelessWidget { } } -class AppendRowButton extends StatelessWidget { - const AppendRowButton({Key? key}) : super(key: key); +class _InsertRowButton extends StatelessWidget { + const _InsertRowButton({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); return FlowyIconButton( hoverColor: theme.hover, - width: 22, + width: 20, + height: 30, onPressed: () => context.read().add(const RowEvent.createRow()), iconPadding: const EdgeInsets.all(3), icon: svgWidget("home/add"), @@ -114,6 +119,25 @@ class AppendRowButton extends StatelessWidget { } } +class _DeleteRowButton extends StatelessWidget { + const _DeleteRowButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyIconButton( + hoverColor: theme.hover, + width: 20, + height: 30, + onPressed: () => GridRowActionSheet( + rowData: context.read().state.rowData, + ).show(context), + iconPadding: const EdgeInsets.all(3), + icon: svgWidget("editor/details"), + ); + } +} + class _RowCells extends StatelessWidget { const _RowCells({Key? key}) : super(key: key); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart new file mode 100644 index 0000000000..f1ff46af08 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart @@ -0,0 +1,133 @@ +import 'package:app_flowy/workspace/application/grid/row/row_action_sheet_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class GridRowActionSheet extends StatelessWidget { + final RowData rowData; + const GridRowActionSheet({required this.rowData, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => RowActionSheetBloc(rowData: rowData), + child: BlocBuilder( + builder: (context, state) { + final cells = _RowAction.values + .map( + (action) => _RowActionCell( + action: action, + onDismissed: () => remove(context), + ), + ) + .toList(); + + // + final list = ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + itemCount: cells.length, + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ); + return list; + }, + ), + ); + } + + void show(BuildContext overlayContext) { + FlowyOverlay.of(overlayContext).insertWithAnchor( + widget: OverlayContainer( + child: this, + constraints: BoxConstraints.loose(const Size(140, 200)), + ), + identifier: GridRowActionSheet.identifier(), + anchorContext: overlayContext, + anchorDirection: AnchorDirection.leftWithCenterAligned, + ); + } + + void remove(BuildContext overlayContext) { + FlowyOverlay.of(overlayContext).remove(GridRowActionSheet.identifier()); + } + + static String identifier() { + return (GridRowActionSheet).toString(); + } +} + +class _RowActionCell extends StatelessWidget { + final _RowAction action; + final VoidCallback onDismissed; + const _RowActionCell({required this.action, required this.onDismissed, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(action.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + action.performAction(context); + onDismissed(); + }, + leftIcon: svgWidget(action.iconName(), color: theme.iconColor), + ), + ); + } +} + +enum _RowAction { + delete, + duplicate, +} + +extension _RowActionExtension on _RowAction { + String iconName() { + switch (this) { + case _RowAction.duplicate: + return 'grid/duplicate'; + case _RowAction.delete: + return 'grid/delete'; + } + } + + String title() { + switch (this) { + case _RowAction.duplicate: + return LocaleKeys.grid_row_duplicate.tr(); + case _RowAction.delete: + return LocaleKeys.grid_row_delete.tr(); + } + } + + void performAction(BuildContext context) { + switch (this) { + case _RowAction.duplicate: + // context.read().add(const RowActionSheetEvent.duplicateRow()); + break; + case _RowAction.delete: + // context.read().add(const RowActionSheetEvent.deleteRow()); + break; + } + } +} diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index a4871a6bef..8544bc6edd 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -239,6 +239,40 @@ class GridEventGetRow { } } +class GridEventDeleteRow { + RowIdentifierPayload request; + GridEventDeleteRow(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.DeleteRow.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + +class GridEventDuplicateRow { + RowIdentifierPayload request; + GridEventDuplicateRow(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.DuplicateRow.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventGetCell { CellIdentifierPayload request; GridEventGetCell(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 37032ec41b..5be5844119 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -24,6 +24,8 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent ApplySelectOptionChangeset = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset'); static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); + static const GridEvent DeleteRow = GridEvent._(52, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteRow'); + static const GridEvent DuplicateRow = GridEvent._(53, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateRow'); static const GridEvent GetCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCell'); static const GridEvent UpdateCell = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(72, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset'); @@ -43,6 +45,8 @@ class GridEvent extends $pb.ProtobufEnum { ApplySelectOptionChangeset, CreateRow, GetRow, + DeleteRow, + DuplicateRow, GetCell, UpdateCell, ApplySelectOptionCellChangeset, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index bc4b838bca..2f2921564b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -26,6 +26,8 @@ const GridEvent$json = const { const {'1': 'ApplySelectOptionChangeset', '2': 32}, const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, + const {'1': 'DeleteRow', '2': 52}, + const {'1': 'DuplicateRow', '2': 53}, const {'1': 'GetCell', '2': 70}, const {'1': 'UpdateCell', '2': 71}, const {'1': 'ApplySelectOptionCellChangeset', '2': 72}, @@ -33,4 +35,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 467c3e334b..d94753c4b0 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -179,6 +179,22 @@ pub(crate) async fn get_row_handler( } } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn delete_row_handler( + data: Data, + manager: AppData>, +) -> DataResult { + todo!() +} + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn duplicate_row_handler( + data: Data, + manager: AppData>, +) -> DataResult { + todo!() +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn create_row_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 8a4c68e468..7246cc7f4f 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -20,6 +20,8 @@ pub fn create(grid_manager: Arc) -> Module { // Row .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) + .event(GridEvent::DeleteRow, delete_row_handler) + .event(GridEvent::DuplicateRow, duplicate_row_handler) // Cell .event(GridEvent::GetCell, get_cell_handler) .event(GridEvent::UpdateCell, update_cell_handler) @@ -81,6 +83,12 @@ pub enum GridEvent { #[event(input = "RowIdentifierPayload", output = "Row")] GetRow = 51, + #[event(input = "RowIdentifierPayload")] + DeleteRow = 52, + + #[event(input = "RowIdentifierPayload")] + DuplicateRow = 53, + #[event(input = "CellIdentifierPayload", output = "Cell")] GetCell = 70, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index d9cfbac578..10bee819ce 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -39,6 +39,8 @@ pub enum GridEvent { ApplySelectOptionChangeset = 32, CreateRow = 50, GetRow = 51, + DeleteRow = 52, + DuplicateRow = 53, GetCell = 70, UpdateCell = 71, ApplySelectOptionCellChangeset = 72, @@ -65,6 +67,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { 32 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset), 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), + 52 => ::std::option::Option::Some(GridEvent::DeleteRow), + 53 => ::std::option::Option::Some(GridEvent::DuplicateRow), 70 => ::std::option::Option::Some(GridEvent::GetCell), 71 => ::std::option::Option::Some(GridEvent::UpdateCell), 72 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset), @@ -88,6 +92,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::ApplySelectOptionChangeset, GridEvent::CreateRow, GridEvent::GetRow, + GridEvent::DeleteRow, + GridEvent::DuplicateRow, GridEvent::GetCell, GridEvent::UpdateCell, GridEvent::ApplySelectOptionCellChangeset, @@ -119,15 +125,16 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xde\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xff\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x13\n\x0fNewSe\ lectOption\x10\x1e\x12\x1a\n\x16GetSelectOptionContext\x10\x1f\x12\x1e\n\ \x1aApplySelectOptionChangeset\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\ - \x06GetRow\x103\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\ - \"\n\x1eApplySelectOptionCellChangeset\x10Hb\x06proto3\ + \x06GetRow\x103\x12\r\n\tDeleteRow\x104\x12\x10\n\x0cDuplicateRow\x105\ + \x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\"\n\x1eApplySe\ + lectOptionCellChangeset\x10Hb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 1201bd759e..9fad8dd7b1 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -15,6 +15,8 @@ enum GridEvent { ApplySelectOptionChangeset = 32; CreateRow = 50; GetRow = 51; + DeleteRow = 52; + DuplicateRow = 53; GetCell = 70; UpdateCell = 71; ApplySelectOptionCellChangeset = 72; From d08f298fb6a2eb2ef1665fc9999958f1d152f4cb Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 9 Apr 2022 22:42:42 +0800 Subject: [PATCH 3/9] chore: rename structs --- frontend/rust-lib/flowy-grid/src/event_handler.rs | 14 ++++++++++---- .../flowy-grid/src/services/block_meta_manager.rs | 10 +++++----- .../flowy-grid/src/services/grid_editor.rs | 12 ++++++++++++ .../flowy-grid/src/services/row/row_loader.rs | 12 ++++++------ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index d94753c4b0..1ac3796059 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -183,16 +183,22 @@ pub(crate) async fn get_row_handler( pub(crate) async fn delete_row_handler( data: Data, manager: AppData>, -) -> DataResult { - todo!() +) -> Result<(), FlowyError> { + let params: RowIdentifier = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.delete_row(¶ms.row_id)?; + Ok(()) } #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn duplicate_row_handler( data: Data, manager: AppData>, -) -> DataResult { - todo!() +) -> Result<(), FlowyError> { + let params: RowIdentifier = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.duplicate_row(¶ms.row_id)?; + Ok(()) } #[tracing::instrument(level = "debug", skip(data, manager), err)] diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs index 104b6fbbdb..54e223c242 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -2,7 +2,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::ClientGridBlockMetaEditor; use crate::services::persistence::block_index::BlockIndexPersistence; -use crate::services::row::{make_block_row_ids, make_rows_from_row_metas, GridBlockSnapshot}; +use crate::services::row::{make_block_rows, make_rows_from_row_metas, GridBlockSnapshot}; use dashmap::DashMap; use flowy_error::FlowyResult; @@ -94,11 +94,11 @@ impl GridBlockMetaEditorManager { pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { let mut changesets = vec![]; - for block_row_ids in make_block_row_ids(&row_orders) { - let editor = self.get_editor(&block_row_ids.block_id).await?; - let row_count = editor.delete_rows(block_row_ids.row_ids).await?; + for block_row in make_block_rows(&row_orders) { + let editor = self.get_editor(&block_row.block_id).await?; + let row_count = editor.delete_rows(block_row.row_ids).await?; - let changeset = GridBlockMetaChangeset::from_row_count(&block_row_ids.block_id, row_count); + let changeset = GridBlockMetaChangeset::from_row_count(&block_row.block_id, row_count); changesets.push(changeset); } 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 b934d4bc35..1753013760 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -267,6 +267,13 @@ impl ClientGridEditor { } } } + pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> { + todo!() + } + + pub async fn duplicate_row(&self, row_id: &str) -> FlowyResult<()> { + todo!() + } pub async fn get_cell(&self, params: &CellIdentifier) -> Option { let field_meta = self.get_field_meta(¶ms.field_id).await?; @@ -316,6 +323,11 @@ impl ClientGridEditor { Ok(grid_blocks) } + // pub async fn get_field_metas(&self, field_ids: Option>) -> FlowyResult> + // where + // T: Into, + // { + pub async fn delete_rows(&self, row_orders: Vec) -> FlowyResult<()> { let changesets = self.block_meta_manager.delete_rows(row_orders).await?; for changeset in changesets { diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index 89f7db216c..ac26f1d32c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -8,14 +8,14 @@ use std::collections::HashMap; use std::sync::Arc; -pub(crate) struct BlockRowIds { +pub(crate) struct BlockRows { pub(crate) block_id: String, pub(crate) row_ids: Vec, } -impl BlockRowIds { +impl BlockRows { pub fn new(block_id: &str) -> Self { - BlockRowIds { + BlockRows { block_id: block_id.to_owned(), row_ids: vec![], } @@ -27,13 +27,13 @@ pub struct GridBlockSnapshot { pub row_metas: Vec>, } -pub(crate) fn make_block_row_ids(row_orders: &[RowOrder]) -> Vec { - let mut map: HashMap<&String, BlockRowIds> = HashMap::new(); +pub(crate) fn make_block_rows(row_orders: &[RowOrder]) -> Vec { + let mut map: HashMap<&String, BlockRows> = HashMap::new(); row_orders.iter().for_each(|row_order| { let block_id = &row_order.block_id; let row_id = row_order.row_id.clone(); map.entry(block_id) - .or_insert_with(|| BlockRowIds::new(block_id)) + .or_insert_with(|| BlockRows::new(block_id)) .row_ids .push(row_id); }); From b92660058ca7c428be6f23fa3dc3e671453703ec Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 07:10:15 +0800 Subject: [PATCH 4/9] chore: remove grid block from dart side --- .../workspace/application/grid/grid_bloc.dart | 2 +- .../application/grid/grid_service.dart | 10 +---- .../plugins/grid/src/grid_page.dart | 37 +++++++++++++------ frontend/rust-lib/flowy-grid/src/manager.rs | 4 +- .../src/entities/meta.rs | 8 ++-- .../flowy-grid-data-model/tests/serde_test.rs | 4 +- .../src/client_grid/grid_block_meta_pad.rs | 10 ++--- .../src/client_grid/grid_builder.rs | 4 +- .../src/client_grid/grid_meta_pad.rs | 26 ++++++------- 9 files changed, 51 insertions(+), 54 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index a46136a6b5..9e563e2d4e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -79,7 +79,7 @@ class GridBloc extends Bloc { } Future _loadGrid(Emitter emit) async { - final result = await service.openGrid(gridId: view.id); + final result = await service.loadGrid(gridId: view.id); return Future( () => result.fold( (grid) async => await _loadFields(grid, emit), diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 9bb2e36e5f..3456007a6c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -5,7 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:dartz/dartz.dart'; class GridService { - Future> openGrid({required String gridId}) async { + Future> loadGrid({required String gridId}) async { await FolderEventSetLatestView(ViewId(value: gridId)).send(); final payload = GridId(value: gridId); @@ -18,14 +18,6 @@ class GridService { return GridEventCreateRow(payload).send(); } - Future> getGridBlocks( - {required String gridId, required List blockOrders}) { - final payload = QueryGridBlocksPayload.create() - ..gridId = gridId - ..blockOrders.addAll(blockOrders); - return GridEventGetGridBlocks(payload).send(); - } - Future> getFields({required String gridId, required List fieldOrders}) { final payload = QueryFieldPayload.create() ..gridId = gridId diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index b96b89ba2e..6ff3852de5 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -155,24 +155,37 @@ class _FlowyGridState extends State { return rowChanged; }, builder: (context, state) { - return SliverAnimatedList( - key: _key, - initialItemCount: context.read().state.rows.length, - itemBuilder: (BuildContext context, int index, Animation animation) { + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { final blockRow = context.read().state.rows[index]; final fields = context.read().state.fields; final rowData = RowData.fromBlockRow(blockRow, fields); - return _renderRow(rowData, animation); + return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)); }, - ); + childCount: context.read().state.rows.length, + addRepaintBoundaries: true, + addAutomaticKeepAlives: true, + )); + + // return SliverAnimatedList( + // key: _key, + // initialItemCount: context.read().state.rows.length, + // itemBuilder: (BuildContext context, int index, Animation animation) { + // final blockRow = context.read().state.rows[index]; + // final fields = context.read().state.fields; + // final rowData = RowData.fromBlockRow(blockRow, fields); + // return _renderRow(rowData, animation); + // }, + // ); }, ); } - Widget _renderRow(RowData rowData, Animation animation) { - return SizeTransition( - sizeFactor: animation, - child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)), - ); - } + // Widget _renderRow(RowData rowData, Animation animation) { + // return SizeTransition( + // sizeFactor: animation, + // child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)), + // ); + // } } diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index d35ad334c9..21106351c6 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -179,7 +179,7 @@ pub async fn make_grid_view_data( let grid_meta = GridMeta { grid_id: view_id.to_string(), fields: build_context.field_metas, - block_metas: vec![build_context.block_metas], + blocks: vec![build_context.block_metas], }; // Create grid @@ -190,7 +190,7 @@ pub async fn make_grid_view_data( let _ = grid_manager.create_grid(view_id, repeated_revision).await?; // Indexing the block's rows - build_context.block_meta_data.row_metas.iter().for_each(|row| { + build_context.block_meta_data.rows.iter().for_each(|row| { let _ = grid_manager .block_index_persistence .insert_or_update(&row.block_id, &row.id); diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index a7354d3668..7ccd96e955 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -18,7 +18,7 @@ pub struct GridMeta { pub fields: Vec, #[pb(index = 3)] - pub block_metas: Vec, + pub blocks: Vec, } #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, ProtoBuf)] @@ -74,7 +74,7 @@ pub struct GridBlockMetaData { pub block_id: String, #[pb(index = 2)] - pub row_metas: Vec, + pub rows: Vec, } #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, Eq, PartialEq)] @@ -398,7 +398,7 @@ impl std::convert::From for RowMetaChangeset { row_id: changeset.row_id, height: None, visibility: None, - cell_by_field_id: cell_by_field_id, + cell_by_field_id, } } } @@ -420,7 +420,7 @@ impl std::default::Default for BuildGridContext { let grid_block = GridBlockMeta::new(); let grid_block_meta_data = GridBlockMetaData { block_id: grid_block.block_id.clone(), - row_metas: vec![], + rows: vec![], }; Self { diff --git a/shared-lib/flowy-grid-data-model/tests/serde_test.rs b/shared-lib/flowy-grid-data-model/tests/serde_test.rs index 15367cc5ac..0847950b98 100644 --- a/shared-lib/flowy-grid-data-model/tests/serde_test.rs +++ b/shared-lib/flowy-grid-data-model/tests/serde_test.rs @@ -7,7 +7,7 @@ fn grid_serde_test() { let grid = GridMeta { grid_id, fields, - block_metas: vec![], + blocks: vec![], }; let grid_1_json = serde_json::to_string(&grid).unwrap(); @@ -24,7 +24,7 @@ fn grid_default_serde_test() { let grid = GridMeta { grid_id, fields: vec![], - block_metas: vec![], + blocks: vec![], }; let json = serde_json::to_string(&grid).unwrap(); diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index 11cb625762..ce2802052e 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -30,11 +30,7 @@ impl GridBlockMetaPad { CollaborateError::internal().context(msg) })?; let block_id = meta_data.block_id; - let rows = meta_data - .row_metas - .into_iter() - .map(Arc::new) - .collect::>>(); + let rows = meta_data.rows.into_iter().map(Arc::new).collect::>>(); Ok(Self { block_id, row_metas: rows, @@ -215,13 +211,13 @@ impl std::default::Default for GridBlockMetaPad { fn default() -> Self { let block_meta_data = GridBlockMetaData { block_id: uuid(), - row_metas: vec![], + rows: vec![], }; let delta = make_block_meta_delta(&block_meta_data); GridBlockMetaPad { block_id: block_meta_data.block_id, - row_metas: block_meta_data.row_metas.into_iter().map(Arc::new).collect::>(), + row_metas: block_meta_data.rows.into_iter().map(Arc::new).collect::>(), delta, } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs index 43b85de269..d9c5d17280 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs @@ -14,7 +14,7 @@ impl GridBuilder { pub fn add_empty_row(mut self) -> Self { let row = RowMeta::new(&self.build_context.block_metas.block_id); - self.build_context.block_meta_data.row_metas.push(row); + self.build_context.block_meta_data.rows.push(row); self.build_context.block_metas.row_count += 1; self } @@ -57,7 +57,7 @@ mod tests { let grid_meta = GridMeta { grid_id, fields: build_context.field_metas, - block_metas: vec![build_context.block_metas], + blocks: vec![build_context.block_metas], }; let grid_meta_delta = make_grid_delta(&grid_meta); diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 8329d9cc9c..e9788e802d 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -235,12 +235,12 @@ impl GridMetaPad { pub fn create_block_meta(&mut self, block: GridBlockMeta) -> CollaborateResult> { self.modify_grid(|grid_meta| { - if grid_meta.block_metas.iter().any(|b| b.block_id == block.block_id) { + if grid_meta.blocks.iter().any(|b| b.block_id == block.block_id) { tracing::warn!("Duplicate grid block"); Ok(None) } else { - match grid_meta.block_metas.last() { - None => grid_meta.block_metas.push(block), + match grid_meta.blocks.last() { + None => grid_meta.blocks.push(block), Some(last_block) => { if last_block.start_row_index > block.start_row_index && last_block.len() > block.start_row_index @@ -248,7 +248,7 @@ impl GridMetaPad { let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string(); return Err(CollaborateError::internal().context(msg)) } - grid_meta.block_metas.push(block); + grid_meta.blocks.push(block); } } Ok(Some(())) @@ -257,7 +257,7 @@ impl GridMetaPad { } pub fn get_block_metas(&self) -> Vec { - self.grid_meta.block_metas.clone() + self.grid_meta.blocks.clone() } pub fn update_block_meta(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult> { @@ -320,19 +320,15 @@ impl GridMetaPad { where F: FnOnce(&mut GridBlockMeta) -> CollaborateResult>, { - self.modify_grid(|grid_meta| { - match grid_meta - .block_metas - .iter() - .position(|block| block.block_id == block_id) - { + self.modify_grid( + |grid_meta| match grid_meta.blocks.iter().position(|block| block.block_id == block_id) { None => { tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id); Ok(None) } - Some(index) => f(&mut grid_meta.block_metas[index]), - } - }) + Some(index) => f(&mut grid_meta.blocks[index]), + }, + ) } pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> @@ -380,7 +376,7 @@ impl std::default::Default for GridMetaPad { let grid = GridMeta { grid_id: uuid(), fields: vec![], - block_metas: vec![], + blocks: vec![], }; let delta = make_grid_delta(&grid); GridMetaPad { From a755d523719b3bedb1757362ff4f13d67f1492cf Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 08:25:01 +0800 Subject: [PATCH 5/9] chore: using cow for row ids stuff --- .../app_flowy/lib/startup/deps_resolver.dart | 2 +- .../workspace/application/grid/grid_bloc.dart | 45 ++++--- .../application/grid/grid_listener.dart | 42 +++++++ .../application/grid/grid_service.dart | 2 +- .../flowy-grid-data-model/grid.pb.dart | 8 ++ .../flowy-grid-data-model/grid.pbjson.dart | 3 +- .../flowy-grid-data-model/meta.pb.dart | 20 +-- .../flowy-grid-data-model/meta.pbjson.dart | 8 +- .../rust-lib/flowy-grid/src/event_handler.rs | 4 +- .../src/services/block_meta_editor.rs | 20 ++- .../src/services/block_meta_manager.rs | 79 +++++------- .../flowy-grid/src/services/grid_editor.rs | 23 ++-- .../flowy-grid/src/services/row/row_loader.rs | 33 ++--- .../src/entities/grid.rs | 12 +- .../src/protobuf/model/grid.rs | 100 +++++++++++---- .../src/protobuf/model/meta.rs | 118 +++++++++--------- .../src/protobuf/proto/grid.proto | 1 + .../src/protobuf/proto/meta.proto | 4 +- .../src/client_grid/grid_block_meta_pad.rs | 36 ++++-- 19 files changed, 331 insertions(+), 229 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 5f69ab1ad4..98ab00d0e4 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -148,7 +148,7 @@ void _resolveDocDeps(GetIt getIt) { void _resolveGridDeps(GetIt getIt) { // Grid getIt.registerFactoryParam( - (view, _) => GridBloc(view: view, service: GridService()), + (view, _) => GridBloc(view: view), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 9e563e2d4e..c68cd8c726 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -9,27 +9,31 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'grid_block_service.dart'; import 'field/grid_listenr.dart'; +import 'grid_listener.dart'; import 'grid_service.dart'; part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final View view; - final GridService service; + final GridService _gridService; + final GridListener _gridListener; final GridFieldsListener _fieldListener; - GridBlockService? _blockService; - GridBloc({required this.view, required this.service}) + GridBloc({required this.view}) : _fieldListener = GridFieldsListener(gridId: view.id), + _gridService = GridService(), + _gridListener = GridListener(gridId: view.id), super(GridState.initial()) { on( (event, emit) async { await event.map( initial: (InitialGrid value) async { await _initGrid(emit); + _startListening(); }, createRow: (_CreateRow value) { - service.createRow(gridId: view.id); + _gridService.createRow(gridId: view.id); }, delete: (_Delete value) {}, rename: (_Rename value) {}, @@ -48,7 +52,7 @@ class GridBloc extends Bloc { @override Future close() async { await _fieldListener.stop(); - await _blockService?.stop(); + await _gridListener.stop(); return super.close(); } @@ -64,22 +68,17 @@ class GridBloc extends Bloc { await _loadGrid(emit); } - Future _initGridBlock(Grid grid) async { - _blockService = GridBlockService( - gridId: grid.id, - blockOrders: grid.blockOrders, - ); - - _blockService?.blocksUpdateNotifier?.addPublishListener((result) { - result.fold( - (blockMap) => add(GridEvent.didReceiveRowUpdate(_buildRows(blockMap))), - (err) => Log.error('$err'), - ); + void _startListening() { + _gridListener.rowsUpdateNotifier.addPublishListener((result) { + result.fold((blockOrders) { + add(GridEvent.didReceiveRowUpdate(_buildRows(blockOrders))); + }, (err) => Log.error(err)); }); + _gridListener.start(); } Future _loadGrid(Emitter emit) async { - final result = await service.loadGrid(gridId: view.id); + final result = await _gridService.loadGrid(gridId: view.id); return Future( () => result.fold( (grid) async => await _loadFields(grid, emit), @@ -89,14 +88,14 @@ class GridBloc extends Bloc { } Future _loadFields(Grid grid, Emitter emit) async { - final result = await service.getFields(gridId: grid.id, fieldOrders: grid.fieldOrders); + final result = await _gridService.getFields(gridId: grid.id, fieldOrders: grid.fieldOrders); return Future( () => result.fold( (fields) { - _initGridBlock(grid); emit(state.copyWith( grid: Some(grid), fields: fields.items, + rows: _buildRows(grid.blockOrders), loadingState: GridLoadingState.finish(left(unit)), )); }, @@ -105,17 +104,17 @@ class GridBloc extends Bloc { ); } - List _buildRows(GridBlockMap blockMap) { + List _buildRows(List blockOrders) { List rows = []; - blockMap.forEach((_, GridBlock gridBlock) { - rows.addAll(gridBlock.rowOrders.map( + for (final blockOrder in blockOrders) { + rows.addAll(blockOrder.rowOrders.map( (rowOrder) => GridBlockRow( gridId: view.id, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), ), )); - }); + } return rows; } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart new file mode 100644 index 0000000000..b2917089c8 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart @@ -0,0 +1,42 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'dart:async'; +import 'dart:typed_data'; +import 'package:app_flowy/core/notification_helper.dart'; + +class GridListener { + final String gridId; + PublishNotifier, FlowyError>> rowsUpdateNotifier = PublishNotifier(comparable: null); + GridNotificationListener? _listener; + + GridListener({required this.gridId}); + + void start() { + _listener = GridNotificationListener( + objectId: gridId, + handler: _handler, + ); + } + + void _handler(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.DidUpdateBlock: + result.fold( + (payload) => rowsUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), + (error) => rowsUpdateNotifier.value = right(error), + ); + break; + + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + rowsUpdateNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 3456007a6c..bf558cb574 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -5,7 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:dartz/dartz.dart'; class GridService { - Future> loadGrid({required String gridId}) async { + Future> loadGrid({required String gridId}) async { await FolderEventSetLatestView(ViewId(value: gridId)).send(); final payload = GridId(value: gridId); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index e27e019be3..c5e0fb28c9 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -803,17 +803,22 @@ class RepeatedGridBlock extends $pb.GeneratedMessage { class GridBlockOrder extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockOrder', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowOrders', $pb.PbFieldType.PM, subBuilder: RowOrder.create) ..hasRequiredFields = false ; GridBlockOrder._() : super(); factory GridBlockOrder({ $core.String? blockId, + $core.Iterable? rowOrders, }) { final _result = create(); if (blockId != null) { _result.blockId = blockId; } + if (rowOrders != null) { + _result.rowOrders.addAll(rowOrders); + } return _result; } factory GridBlockOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -845,6 +850,9 @@ class GridBlockOrder extends $pb.GeneratedMessage { $core.bool hasBlockId() => $_has(0); @$pb.TagNumber(1) void clearBlockId() => clearField(1); + + @$pb.TagNumber(2) + $core.List get rowOrders => $_getList(1); } class GridBlock extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 3cd228af79..676025d66a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -165,11 +165,12 @@ const GridBlockOrder$json = const { '1': 'GridBlockOrder', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, + const {'1': 'row_orders', '3': 2, '4': 3, '5': 11, '6': '.RowOrder', '10': 'rowOrders'}, ], }; /// Descriptor for `GridBlockOrder`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg5HcmlkQmxvY2tPcmRlchIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZA=='); +final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg5HcmlkQmxvY2tPcmRlchIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIoCgpyb3dfb3JkZXJzGAIgAygLMgkuUm93T3JkZXJSCXJvd09yZGVycw=='); @$core.Deprecated('Use gridBlockDescriptor instead') const GridBlock$json = const { '1': 'GridBlock', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index d322e644c0..9e0f08d42a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -17,7 +17,7 @@ class GridMeta extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridMeta', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fields', $pb.PbFieldType.PM, subBuilder: FieldMeta.create) - ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetas', $pb.PbFieldType.PM, subBuilder: GridBlockMeta.create) + ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blocks', $pb.PbFieldType.PM, subBuilder: GridBlockMeta.create) ..hasRequiredFields = false ; @@ -25,7 +25,7 @@ class GridMeta extends $pb.GeneratedMessage { factory GridMeta({ $core.String? gridId, $core.Iterable? fields, - $core.Iterable? blockMetas, + $core.Iterable? blocks, }) { final _result = create(); if (gridId != null) { @@ -34,8 +34,8 @@ class GridMeta extends $pb.GeneratedMessage { if (fields != null) { _result.fields.addAll(fields); } - if (blockMetas != null) { - _result.blockMetas.addAll(blockMetas); + if (blocks != null) { + _result.blocks.addAll(blocks); } return _result; } @@ -73,7 +73,7 @@ class GridMeta extends $pb.GeneratedMessage { $core.List get fields => $_getList(1); @$pb.TagNumber(3) - $core.List get blockMetas => $_getList(2); + $core.List get blocks => $_getList(2); } class GridBlockMeta extends $pb.GeneratedMessage { @@ -154,21 +154,21 @@ class GridBlockMeta extends $pb.GeneratedMessage { class GridBlockMetaData extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMetaData', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') - ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowMetas', $pb.PbFieldType.PM, subBuilder: RowMeta.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rows', $pb.PbFieldType.PM, subBuilder: RowMeta.create) ..hasRequiredFields = false ; GridBlockMetaData._() : super(); factory GridBlockMetaData({ $core.String? blockId, - $core.Iterable? rowMetas, + $core.Iterable? rows, }) { final _result = create(); if (blockId != null) { _result.blockId = blockId; } - if (rowMetas != null) { - _result.rowMetas.addAll(rowMetas); + if (rows != null) { + _result.rows.addAll(rows); } return _result; } @@ -203,7 +203,7 @@ class GridBlockMetaData extends $pb.GeneratedMessage { void clearBlockId() => clearField(1); @$pb.TagNumber(2) - $core.List get rowMetas => $_getList(1); + $core.List get rows => $_getList(1); } class FieldMeta extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 71b0c1b8e0..70180c231d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -29,12 +29,12 @@ const GridMeta$json = const { '2': const [ const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, const {'1': 'fields', '3': 2, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fields'}, - const {'1': 'block_metas', '3': 3, '4': 3, '5': 11, '6': '.GridBlockMeta', '10': 'blockMetas'}, + const {'1': 'blocks', '3': 3, '4': 3, '5': 11, '6': '.GridBlockMeta', '10': 'blocks'}, ], }; /// Descriptor for `GridMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSIgoGZmllbGRzGAIgAygLMgouRmllbGRNZXRhUgZmaWVsZHMSLwoLYmxvY2tfbWV0YXMYAyADKAsyDi5HcmlkQmxvY2tNZXRhUgpibG9ja01ldGFz'); +final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSIgoGZmllbGRzGAIgAygLMgouRmllbGRNZXRhUgZmaWVsZHMSJgoGYmxvY2tzGAMgAygLMg4uR3JpZEJsb2NrTWV0YVIGYmxvY2tz'); @$core.Deprecated('Use gridBlockMetaDescriptor instead') const GridBlockMeta$json = const { '1': 'GridBlockMeta', @@ -52,12 +52,12 @@ const GridBlockMetaData$json = const { '1': 'GridBlockMetaData', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, - const {'1': 'row_metas', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rowMetas'}, + const {'1': 'rows', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rows'}, ], }; /// Descriptor for `GridBlockMetaData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIlCglyb3dfbWV0YXMYAiADKAsyCC5Sb3dNZXRhUghyb3dNZXRhcw=='); +final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIcCgRyb3dzGAIgAygLMgguUm93TWV0YVIEcm93cw=='); @$core.Deprecated('Use fieldMetaDescriptor instead') const FieldMeta$json = const { '1': 'FieldMeta', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 1ac3796059..acc1eeb5c6 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -186,7 +186,7 @@ pub(crate) async fn delete_row_handler( ) -> Result<(), FlowyError> { let params: RowIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.delete_row(¶ms.row_id)?; + let _ = editor.delete_row(¶ms.row_id).await?; Ok(()) } @@ -197,7 +197,7 @@ pub(crate) async fn duplicate_row_handler( ) -> Result<(), FlowyError> { let params: RowIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.duplicate_row(¶ms.row_id)?; + let _ = editor.duplicate_row(¶ms.row_id).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs index 8518a70fb0..1f8e2e2006 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs @@ -7,6 +7,7 @@ use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_delta_from_revisions; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; +use std::borrow::Cow; use std::sync::Arc; use tokio::sync::RwLock; @@ -54,11 +55,11 @@ impl ClientGridBlockMetaEditor { Ok(row_count) } - pub async fn delete_rows(&self, ids: Vec) -> FlowyResult { + pub async fn delete_rows(&self, ids: Vec>) -> FlowyResult { let mut row_count = 0; let _ = self .modify(|pad| { - let changeset = pad.delete_rows(&ids)?; + let changeset = pad.delete_rows(ids)?; row_count = pad.number_of_rows(); Ok(changeset) }) @@ -71,17 +72,24 @@ impl ClientGridBlockMetaEditor { Ok(()) } - pub async fn get_row_metas(&self, row_ids: Option>) -> FlowyResult>> { - let row_metas = self.pad.read().await.get_row_metas(&row_ids)?; + pub async fn get_row_metas(&self, row_ids: Option>>) -> FlowyResult>> + where + T: AsRef + ToOwned + ?Sized, + { + let row_metas = self.pad.read().await.get_row_metas(row_ids)?; Ok(row_metas) } - pub async fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> FlowyResult> { + pub async fn get_cell_metas( + &self, + field_id: &str, + row_ids: Option>>, + ) -> FlowyResult> { let cell_metas = self.pad.read().await.get_cell_metas(field_id, row_ids)?; Ok(cell_metas) } - pub async fn get_row_orders(&self, row_ids: &Option>) -> FlowyResult> { + pub async fn get_row_orders(&self, row_ids: Option>>) -> FlowyResult> { let row_orders = self .pad .read() diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs index 54e223c242..b14f6641f3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -2,7 +2,8 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::ClientGridBlockMetaEditor; use crate::services::persistence::block_index::BlockIndexPersistence; -use crate::services::row::{make_block_rows, make_rows_from_row_metas, GridBlockSnapshot}; +use crate::services::row::{group_row_orders, make_rows_from_row_metas, GridBlockSnapshot}; +use std::borrow::Cow; use dashmap::DashMap; use flowy_error::FlowyResult; @@ -18,6 +19,7 @@ use std::sync::Arc; pub(crate) struct GridBlockMetaEditorManager { grid_id: String, user: Arc, + // Key: block_id editor_map: DashMap>, persistence: Arc, } @@ -92,19 +94,6 @@ impl GridBlockMetaEditorManager { Ok(changesets) } - pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { - let mut changesets = vec![]; - for block_row in make_block_rows(&row_orders) { - let editor = self.get_editor(&block_row.block_id).await?; - let row_count = editor.delete_rows(block_row.row_ids).await?; - - let changeset = GridBlockMetaChangeset::from_row_count(&block_row.block_id, row_count); - changesets.push(changeset); - } - - Ok(changesets) - } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; @@ -112,6 +101,23 @@ impl GridBlockMetaEditorManager { Ok(()) } + pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { + let mut changesets = vec![]; + for block_order in group_row_orders(row_orders) { + let editor = self.get_editor(&block_order.block_id).await?; + let row_ids = block_order + .row_orders + .into_iter() + .map(|row_order| Cow::Owned(row_order.row_id)) + .collect::>>(); + let row_count = editor.delete_rows(row_ids).await?; + let changeset = GridBlockMetaChangeset::from_row_count(&block_order.block_id, row_count); + changesets.push(changeset); + } + + Ok(changesets) + } + pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { let row_id = changeset.row_id.clone(); let editor = self.get_editor_from_row_id(&row_id).await?; @@ -130,7 +136,7 @@ impl GridBlockMetaEditorManager { pub async fn get_row_meta(&self, row_id: &str) -> FlowyResult>> { let editor = self.get_editor_from_row_id(row_id).await?; - let row_ids = vec![row_id.to_owned()]; + let row_ids = vec![Cow::Borrowed(row_id)]; let mut row_metas = editor.get_row_metas(Some(row_ids)).await?; if row_metas.is_empty() { Ok(None) @@ -139,11 +145,16 @@ impl GridBlockMetaEditorManager { } } + pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult> { + let editor = self.get_editor(block_id).await?; + editor.get_row_orders(None).await + } + pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { let mut snapshots = vec![]; for block_id in block_ids { let editor = self.get_editor(&block_id).await?; - let row_metas = editor.get_row_metas(None).await?; + let row_metas = editor.get_row_metas::<&str>(None).await?; snapshots.push(GridBlockSnapshot { block_id, row_metas }); } Ok(snapshots) @@ -155,22 +166,22 @@ impl GridBlockMetaEditorManager { &self, block_ids: Vec, field_id: &str, - row_ids: Option>, + row_ids: Option>>, ) -> FlowyResult> { let mut block_cell_metas = vec![]; for block_id in block_ids { let editor = self.get_editor(&block_id).await?; - let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?; + let cell_metas = editor.get_cell_metas(field_id, row_ids.clone()).await?; block_cell_metas.extend(cell_metas); } Ok(block_cell_metas) } async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { - let block_order: GridBlockOrder = block_id.into(); - send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) - .payload(block_order) - .send(); + // let block_order: GridBlockOrder = block_id.into(); + // send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) + // .payload(block_order) + // .send(); Ok(()) } @@ -196,30 +207,6 @@ impl GridBlockMetaEditorManager { } } Ok(()) - - // - // let field_meta_map = field_metas - // .iter() - // .map(|field_meta| (&field_meta.id, field_meta)) - // .collect::>(); - // - // let mut cells = vec![]; - // changeset - // .cell_by_field_id - // .into_iter() - // .for_each( - // |(field_id, cell_meta)| match make_cell_by_field_id(&field_meta_map, field_id, cell_meta) { - // None => {} - // Some((_, cell)) => cells.push(cell), - // }, - // ); - // - // if !cells.is_empty() { - // send_dart_notification(&changeset.row_id, GridNotification::DidUpdateRow) - // .payload(RepeatedCell::from(cells)) - // .send(); - // } - // 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 1753013760..44fc4c4e76 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -337,17 +337,18 @@ impl ClientGridEditor { } pub async fn grid_data(&self) -> FlowyResult { - let field_orders = self.pad.read().await.get_field_orders(); - let block_orders = self - .pad - .read() - .await - .get_block_metas() - .into_iter() - .map(|grid_block_meta| GridBlockOrder { - block_id: grid_block_meta.block_id, - }) - .collect::>(); + let pad_read_guard = self.pad.read().await; + let field_orders = pad_read_guard.get_field_orders(); + let mut block_orders = vec![]; + for block_order in pad_read_guard.get_block_metas() { + let row_orders = self.block_meta_manager.get_row_orders(&block_order.block_id).await?; + let block_order = GridBlockOrder { + block_id: block_order.block_id, + row_orders, + }; + block_orders.push(block_order); + } + Ok(Grid { id: self.grid_id.clone(), field_orders, diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index ac26f1d32c..26e889f1af 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -1,41 +1,28 @@ use crate::services::row::decode_cell_data; use flowy_error::FlowyResult; use flowy_grid_data_model::entities::{ - Cell, CellMeta, FieldMeta, GridBlock, RepeatedGridBlock, Row, RowMeta, RowOrder, + Cell, CellMeta, FieldMeta, GridBlock, GridBlockOrder, RepeatedGridBlock, Row, RowMeta, RowOrder, }; use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; -pub(crate) struct BlockRows { - pub(crate) block_id: String, - pub(crate) row_ids: Vec, -} - -impl BlockRows { - pub fn new(block_id: &str) -> Self { - BlockRows { - block_id: block_id.to_owned(), - row_ids: vec![], - } - } -} - pub struct GridBlockSnapshot { pub(crate) block_id: String, pub row_metas: Vec>, } -pub(crate) fn make_block_rows(row_orders: &[RowOrder]) -> Vec { - let mut map: HashMap<&String, BlockRows> = HashMap::new(); - row_orders.iter().for_each(|row_order| { - let block_id = &row_order.block_id; - let row_id = row_order.row_id.clone(); +pub(crate) fn group_row_orders(row_orders: Vec) -> Vec { + let mut map: HashMap = HashMap::new(); + row_orders.into_iter().for_each(|row_order| { + // Memory Optimization: escape clone block_id + let block_id = row_order.block_id.clone(); map.entry(block_id) - .or_insert_with(|| BlockRows::new(block_id)) - .row_ids - .push(row_id); + .or_insert_with(|| GridBlockOrder::new(&row_order.block_id)) + .row_orders + .push(row_order); }); map.into_values().collect::>() } diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index d3cb9f7f69..42b3453d20 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -260,11 +260,17 @@ impl std::convert::From> for RepeatedGridBlock { pub struct GridBlockOrder { #[pb(index = 1)] pub block_id: String, + + #[pb(index = 2)] + pub row_orders: Vec, } -impl std::convert::From<&str> for GridBlockOrder { - fn from(s: &str) -> Self { - GridBlockOrder { block_id: s.to_owned() } +impl GridBlockOrder { + pub fn new(block_id: &str) -> Self { + GridBlockOrder { + block_id: block_id.to_owned(), + row_orders: vec![], + } } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index c31a2def27..944db183f9 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -2715,6 +2715,7 @@ impl ::protobuf::reflect::ProtobufValue for RepeatedGridBlock { pub struct GridBlockOrder { // message fields pub block_id: ::std::string::String, + pub row_orders: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -2756,10 +2757,40 @@ impl GridBlockOrder { pub fn take_block_id(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } + + // repeated .RowOrder row_orders = 2; + + + pub fn get_row_orders(&self) -> &[RowOrder] { + &self.row_orders + } + pub fn clear_row_orders(&mut self) { + self.row_orders.clear(); + } + + // Param is passed by value, moved + pub fn set_row_orders(&mut self, v: ::protobuf::RepeatedField) { + self.row_orders = v; + } + + // Mutable pointer to the field. + pub fn mut_row_orders(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.row_orders + } + + // Take field + pub fn take_row_orders(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.row_orders, ::protobuf::RepeatedField::new()) + } } impl ::protobuf::Message for GridBlockOrder { fn is_initialized(&self) -> bool { + for v in &self.row_orders { + if !v.is_initialized() { + return false; + } + }; true } @@ -2770,6 +2801,9 @@ impl ::protobuf::Message for GridBlockOrder { 1 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; }, + 2 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.row_orders)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -2785,6 +2819,10 @@ impl ::protobuf::Message for GridBlockOrder { if !self.block_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.block_id); } + for value in &self.row_orders { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -2794,6 +2832,11 @@ impl ::protobuf::Message for GridBlockOrder { if !self.block_id.is_empty() { os.write_string(1, &self.block_id)?; } + for v in &self.row_orders { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -2837,6 +2880,11 @@ impl ::protobuf::Message for GridBlockOrder { |m: &GridBlockOrder| { &m.block_id }, |m: &mut GridBlockOrder| { &mut m.block_id }, )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "row_orders", + |m: &GridBlockOrder| { &m.row_orders }, + |m: &mut GridBlockOrder| { &mut m.row_orders }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridBlockOrder", fields, @@ -2854,6 +2902,7 @@ impl ::protobuf::Message for GridBlockOrder { impl ::protobuf::Clear for GridBlockOrder { fn clear(&mut self) { self.block_id.clear(); + self.row_orders.clear(); self.unknown_fields.clear(); } } @@ -5283,31 +5332,32 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ - items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ - \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ - \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ - \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ - \x07content\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07\ - fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07co\ - ntent\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\ - \x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05i\ - tems\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04\ - name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"\ - #\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\ - \x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13on\ - e_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\ - \x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\ - \x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\ - \x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cst\ - artFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\ - \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\ - \x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16Qu\ - eryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblo\ - ckOrdersb\x06proto3\ + items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\ + \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\ + \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"E\n\tGridBlock\x12\x0e\n\ + \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ + 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ + \x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\ + \"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\x01\x20\ + \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ + \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\ + \x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepe\ + atedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\ + \n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\ + \x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\ + \x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10\ + CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ + \"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of\ + _start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.\ + FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etype\ + OptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartField\ + IdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\ + \x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\ + locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\ + \x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\ + sb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index f90832a447..8ca8db2765 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -28,7 +28,7 @@ pub struct GridMeta { // message fields pub grid_id: ::std::string::String, pub fields: ::protobuf::RepeatedField, - pub block_metas: ::protobuf::RepeatedField, + pub blocks: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -96,29 +96,29 @@ impl GridMeta { ::std::mem::replace(&mut self.fields, ::protobuf::RepeatedField::new()) } - // repeated .GridBlockMeta block_metas = 3; + // repeated .GridBlockMeta blocks = 3; - pub fn get_block_metas(&self) -> &[GridBlockMeta] { - &self.block_metas + pub fn get_blocks(&self) -> &[GridBlockMeta] { + &self.blocks } - pub fn clear_block_metas(&mut self) { - self.block_metas.clear(); + pub fn clear_blocks(&mut self) { + self.blocks.clear(); } // Param is passed by value, moved - pub fn set_block_metas(&mut self, v: ::protobuf::RepeatedField) { - self.block_metas = v; + pub fn set_blocks(&mut self, v: ::protobuf::RepeatedField) { + self.blocks = v; } // Mutable pointer to the field. - pub fn mut_block_metas(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.block_metas + pub fn mut_blocks(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.blocks } // Take field - pub fn take_block_metas(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.block_metas, ::protobuf::RepeatedField::new()) + pub fn take_blocks(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.blocks, ::protobuf::RepeatedField::new()) } } @@ -129,7 +129,7 @@ impl ::protobuf::Message for GridMeta { return false; } }; - for v in &self.block_metas { + for v in &self.blocks { if !v.is_initialized() { return false; } @@ -148,7 +148,7 @@ impl ::protobuf::Message for GridMeta { ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.fields)?; }, 3 => { - ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.block_metas)?; + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.blocks)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -169,7 +169,7 @@ impl ::protobuf::Message for GridMeta { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; - for value in &self.block_metas { + for value in &self.blocks { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; @@ -187,7 +187,7 @@ impl ::protobuf::Message for GridMeta { os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; }; - for v in &self.block_metas { + for v in &self.blocks { os.write_tag(3, ::protobuf::wire_format::WireTypeLengthDelimited)?; os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; @@ -241,9 +241,9 @@ impl ::protobuf::Message for GridMeta { |m: &mut GridMeta| { &mut m.fields }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "block_metas", - |m: &GridMeta| { &m.block_metas }, - |m: &mut GridMeta| { &mut m.block_metas }, + "blocks", + |m: &GridMeta| { &m.blocks }, + |m: &mut GridMeta| { &mut m.blocks }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridMeta", @@ -263,7 +263,7 @@ impl ::protobuf::Clear for GridMeta { fn clear(&mut self) { self.grid_id.clear(); self.fields.clear(); - self.block_metas.clear(); + self.blocks.clear(); self.unknown_fields.clear(); } } @@ -513,7 +513,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockMeta { pub struct GridBlockMetaData { // message fields pub block_id: ::std::string::String, - pub row_metas: ::protobuf::RepeatedField, + pub rows: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -556,35 +556,35 @@ impl GridBlockMetaData { ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } - // repeated .RowMeta row_metas = 2; + // repeated .RowMeta rows = 2; - pub fn get_row_metas(&self) -> &[RowMeta] { - &self.row_metas + pub fn get_rows(&self) -> &[RowMeta] { + &self.rows } - pub fn clear_row_metas(&mut self) { - self.row_metas.clear(); + pub fn clear_rows(&mut self) { + self.rows.clear(); } // Param is passed by value, moved - pub fn set_row_metas(&mut self, v: ::protobuf::RepeatedField) { - self.row_metas = v; + pub fn set_rows(&mut self, v: ::protobuf::RepeatedField) { + self.rows = v; } // Mutable pointer to the field. - pub fn mut_row_metas(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.row_metas + pub fn mut_rows(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.rows } // Take field - pub fn take_row_metas(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.row_metas, ::protobuf::RepeatedField::new()) + pub fn take_rows(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.rows, ::protobuf::RepeatedField::new()) } } impl ::protobuf::Message for GridBlockMetaData { fn is_initialized(&self) -> bool { - for v in &self.row_metas { + for v in &self.rows { if !v.is_initialized() { return false; } @@ -600,7 +600,7 @@ impl ::protobuf::Message for GridBlockMetaData { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; }, 2 => { - ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.row_metas)?; + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.rows)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -617,7 +617,7 @@ impl ::protobuf::Message for GridBlockMetaData { if !self.block_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.block_id); } - for value in &self.row_metas { + for value in &self.rows { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; @@ -630,7 +630,7 @@ impl ::protobuf::Message for GridBlockMetaData { if !self.block_id.is_empty() { os.write_string(1, &self.block_id)?; } - for v in &self.row_metas { + for v in &self.rows { os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; @@ -679,9 +679,9 @@ impl ::protobuf::Message for GridBlockMetaData { |m: &mut GridBlockMetaData| { &mut m.block_id }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "row_metas", - |m: &GridBlockMetaData| { &m.row_metas }, - |m: &mut GridBlockMetaData| { &mut m.row_metas }, + "rows", + |m: &GridBlockMetaData| { &m.rows }, + |m: &mut GridBlockMetaData| { &mut m.rows }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridBlockMetaData", @@ -700,7 +700,7 @@ impl ::protobuf::Message for GridBlockMetaData { impl ::protobuf::Clear for GridBlockMetaData { fn clear(&mut self) { self.block_id.clear(); - self.row_metas.clear(); + self.rows.clear(); self.unknown_fields.clear(); } } @@ -3453,26 +3453,26 @@ impl ::protobuf::reflect::ProtobufValue for FieldType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nmeta.proto\"x\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ + \n\nmeta.proto\"o\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ \x06gridId\x12\"\n\x06fields\x18\x02\x20\x03(\x0b2\n.FieldMetaR\x06field\ - s\x12/\n\x0bblock_metas\x18\x03\x20\x03(\x0b2\x0e.GridBlockMetaR\nblockM\ - etas\"o\n\rGridBlockMeta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07bl\ - ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ - \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"U\n\x11GridBlockMet\ - aData\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_m\ - etas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xbc\x02\n\tFieldMe\ - ta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ - \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ - \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ - \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ - \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12>\n\x0ctype_options\x18\x08\x20\x03(\x0b2\x1b.FieldMeta.TypeOpti\ - onsEntryR\x0btypeOptions\x1a>\n\x10TypeOptionsEntry\x12\x10\n\x03key\x18\ - \x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\ - \x028\x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\ - \x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06\ - gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04des\ - c\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\ + s\x12&\n\x06blocks\x18\x03\x20\x03(\x0b2\x0e.GridBlockMetaR\x06blocks\"o\ + \n\rGridBlockMeta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\ + \x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\x1b\ + \n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"L\n\x11GridBlockMetaDat\ + a\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12\x1c\n\x04rows\ + \x18\x02\x20\x03(\x0b2\x08.RowMetaR\x04rows\"\xbc\x02\n\tFieldMeta\x12\ + \x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01\ + (\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield\ + _type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\ + \x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\ + \x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\x12>\ + \n\x0ctype_options\x18\x08\x20\x03(\x0b2\x1b.FieldMeta.TypeOptionsEntryR\ + \x0btypeOptions\x1a>\n\x10TypeOptionsEntry\x12\x10\n\x03key\x18\x01\x20\ + \x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\x028\ + \x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\ + \x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06grid\ + Id\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\ + \x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\ \x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\ \x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nv\ isibility\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\ diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index c1166a3ae1..b1bf045cd7 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -57,6 +57,7 @@ message RepeatedGridBlock { } message GridBlockOrder { string block_id = 1; + repeated RowOrder row_orders = 2; } message GridBlock { string id = 1; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 18c05896fe..2cf0f9b2af 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -3,7 +3,7 @@ syntax = "proto3"; message GridMeta { string grid_id = 1; repeated FieldMeta fields = 2; - repeated GridBlockMeta block_metas = 3; + repeated GridBlockMeta blocks = 3; } message GridBlockMeta { string block_id = 1; @@ -12,7 +12,7 @@ message GridBlockMeta { } message GridBlockMetaData { string block_id = 1; - repeated RowMeta row_metas = 2; + repeated RowMeta rows = 2; } message FieldMeta { string id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index ce2802052e..bd5ea1d1a6 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -5,6 +5,7 @@ use flowy_grid_data_model::entities::{CellMeta, GridBlockMetaData, RowMeta, RowM use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -67,38 +68,48 @@ impl GridBlockMetaPad { }) } - pub fn delete_rows(&mut self, row_ids: &[String]) -> CollaborateResult> { + pub fn delete_rows(&mut self, row_ids: Vec>) -> CollaborateResult> { self.modify(|rows| { - rows.retain(|row| !row_ids.contains(&row.id)); + rows.retain(|row| !row_ids.contains(&Cow::Borrowed(&row.id))); Ok(Some(())) }) } - pub fn get_row_metas(&self, row_ids: &Option>) -> CollaborateResult>> { + pub fn get_row_metas(&self, row_ids: Option>>) -> CollaborateResult>> + where + T: AsRef + ToOwned + ?Sized, + { match row_ids { None => Ok(self.row_metas.to_vec()), Some(row_ids) => { let row_map = self .row_metas .iter() - .map(|row| (&row.id, row.clone())) - .collect::>>(); + .map(|row| (row.id.as_str(), row.clone())) + .collect::>>(); Ok(row_ids .iter() - .flat_map(|row_id| match row_map.get(row_id) { - None => { - tracing::error!("Can't find the row with id: {}", row_id); - None + .flat_map(|row_id| { + let row_id = row_id.as_ref().as_ref(); + match row_map.get(row_id) { + None => { + tracing::error!("Can't find the row with id: {}", row_id); + None + } + Some(row) => Some(row.clone()), } - Some(row) => Some(row.clone()), }) .collect::>()) } } } - pub fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> CollaborateResult> { + pub fn get_cell_metas( + &self, + field_id: &str, + row_ids: Option>>, + ) -> CollaborateResult> { let rows = self.get_row_metas(row_ids)?; let cell_metas = rows .iter() @@ -227,6 +238,7 @@ impl std::default::Default for GridBlockMetaPad { mod tests { use crate::client_grid::{GridBlockMetaDelta, GridBlockMetaPad}; use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset}; + use std::borrow::Cow; #[test] fn block_meta_add_row() { @@ -331,7 +343,7 @@ mod tests { }; let _ = pad.add_row_meta(row.clone(), None).unwrap().unwrap(); - let change = pad.delete_rows(&[row.id]).unwrap().unwrap(); + let change = pad.delete_rows(vec![Cow::Borrowed(&row.id)]).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":29},{"delete":77},{"retain":2}]"# From 420b8ca05dcc27a50158bbddb08ec78b05cea0c4 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 10:31:55 +0800 Subject: [PATCH 6/9] chore: fix deserialize GridBlockMetaPad error --- .../workspace/application/grid/grid_bloc.dart | 13 +- .../application/grid/grid_block_service.dart | 92 ----- .../application/grid/grid_listener.dart | 7 +- .../flowy-grid-data-model/grid.pb.dart | 71 ++++ .../flowy-grid-data-model/grid.pbjson.dart | 13 + .../flowy-grid-data-model/meta.pb.dart | 18 +- .../flowy-grid-data-model/meta.pbjson.dart | 4 +- .../flowy-grid/dart_notification.pbenum.dart | 4 +- .../flowy-grid/dart_notification.pbjson.dart | 4 +- .../flowy-grid/src/dart_notification.rs | 2 +- frontend/rust-lib/flowy-grid/src/manager.rs | 5 +- .../src/protobuf/model/dart_notification.rs | 16 +- .../protobuf/proto/dart_notification.proto | 2 +- .../src/services/block_meta_manager.rs | 41 +- .../src/entities/grid.rs | 44 +++ .../src/entities/meta.rs | 12 +- .../src/protobuf/model/grid.rs | 358 ++++++++++++++++-- .../src/protobuf/model/meta.rs | 63 ++- .../src/protobuf/proto/grid.proto | 6 + .../src/protobuf/proto/meta.proto | 2 +- .../src/client_grid/grid_block_meta_pad.rs | 53 ++- .../src/client_grid/grid_builder.rs | 6 +- 22 files changed, 605 insertions(+), 231 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index c68cd8c726..44c048bac3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -7,7 +7,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'grid_block_service.dart'; import 'field/grid_listenr.dart'; import 'grid_listener.dart'; import 'grid_service.dart'; @@ -70,8 +69,16 @@ class GridBloc extends Bloc { void _startListening() { _gridListener.rowsUpdateNotifier.addPublishListener((result) { - result.fold((blockOrders) { - add(GridEvent.didReceiveRowUpdate(_buildRows(blockOrders))); + result.fold((gridBlockChangeset) { + for (final changeset in gridBlockChangeset) { + if (changeset.insertedRows.isNotEmpty) {} + + if (changeset.deletedRows.isNotEmpty) {} + + if (changeset.updatedRows.isNotEmpty) {} + } + + // add(GridEvent.didReceiveRowUpdate(_buildRows(blockOrders))); }, (err) => Log.error(err)); }); _gridListener.start(); diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart deleted file mode 100644 index e6ecad0949..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:collection'; -import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'dart:async'; -import 'dart:typed_data'; -import 'package:app_flowy/core/notification_helper.dart'; - -typedef GridBlockMap = LinkedHashMap; -typedef BlocksUpdateNotifierValue = Either; - -class GridBlockService { - String gridId; - GridBlockMap blockMap = GridBlockMap(); - late GridBlockListener _blockListener; - PublishNotifier? blocksUpdateNotifier = PublishNotifier(); - - GridBlockService({required this.gridId, required List blockOrders}) { - _loadGridBlocks(blockOrders); - - _blockListener = GridBlockListener(gridId: gridId); - _blockListener.blockUpdateNotifier.addPublishListener((result) { - result.fold( - (blockOrder) => _loadGridBlocks(blockOrder), - (err) => Log.error(err), - ); - }); - _blockListener.start(); - } - - Future stop() async { - await _blockListener.stop(); - blocksUpdateNotifier?.dispose(); - blocksUpdateNotifier = null; - } - - void _loadGridBlocks(List blockOrders) { - final payload = QueryGridBlocksPayload.create() - ..gridId = gridId - ..blockOrders.addAll(blockOrders); - - GridEventGetGridBlocks(payload).send().then((result) { - result.fold( - (repeatedBlocks) { - for (final gridBlock in repeatedBlocks.items) { - blockMap[gridBlock.id] = gridBlock; - } - blocksUpdateNotifier?.value = left(blockMap); - }, - (err) => blocksUpdateNotifier?.value = right(err), - ); - }); - } -} - -class GridBlockListener { - final String gridId; - PublishNotifier, FlowyError>> blockUpdateNotifier = PublishNotifier(comparable: null); - GridNotificationListener? _listener; - - GridBlockListener({required this.gridId}); - - void start() { - _listener = GridNotificationListener( - objectId: gridId, - handler: _handler, - ); - } - - void _handler(GridNotification ty, Either result) { - switch (ty) { - case GridNotification.DidUpdateBlock: - result.fold( - (payload) => blockUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), - (error) => blockUpdateNotifier.value = right(error), - ); - break; - - default: - break; - } - } - - Future stop() async { - await _listener?.stop(); - blockUpdateNotifier.dispose(); - } -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart index b2917089c8..f36a630e1a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart @@ -9,7 +9,8 @@ import 'package:app_flowy/core/notification_helper.dart'; class GridListener { final String gridId; - PublishNotifier, FlowyError>> rowsUpdateNotifier = PublishNotifier(comparable: null); + PublishNotifier, FlowyError>> rowsUpdateNotifier = + PublishNotifier(comparable: null); GridNotificationListener? _listener; GridListener({required this.gridId}); @@ -23,9 +24,9 @@ class GridListener { void _handler(GridNotification ty, Either result) { switch (ty) { - case GridNotification.DidUpdateBlock: + case GridNotification.DidUpdateGridBlock: result.fold( - (payload) => rowsUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), + (payload) => rowsUpdateNotifier.value = left([GridBlockOrderChangeset.fromBuffer(payload)]), (error) => rowsUpdateNotifier.value = right(error), ); break; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index c5e0fb28c9..f613504047 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -855,6 +855,77 @@ class GridBlockOrder extends $pb.GeneratedMessage { $core.List get rowOrders => $_getList(1); } +class GridBlockOrderChangeset extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockOrderChangeset', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) + ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deletedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) + ..pc(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'updatedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) + ..hasRequiredFields = false + ; + + GridBlockOrderChangeset._() : super(); + factory GridBlockOrderChangeset({ + $core.String? blockId, + $core.Iterable? insertedRows, + $core.Iterable? deletedRows, + $core.Iterable? updatedRows, + }) { + final _result = create(); + if (blockId != null) { + _result.blockId = blockId; + } + if (insertedRows != null) { + _result.insertedRows.addAll(insertedRows); + } + if (deletedRows != null) { + _result.deletedRows.addAll(deletedRows); + } + if (updatedRows != null) { + _result.updatedRows.addAll(updatedRows); + } + return _result; + } + factory GridBlockOrderChangeset.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GridBlockOrderChangeset.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + GridBlockOrderChangeset clone() => GridBlockOrderChangeset()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GridBlockOrderChangeset copyWith(void Function(GridBlockOrderChangeset) updates) => super.copyWith((message) => updates(message as GridBlockOrderChangeset)) as GridBlockOrderChangeset; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GridBlockOrderChangeset create() => GridBlockOrderChangeset._(); + GridBlockOrderChangeset createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static GridBlockOrderChangeset getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GridBlockOrderChangeset? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get blockId => $_getSZ(0); + @$pb.TagNumber(1) + set blockId($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasBlockId() => $_has(0); + @$pb.TagNumber(1) + void clearBlockId() => clearField(1); + + @$pb.TagNumber(2) + $core.List get insertedRows => $_getList(1); + + @$pb.TagNumber(3) + $core.List get deletedRows => $_getList(2); + + @$pb.TagNumber(4) + $core.List get updatedRows => $_getList(3); +} + class GridBlock extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlock', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 676025d66a..0c1abf778e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -171,6 +171,19 @@ const GridBlockOrder$json = const { /// Descriptor for `GridBlockOrder`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg5HcmlkQmxvY2tPcmRlchIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIoCgpyb3dfb3JkZXJzGAIgAygLMgkuUm93T3JkZXJSCXJvd09yZGVycw=='); +@$core.Deprecated('Use gridBlockOrderChangesetDescriptor instead') +const GridBlockOrderChangeset$json = const { + '1': 'GridBlockOrderChangeset', + '2': const [ + const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, + const {'1': 'inserted_rows', '3': 2, '4': 3, '5': 11, '6': '.RowOrder', '10': 'insertedRows'}, + const {'1': 'deleted_rows', '3': 3, '4': 3, '5': 11, '6': '.RowOrder', '10': 'deletedRows'}, + const {'1': 'updated_rows', '3': 4, '4': 3, '5': 11, '6': '.RowOrder', '10': 'updatedRows'}, + ], +}; + +/// Descriptor for `GridBlockOrderChangeset`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List gridBlockOrderChangesetDescriptor = $convert.base64Decode('ChdHcmlkQmxvY2tPcmRlckNoYW5nZXNldBIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIuCg1pbnNlcnRlZF9yb3dzGAIgAygLMgkuUm93T3JkZXJSDGluc2VydGVkUm93cxIsCgxkZWxldGVkX3Jvd3MYAyADKAsyCS5Sb3dPcmRlclILZGVsZXRlZFJvd3MSLAoMdXBkYXRlZF9yb3dzGAQgAygLMgkuUm93T3JkZXJSC3VwZGF0ZWRSb3dz'); @$core.Deprecated('Use gridBlockDescriptor instead') const GridBlock$json = const { '1': 'GridBlock', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index 9e0f08d42a..5ab811fa3f 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -1014,7 +1014,7 @@ class CellMetaChangeset extends $pb.GeneratedMessage { class BuildGridContext extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BuildGridContext', createEmptyInstance: create) ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldMetas', $pb.PbFieldType.PM, subBuilder: FieldMeta.create) - ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetas', subBuilder: GridBlockMeta.create) + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMeta', subBuilder: GridBlockMeta.create) ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetaData', subBuilder: GridBlockMetaData.create) ..hasRequiredFields = false ; @@ -1022,15 +1022,15 @@ class BuildGridContext extends $pb.GeneratedMessage { BuildGridContext._() : super(); factory BuildGridContext({ $core.Iterable? fieldMetas, - GridBlockMeta? blockMetas, + GridBlockMeta? blockMeta, GridBlockMetaData? blockMetaData, }) { final _result = create(); if (fieldMetas != null) { _result.fieldMetas.addAll(fieldMetas); } - if (blockMetas != null) { - _result.blockMetas = blockMetas; + if (blockMeta != null) { + _result.blockMeta = blockMeta; } if (blockMetaData != null) { _result.blockMetaData = blockMetaData; @@ -1062,15 +1062,15 @@ class BuildGridContext extends $pb.GeneratedMessage { $core.List get fieldMetas => $_getList(0); @$pb.TagNumber(2) - GridBlockMeta get blockMetas => $_getN(1); + GridBlockMeta get blockMeta => $_getN(1); @$pb.TagNumber(2) - set blockMetas(GridBlockMeta v) { setField(2, v); } + set blockMeta(GridBlockMeta v) { setField(2, v); } @$pb.TagNumber(2) - $core.bool hasBlockMetas() => $_has(1); + $core.bool hasBlockMeta() => $_has(1); @$pb.TagNumber(2) - void clearBlockMetas() => clearField(2); + void clearBlockMeta() => clearField(2); @$pb.TagNumber(2) - GridBlockMeta ensureBlockMetas() => $_ensure(1); + GridBlockMeta ensureBlockMeta() => $_ensure(1); @$pb.TagNumber(3) GridBlockMetaData get blockMetaData => $_getN(2); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 70180c231d..8e73d2ce1c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -208,10 +208,10 @@ const BuildGridContext$json = const { '1': 'BuildGridContext', '2': const [ const {'1': 'field_metas', '3': 1, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fieldMetas'}, - const {'1': 'block_metas', '3': 2, '4': 1, '5': 11, '6': '.GridBlockMeta', '10': 'blockMetas'}, + const {'1': 'block_meta', '3': 2, '4': 1, '5': 11, '6': '.GridBlockMeta', '10': 'blockMeta'}, const {'1': 'block_meta_data', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMetaData', '10': 'blockMetaData'}, ], }; /// Descriptor for `BuildGridContext`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi8KC2Jsb2NrX21ldGFzGAIgASgLMg4uR3JpZEJsb2NrTWV0YVIKYmxvY2tNZXRhcxI6Cg9ibG9ja19tZXRhX2RhdGEYAyABKAsyEi5HcmlkQmxvY2tNZXRhRGF0YVINYmxvY2tNZXRhRGF0YQ=='); +final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi0KCmJsb2NrX21ldGEYAiABKAsyDi5HcmlkQmxvY2tNZXRhUglibG9ja01ldGESOgoPYmxvY2tfbWV0YV9kYXRhGAMgASgLMhIuR3JpZEJsb2NrTWV0YURhdGFSDWJsb2NrTWV0YURhdGE='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart index 4331fef2a7..d39002e540 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart @@ -12,7 +12,7 @@ import 'package:protobuf/protobuf.dart' as $pb; class GridNotification extends $pb.ProtobufEnum { static const GridNotification Unknown = GridNotification._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown'); static const GridNotification DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock'); - static const GridNotification DidUpdateBlock = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateBlock'); + static const GridNotification DidUpdateGridBlock = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateGridBlock'); static const GridNotification DidUpdateRow = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification DidUpdateCell = GridNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateCell'); static const GridNotification DidUpdateGrid = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateGrid'); @@ -21,7 +21,7 @@ class GridNotification extends $pb.ProtobufEnum { static const $core.List values = [ Unknown, DidCreateBlock, - DidUpdateBlock, + DidUpdateGridBlock, DidUpdateRow, DidUpdateCell, DidUpdateGrid, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart index ed6bbdc2d4..787a77ffa1 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart @@ -14,7 +14,7 @@ const GridNotification$json = const { '2': const [ const {'1': 'Unknown', '2': 0}, const {'1': 'DidCreateBlock', '2': 11}, - const {'1': 'DidUpdateBlock', '2': 20}, + const {'1': 'DidUpdateGridBlock', '2': 20}, const {'1': 'DidUpdateRow', '2': 30}, const {'1': 'DidUpdateCell', '2': 31}, const {'1': 'DidUpdateGrid', '2': 40}, @@ -23,4 +23,4 @@ const GridNotification$json = const { }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEQoNRGlkVXBkYXRlQ2VsbBAfEhEKDURpZFVwZGF0ZUdyaWQQKBISCg5EaWRVcGRhdGVGaWVsZBAp'); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhYKEkRpZFVwZGF0ZUdyaWRCbG9jaxAUEhAKDERpZFVwZGF0ZVJvdxAeEhEKDURpZFVwZGF0ZUNlbGwQHxIRCg1EaWRVcGRhdGVHcmlkECgSEgoORGlkVXBkYXRlRmllbGQQKQ=='); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index cc910e30c6..a2a1de0a9f 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -6,7 +6,7 @@ const OBSERVABLE_CATEGORY: &str = "Grid"; pub enum GridNotification { Unknown = 0, DidCreateBlock = 11, - DidUpdateBlock = 20, + DidUpdateGridBlock = 20, DidUpdateRow = 30, DidUpdateCell = 31, DidUpdateGrid = 40, diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 21106351c6..9f8d0c77e1 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -110,6 +110,7 @@ impl GridManager { } } + #[tracing::instrument(level = "trace", skip(self, pool), err)] async fn make_grid_editor( &self, grid_id: &str, @@ -175,11 +176,11 @@ pub async fn make_grid_view_data( grid_manager: Arc, build_context: BuildGridContext, ) -> FlowyResult { - let block_id = build_context.block_metas.block_id.clone(); + let block_id = build_context.block_meta.block_id.clone(); let grid_meta = GridMeta { grid_id: view_id.to_string(), fields: build_context.field_metas, - blocks: vec![build_context.block_metas], + blocks: vec![build_context.block_meta], }; // Create grid diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs index d5eaa2a6d8..326ae3ef4e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -27,7 +27,7 @@ pub enum GridNotification { Unknown = 0, DidCreateBlock = 11, - DidUpdateBlock = 20, + DidUpdateGridBlock = 20, DidUpdateRow = 30, DidUpdateCell = 31, DidUpdateGrid = 40, @@ -43,7 +43,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), 11 => ::std::option::Option::Some(GridNotification::DidCreateBlock), - 20 => ::std::option::Option::Some(GridNotification::DidUpdateBlock), + 20 => ::std::option::Option::Some(GridNotification::DidUpdateGridBlock), 30 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 31 => ::std::option::Option::Some(GridNotification::DidUpdateCell), 40 => ::std::option::Option::Some(GridNotification::DidUpdateGrid), @@ -56,7 +56,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { static values: &'static [GridNotification] = &[ GridNotification::Unknown, GridNotification::DidCreateBlock, - GridNotification::DidUpdateBlock, + GridNotification::DidUpdateGridBlock, GridNotification::DidUpdateRow, GridNotification::DidUpdateCell, GridNotification::DidUpdateGrid, @@ -89,11 +89,11 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x93\x01\n\x10GridNotification\x12\x0b\n\ - \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x12\n\x0eDidUp\ - dateBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x11\n\rDidUpdate\ - Cell\x10\x1f\x12\x11\n\rDidUpdateGrid\x10(\x12\x12\n\x0eDidUpdateField\ - \x10)b\x06proto3\ + \n\x17dart_notification.proto*\x97\x01\n\x10GridNotification\x12\x0b\n\ + \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x16\n\x12DidUp\ + dateGridBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x11\n\rDidUp\ + dateCell\x10\x1f\x12\x11\n\rDidUpdateGrid\x10(\x12\x12\n\x0eDidUpdateFie\ + ld\x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto index cbda705483..20cf529f3e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -3,7 +3,7 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; DidCreateBlock = 11; - DidUpdateBlock = 20; + DidUpdateGridBlock = 20; DidUpdateRow = 30; DidUpdateCell = 31; DidUpdateGrid = 40; diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs index b14f6641f3..1fcddbd4da 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -9,7 +9,7 @@ use dashmap::DashMap; use flowy_error::FlowyResult; use flowy_grid_data_model::entities::{ CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, - GridBlockOrder, RowMeta, RowMetaChangeset, RowOrder, + GridBlockOrder, GridBlockOrderChangeset, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{RevisionManager, RevisionPersistence}; @@ -70,8 +70,12 @@ impl GridBlockMetaEditorManager { ) -> FlowyResult { let _ = self.persistence.insert_or_update(&row_meta.block_id, &row_meta.id)?; let editor = self.get_editor(&row_meta.block_id).await?; + let row_order = RowOrder::from(&row_meta); let row_count = editor.create_row(row_meta, start_row_id).await?; - self.notify_block_did_update_row(block_id).await?; + + let _ = self + .notify_block_did_update_row(GridBlockOrderChangeset::from_update(block_id, vec![row_order])) + .await?; Ok(row_count) } @@ -81,14 +85,18 @@ impl GridBlockMetaEditorManager { ) -> FlowyResult> { let mut changesets = vec![]; for (block_id, row_metas) in rows_by_block_id { + let mut inserted_row_orders = vec![]; let editor = self.get_editor(&block_id).await?; let mut row_count = 0; - for row in &row_metas { + for row in row_metas { let _ = self.persistence.insert_or_update(&row.block_id, &row.id)?; - row_count = editor.create_row(row.clone(), None).await?; + inserted_row_orders.push(RowOrder::from(&row)); + row_count = editor.create_row(row, None).await?; } changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); - let _ = self.notify_block_did_update_row(&block_id).await?; + let _ = self + .notify_block_did_update_row(GridBlockOrderChangeset::from_insert(&block_id, inserted_row_orders)) + .await?; } Ok(changesets) @@ -97,7 +105,19 @@ impl GridBlockMetaEditorManager { pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; - let _ = self.notify_block_did_update_row(&editor.block_id).await?; + + match editor + .get_row_orders(Some(vec![Cow::Borrowed(&changeset.row_id)])) + .await? + .pop() + { + None => {} + Some(row_order) => { + let block_order_changeset = GridBlockOrderChangeset::from_update(&editor.block_id, vec![row_order]); + let _ = self.notify_block_did_update_row(block_order_changeset).await?; + } + } + Ok(()) } @@ -177,11 +197,10 @@ impl GridBlockMetaEditorManager { Ok(block_cell_metas) } - async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { - // let block_order: GridBlockOrder = block_id.into(); - // send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) - // .payload(block_order) - // .send(); + async fn notify_block_did_update_row(&self, changeset: GridBlockOrderChangeset) -> FlowyResult<()> { + send_dart_notification(&self.grid_id, GridNotification::DidUpdateGridBlock) + .payload(changeset) + .send(); Ok(()) } diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index 42b3453d20..9f09e4e975 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -274,6 +274,50 @@ impl GridBlockOrder { } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct GridBlockOrderChangeset { + #[pb(index = 1)] + pub block_id: String, + + #[pb(index = 2)] + pub inserted_rows: Vec, + + #[pb(index = 3)] + pub deleted_rows: Vec, + + #[pb(index = 4)] + pub updated_rows: Vec, +} + +impl GridBlockOrderChangeset { + pub fn from_insert(block_id: &str, inserted_rows: Vec) -> Self { + Self { + block_id: block_id.to_owned(), + inserted_rows, + deleted_rows: vec![], + updated_rows: vec![], + } + } + + pub fn from_delete(block_id: &str, deleted_rows: Vec) -> Self { + Self { + block_id: block_id.to_owned(), + inserted_rows: vec![], + deleted_rows, + updated_rows: vec![], + } + } + + pub fn from_update(block_id: &str, updated_rows: Vec) -> Self { + Self { + block_id: block_id.to_owned(), + inserted_rows: vec![], + deleted_rows: vec![], + updated_rows, + } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct GridBlock { #[pb(index = 1)] diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 7ccd96e955..b78b166802 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -409,7 +409,7 @@ pub struct BuildGridContext { pub field_metas: Vec, #[pb(index = 2)] - pub block_metas: GridBlockMeta, + pub block_meta: GridBlockMeta, #[pb(index = 3)] pub block_meta_data: GridBlockMetaData, @@ -417,16 +417,16 @@ pub struct BuildGridContext { impl std::default::Default for BuildGridContext { fn default() -> Self { - let grid_block = GridBlockMeta::new(); - let grid_block_meta_data = GridBlockMetaData { - block_id: grid_block.block_id.clone(), + let block_meta = GridBlockMeta::new(); + let block_meta_data = GridBlockMetaData { + block_id: block_meta.block_id.clone(), rows: vec![], }; Self { field_metas: vec![], - block_metas: grid_block, - block_meta_data: grid_block_meta_data, + block_meta, + block_meta_data, } } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index 944db183f9..44c51f4a21 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -2919,6 +2919,312 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockOrder { } } +#[derive(PartialEq,Clone,Default)] +pub struct GridBlockOrderChangeset { + // message fields + pub block_id: ::std::string::String, + pub inserted_rows: ::protobuf::RepeatedField, + pub deleted_rows: ::protobuf::RepeatedField, + pub updated_rows: ::protobuf::RepeatedField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a GridBlockOrderChangeset { + fn default() -> &'a GridBlockOrderChangeset { + ::default_instance() + } +} + +impl GridBlockOrderChangeset { + pub fn new() -> GridBlockOrderChangeset { + ::std::default::Default::default() + } + + // string block_id = 1; + + + pub fn get_block_id(&self) -> &str { + &self.block_id + } + pub fn clear_block_id(&mut self) { + self.block_id.clear(); + } + + // Param is passed by value, moved + pub fn set_block_id(&mut self, v: ::std::string::String) { + self.block_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_block_id(&mut self) -> &mut ::std::string::String { + &mut self.block_id + } + + // Take field + pub fn take_block_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) + } + + // repeated .RowOrder inserted_rows = 2; + + + pub fn get_inserted_rows(&self) -> &[RowOrder] { + &self.inserted_rows + } + pub fn clear_inserted_rows(&mut self) { + self.inserted_rows.clear(); + } + + // Param is passed by value, moved + pub fn set_inserted_rows(&mut self, v: ::protobuf::RepeatedField) { + self.inserted_rows = v; + } + + // Mutable pointer to the field. + pub fn mut_inserted_rows(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.inserted_rows + } + + // Take field + pub fn take_inserted_rows(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.inserted_rows, ::protobuf::RepeatedField::new()) + } + + // repeated .RowOrder deleted_rows = 3; + + + pub fn get_deleted_rows(&self) -> &[RowOrder] { + &self.deleted_rows + } + pub fn clear_deleted_rows(&mut self) { + self.deleted_rows.clear(); + } + + // Param is passed by value, moved + pub fn set_deleted_rows(&mut self, v: ::protobuf::RepeatedField) { + self.deleted_rows = v; + } + + // Mutable pointer to the field. + pub fn mut_deleted_rows(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.deleted_rows + } + + // Take field + pub fn take_deleted_rows(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.deleted_rows, ::protobuf::RepeatedField::new()) + } + + // repeated .RowOrder updated_rows = 4; + + + pub fn get_updated_rows(&self) -> &[RowOrder] { + &self.updated_rows + } + pub fn clear_updated_rows(&mut self) { + self.updated_rows.clear(); + } + + // Param is passed by value, moved + pub fn set_updated_rows(&mut self, v: ::protobuf::RepeatedField) { + self.updated_rows = v; + } + + // Mutable pointer to the field. + pub fn mut_updated_rows(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.updated_rows + } + + // Take field + pub fn take_updated_rows(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.updated_rows, ::protobuf::RepeatedField::new()) + } +} + +impl ::protobuf::Message for GridBlockOrderChangeset { + fn is_initialized(&self) -> bool { + for v in &self.inserted_rows { + if !v.is_initialized() { + return false; + } + }; + for v in &self.deleted_rows { + if !v.is_initialized() { + return false; + } + }; + for v in &self.updated_rows { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; + }, + 2 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.inserted_rows)?; + }, + 3 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.deleted_rows)?; + }, + 4 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.updated_rows)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.block_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.block_id); + } + for value in &self.inserted_rows { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + for value in &self.deleted_rows { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + for value in &self.updated_rows { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.block_id.is_empty() { + os.write_string(1, &self.block_id)?; + } + for v in &self.inserted_rows { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + for v in &self.deleted_rows { + os.write_tag(3, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + for v in &self.updated_rows { + os.write_tag(4, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> GridBlockOrderChangeset { + GridBlockOrderChangeset::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "block_id", + |m: &GridBlockOrderChangeset| { &m.block_id }, + |m: &mut GridBlockOrderChangeset| { &mut m.block_id }, + )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "inserted_rows", + |m: &GridBlockOrderChangeset| { &m.inserted_rows }, + |m: &mut GridBlockOrderChangeset| { &mut m.inserted_rows }, + )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "deleted_rows", + |m: &GridBlockOrderChangeset| { &m.deleted_rows }, + |m: &mut GridBlockOrderChangeset| { &mut m.deleted_rows }, + )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "updated_rows", + |m: &GridBlockOrderChangeset| { &m.updated_rows }, + |m: &mut GridBlockOrderChangeset| { &mut m.updated_rows }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "GridBlockOrderChangeset", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static GridBlockOrderChangeset { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(GridBlockOrderChangeset::new) + } +} + +impl ::protobuf::Clear for GridBlockOrderChangeset { + fn clear(&mut self) { + self.block_id.clear(); + self.inserted_rows.clear(); + self.deleted_rows.clear(); + self.updated_rows.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for GridBlockOrderChangeset { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for GridBlockOrderChangeset { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct GridBlock { // message fields @@ -5334,30 +5640,34 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\ \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\ - \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"E\n\tGridBlock\x12\x0e\n\ - \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ - 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ - \x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\ - \"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\x01\x20\ - \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ - \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\ - \x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepe\ - atedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\ - \n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\ - \x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\ - \x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10\ - CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ - \"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of\ - _start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.\ - FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etype\ - OptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartField\ - IdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\ - \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\ - \x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\ - locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\ - \x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\ - sb\x06proto3\ + \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"\xc0\x01\n\x17GridBlockOr\ + derChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12.\n\ + \rinserted_rows\x18\x02\x20\x03(\x0b2\t.RowOrderR\x0cinsertedRows\x12,\n\ + \x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0bdeletedRows\x12,\n\ + \x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0bupdatedRows\"E\n\t\ + GridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\ + \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08\ + field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\ + \x01(\tR\x07content\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07gri\ + d_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01\ + (\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\ + \n\x07content\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\ + \"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\ + \x05items\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\t\ + R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ + lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ + \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ + idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ + \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ + rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ + \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ + \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ + \x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPaylo\ + ad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_or\ + ders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\ + \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ + ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ + \x0bblockOrdersb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index 8ca8db2765..3468eb594d 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -3114,7 +3114,7 @@ impl ::protobuf::reflect::ProtobufValue for CellMetaChangeset { pub struct BuildGridContext { // message fields pub field_metas: ::protobuf::RepeatedField, - pub block_metas: ::protobuf::SingularPtrField, + pub block_meta: ::protobuf::SingularPtrField, pub block_meta_data: ::protobuf::SingularPtrField, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -3157,37 +3157,37 @@ impl BuildGridContext { ::std::mem::replace(&mut self.field_metas, ::protobuf::RepeatedField::new()) } - // .GridBlockMeta block_metas = 2; + // .GridBlockMeta block_meta = 2; - pub fn get_block_metas(&self) -> &GridBlockMeta { - self.block_metas.as_ref().unwrap_or_else(|| ::default_instance()) + pub fn get_block_meta(&self) -> &GridBlockMeta { + self.block_meta.as_ref().unwrap_or_else(|| ::default_instance()) } - pub fn clear_block_metas(&mut self) { - self.block_metas.clear(); + pub fn clear_block_meta(&mut self) { + self.block_meta.clear(); } - pub fn has_block_metas(&self) -> bool { - self.block_metas.is_some() + pub fn has_block_meta(&self) -> bool { + self.block_meta.is_some() } // Param is passed by value, moved - pub fn set_block_metas(&mut self, v: GridBlockMeta) { - self.block_metas = ::protobuf::SingularPtrField::some(v); + pub fn set_block_meta(&mut self, v: GridBlockMeta) { + self.block_meta = ::protobuf::SingularPtrField::some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_block_metas(&mut self) -> &mut GridBlockMeta { - if self.block_metas.is_none() { - self.block_metas.set_default(); + pub fn mut_block_meta(&mut self) -> &mut GridBlockMeta { + if self.block_meta.is_none() { + self.block_meta.set_default(); } - self.block_metas.as_mut().unwrap() + self.block_meta.as_mut().unwrap() } // Take field - pub fn take_block_metas(&mut self) -> GridBlockMeta { - self.block_metas.take().unwrap_or_else(|| GridBlockMeta::new()) + pub fn take_block_meta(&mut self) -> GridBlockMeta { + self.block_meta.take().unwrap_or_else(|| GridBlockMeta::new()) } // .GridBlockMetaData block_meta_data = 3; @@ -3231,7 +3231,7 @@ impl ::protobuf::Message for BuildGridContext { return false; } }; - for v in &self.block_metas { + for v in &self.block_meta { if !v.is_initialized() { return false; } @@ -3252,7 +3252,7 @@ impl ::protobuf::Message for BuildGridContext { ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.field_metas)?; }, 2 => { - ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block_metas)?; + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block_meta)?; }, 3 => { ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.block_meta_data)?; @@ -3273,7 +3273,7 @@ impl ::protobuf::Message for BuildGridContext { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; - if let Some(ref v) = self.block_metas.as_ref() { + if let Some(ref v) = self.block_meta.as_ref() { let len = v.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; } @@ -3292,7 +3292,7 @@ impl ::protobuf::Message for BuildGridContext { os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; }; - if let Some(ref v) = self.block_metas.as_ref() { + if let Some(ref v) = self.block_meta.as_ref() { os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; @@ -3346,9 +3346,9 @@ impl ::protobuf::Message for BuildGridContext { |m: &mut BuildGridContext| { &mut m.field_metas }, )); fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "block_metas", - |m: &BuildGridContext| { &m.block_metas }, - |m: &mut BuildGridContext| { &mut m.block_metas }, + "block_meta", + |m: &BuildGridContext| { &m.block_meta }, + |m: &mut BuildGridContext| { &mut m.block_meta }, )); fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "block_meta_data", @@ -3372,7 +3372,7 @@ impl ::protobuf::Message for BuildGridContext { impl ::protobuf::Clear for BuildGridContext { fn clear(&mut self) { self.field_metas.clear(); - self.block_metas.clear(); + self.block_meta.clear(); self.block_meta_data.clear(); self.unknown_fields.clear(); } @@ -3498,14 +3498,13 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06\ gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08fie\ ld_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\ - \tH\0R\x04dataB\r\n\x0bone_of_data\"\xac\x01\n\x10BuildGridContext\x12+\ - \n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\ - \x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12\ - :\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x12.GridBlockMetaDataR\rblo\ - ckMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\ - \x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\ - \x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06prot\ - o3\ + \tH\0R\x04dataB\r\n\x0bone_of_data\"\xaa\x01\n\x10BuildGridContext\x12+\ + \n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12-\n\ + \nblock_meta\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\tblockMeta\x12:\n\ + \x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x12.GridBlockMetaDataR\rblockM\ + etaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\ + \x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\ + \x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index b1bf045cd7..8c1b48e7a4 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -59,6 +59,12 @@ message GridBlockOrder { string block_id = 1; repeated RowOrder row_orders = 2; } +message GridBlockOrderChangeset { + string block_id = 1; + repeated RowOrder inserted_rows = 2; + repeated RowOrder deleted_rows = 3; + repeated RowOrder updated_rows = 4; +} message GridBlock { string id = 1; repeated RowOrder row_orders = 2; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 2cf0f9b2af..dcc8d5f91c 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -63,7 +63,7 @@ message CellMetaChangeset { } message BuildGridContext { repeated FieldMeta field_metas = 1; - GridBlockMeta block_metas = 2; + GridBlockMeta block_meta = 2; GridBlockMetaData block_meta_data = 3; } enum FieldType { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index bd5ea1d1a6..f416b55141 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -16,7 +16,7 @@ pub type GridBlockMetaDeltaBuilder = PlainTextDeltaBuilder; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct GridBlockMetaPad { block_id: String, - row_metas: Vec>, + rows: Vec>, #[serde(skip)] pub(crate) delta: GridBlockMetaDelta, @@ -32,11 +32,7 @@ impl GridBlockMetaPad { })?; let block_id = meta_data.block_id; let rows = meta_data.rows.into_iter().map(Arc::new).collect::>>(); - Ok(Self { - block_id, - row_metas: rows, - delta, - }) + Ok(Self { block_id, rows, delta }) } pub fn from_revisions(_grid_id: &str, revisions: Vec) -> CollaborateResult { @@ -80,10 +76,10 @@ impl GridBlockMetaPad { T: AsRef + ToOwned + ?Sized, { match row_ids { - None => Ok(self.row_metas.to_vec()), + None => Ok(self.rows.to_vec()), Some(row_ids) => { let row_map = self - .row_metas + .rows .iter() .map(|row| (row.id.as_str(), row.clone())) .collect::>>(); @@ -122,7 +118,7 @@ impl GridBlockMetaPad { } pub fn number_of_rows(&self) -> i32 { - self.row_metas.len() as i32 + self.rows.len() as i32 } pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult> { @@ -155,7 +151,7 @@ impl GridBlockMetaPad { F: for<'a> FnOnce(&'a mut Vec>) -> CollaborateResult>, { let cloned_self = self.clone(); - match f(&mut self.row_metas)? { + match f(&mut self.rows)? { None => Ok(None), Some(_) => { let old = cloned_self.to_json()?; @@ -228,7 +224,7 @@ impl std::default::Default for GridBlockMetaPad { let delta = make_block_meta_delta(&block_meta_data); GridBlockMetaPad { block_id: block_meta_data.block_id, - row_metas: block_meta_data.rows.into_iter().map(Arc::new).collect::>(), + rows: block_meta_data.rows.into_iter().map(Arc::new).collect::>(), delta, } } @@ -254,7 +250,7 @@ mod tests { let change = pad.add_row_meta(row, None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":29},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# + r#"[{"retain":24},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cells\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); } @@ -268,24 +264,24 @@ mod tests { let change = pad.add_row_meta(row_1.clone(), None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":29},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# + r#"[{"retain":24},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cells\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); let change = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":106},{"insert":",{\"id\":\"2\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# + r#"[{"retain":90},{"insert":",{\"id\":\"2\",\"block_id\":\"1\",\"cells\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); let change = pad.add_row_meta(row_3.clone(), Some("2".to_string())).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":114},{"insert":"3\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false},{\"id\":\""},{"retain":72}]"# + r#"[{"retain":157},{"insert":",{\"id\":\"3\",\"block_id\":\"1\",\"cells\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); - assert_eq!(*pad.row_metas[0], row_1); - assert_eq!(*pad.row_metas[1], row_3); - assert_eq!(*pad.row_metas[2], row_2); + assert_eq!(*pad.rows[0], row_1); + assert_eq!(*pad.rows[1], row_2); + assert_eq!(*pad.rows[2], row_3); } fn test_row_meta(id: &str, pad: &GridBlockMetaPad) -> RowMeta { @@ -309,9 +305,9 @@ mod tests { let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); let _ = pad.add_row_meta(row_3.clone(), Some("1".to_string())).unwrap().unwrap(); - assert_eq!(*pad.row_metas[0], row_3); - assert_eq!(*pad.row_metas[1], row_1); - assert_eq!(*pad.row_metas[2], row_2); + assert_eq!(*pad.rows[0], row_3); + assert_eq!(*pad.rows[1], row_1); + assert_eq!(*pad.rows[2], row_2); } #[test] @@ -325,9 +321,9 @@ mod tests { let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); let _ = pad.add_row_meta(row_3.clone(), Some("".to_string())).unwrap().unwrap(); - assert_eq!(*pad.row_metas[0], row_3); - assert_eq!(*pad.row_metas[1], row_1); - assert_eq!(*pad.row_metas[2], row_2); + assert_eq!(*pad.rows[0], row_3); + assert_eq!(*pad.rows[1], row_1); + assert_eq!(*pad.rows[2], row_2); } #[test] @@ -346,7 +342,7 @@ mod tests { let change = pad.delete_rows(vec![Cow::Borrowed(&row.id)]).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":29},{"delete":77},{"retain":2}]"# + r#"[{"retain":24},{"delete":66},{"retain":2}]"# ); assert_eq!(pad.delta_str(), pre_delta_str); @@ -375,18 +371,17 @@ mod tests { assert_eq!( change.delta.to_delta_str(), - r#"[{"retain":85},{"insert":"10"},{"retain":15},{"insert":"tru"},{"delete":4},{"retain":4}]"# + r#"[{"retain":69},{"insert":"10"},{"retain":15},{"insert":"tru"},{"delete":4},{"retain":4}]"# ); assert_eq!( pad.to_json().unwrap(), - r#"{"block_id":"1","row_metas":[{"id":"1","block_id":"1","cell_by_field_id":{},"height":100,"visibility":true}]}"# + r#"{"block_id":"1","rows":[{"id":"1","block_id":"1","cells":{},"height":100,"visibility":true}]}"# ); } fn test_pad() -> GridBlockMetaPad { - let delta = - GridBlockMetaDelta::from_delta_str(r#"[{"insert":"{\"block_id\":\"1\",\"row_metas\":[]}"}]"#).unwrap(); + let delta = GridBlockMetaDelta::from_delta_str(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap(); GridBlockMetaPad::from_delta(delta).unwrap() } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs index d9c5d17280..7a1e140140 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs @@ -13,9 +13,9 @@ impl GridBuilder { } pub fn add_empty_row(mut self) -> Self { - let row = RowMeta::new(&self.build_context.block_metas.block_id); + let row = RowMeta::new(&self.build_context.block_meta.block_id); self.build_context.block_meta_data.rows.push(row); - self.build_context.block_metas.row_count += 1; + self.build_context.block_meta.row_count += 1; self } @@ -57,7 +57,7 @@ mod tests { let grid_meta = GridMeta { grid_id, fields: build_context.field_metas, - blocks: vec![build_context.block_metas], + blocks: vec![build_context.block_meta], }; let grid_meta_delta = make_grid_delta(&grid_meta); From f01d3250ae1201e83479d73914d8e5ea60352f5d Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 14:24:12 +0800 Subject: [PATCH 7/9] chore: reload after delete or insert row --- .../workspace/application/grid/grid_bloc.dart | 67 ++-- .../application/grid/row/row_service.dart | 15 +- .../plugins/grid/src/grid_page.dart | 8 +- .../src/widgets/row/row_action_sheet.dart | 23 +- .../flowy-grid-data-model/grid.pb.dart | 82 ++++- .../flowy-grid-data-model/grid.pbjson.dart | 18 +- .../src/services/block_meta_editor.rs | 22 +- .../src/services/block_meta_manager.rs | 36 ++- .../field/type_options/date_type_option.rs | 2 +- .../type_options/selection_type_option.rs | 8 +- .../flowy-grid/src/services/grid_editor.rs | 9 +- .../flowy-grid/src/services/row/row_loader.rs | 2 +- .../flowy-grid/tests/grid/grid_test.rs | 2 +- .../src/entities/grid.rs | 26 +- .../src/protobuf/model/grid.rs | 304 ++++++++++++++++-- .../src/protobuf/proto/grid.proto | 6 +- .../src/client_grid/grid_block_meta_pad.rs | 20 +- 17 files changed, 533 insertions(+), 117 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 44c048bac3..bf56b9d864 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -34,8 +34,6 @@ class GridBloc extends Bloc { createRow: (_CreateRow value) { _gridService.createRow(gridId: view.id); }, - delete: (_Delete value) {}, - rename: (_Rename value) {}, updateDesc: (_Desc value) {}, didReceiveRowUpdate: (_DidReceiveRowUpdate value) { emit(state.copyWith(rows: value.rows)); @@ -71,14 +69,18 @@ class GridBloc extends Bloc { _gridListener.rowsUpdateNotifier.addPublishListener((result) { result.fold((gridBlockChangeset) { for (final changeset in gridBlockChangeset) { - if (changeset.insertedRows.isNotEmpty) {} + if (changeset.insertedRows.isNotEmpty) { + _insertRows(changeset.insertedRows); + } - if (changeset.deletedRows.isNotEmpty) {} + if (changeset.deletedRows.isNotEmpty) { + _deleteRows(changeset.deletedRows); + } - if (changeset.updatedRows.isNotEmpty) {} + if (changeset.updatedRows.isNotEmpty) { + _updateRows(changeset.updatedRows); + } } - - // add(GridEvent.didReceiveRowUpdate(_buildRows(blockOrders))); }, (err) => Log.error(err)); }); _gridListener.start(); @@ -111,29 +113,50 @@ class GridBloc extends Bloc { ); } - List _buildRows(List blockOrders) { - List rows = []; - for (final blockOrder in blockOrders) { - rows.addAll(blockOrder.rowOrders.map( - (rowOrder) => GridBlockRow( - gridId: view.id, - rowId: rowOrder.rowId, - height: rowOrder.height.toDouble(), - ), - )); + void _deleteRows(List deletedRows) { + final List rows = List.from(state.rows); + rows.retainWhere( + (row) => deletedRows.where((deletedRow) => deletedRow.rowId == row.rowId).isEmpty, + ); + + add(GridEvent.didReceiveRowUpdate(rows)); + } + + void _insertRows(List createdRows) { + final List rows = List.from(state.rows); + for (final newRow in createdRows) { + if (newRow.hasIndex()) { + rows.insert(newRow.index, newRow.rowOrder); + } else { + rows.add(newRow.rowOrder); + } } - return rows; + add(GridEvent.didReceiveRowUpdate(rows)); + } + + void _updateRows(List updatedRows) { + final List rows = List.from(state.rows); + for (final updatedRow in updatedRows) { + final index = rows.indexWhere((row) => row.rowId == updatedRow.rowId); + if (index != -1) { + rows.removeAt(index); + rows.insert(index, updatedRow); + } + } + add(GridEvent.didReceiveRowUpdate(rows)); + } + + List _buildRows(List blockOrders) { + return blockOrders.expand((blockOrder) => blockOrder.rowOrders).toList(); } } @freezed class GridEvent with _$GridEvent { const factory GridEvent.initial() = InitialGrid; - const factory GridEvent.rename(String gridId, String name) = _Rename; const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; - const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; - const factory GridEvent.didReceiveRowUpdate(List rows) = _DidReceiveRowUpdate; + const factory GridEvent.didReceiveRowUpdate(List rows) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; } @@ -142,7 +165,7 @@ class GridState with _$GridState { const factory GridState({ required GridLoadingState loadingState, required List fields, - required List rows, + required List rows, required Option grid, }) = _GridState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index f87d9f8574..643a2c649e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -65,21 +65,12 @@ class RowData with _$RowData { required double height, }) = _RowData; - factory RowData.fromBlockRow(GridBlockRow row, List fields) { + factory RowData.fromBlockRow(String gridId, RowOrder row, List fields) { return RowData( - gridId: row.gridId, + gridId: gridId, rowId: row.rowId, fields: fields, - height: row.height, + height: row.height.toDouble(), ); } } - -@freezed -class GridBlockRow with _$GridBlockRow { - const factory GridBlockRow({ - required String gridId, - required String rowId, - required double height, - }) = _GridBlockRow; -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 6ff3852de5..8ca787f65c 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -73,7 +73,7 @@ class FlowyGrid extends StatefulWidget { class _FlowyGridState extends State { final _scrollController = GridScrollController(); - final _key = GlobalKey(); + // final _key = GlobalKey(); @override void dispose() { @@ -105,7 +105,7 @@ class _FlowyGridState extends State { slivers: [ _renderToolbar(gridId), GridHeader(gridId: gridId, fields: List.from(state.fields)), - _renderRows(context), + _renderRows(gridId: gridId, context: context), const GridFooter(), ], ), @@ -147,7 +147,7 @@ class _FlowyGridState extends State { ); } - Widget _renderRows(BuildContext context) { + Widget _renderRows({required String gridId, required BuildContext context}) { return BlocBuilder( buildWhen: (previous, current) { final rowChanged = previous.rows.length != current.rows.length; @@ -160,7 +160,7 @@ class _FlowyGridState extends State { (context, index) { final blockRow = context.read().state.rows[index]; final fields = context.read().state.fields; - final rowData = RowData.fromBlockRow(blockRow, fields); + final rowData = RowData.fromBlockRow(gridId, blockRow, fields); return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)); }, childCount: context.read().state.rows.length, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart index f1ff46af08..458e934756 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_action_sheet.dart @@ -84,10 +84,16 @@ class _RowActionCell extends StatelessWidget { return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( - text: FlowyText.medium(action.title(), fontSize: 12), + text: FlowyText.medium( + action.title(), + fontSize: 12, + color: action.enable() ? theme.textColor : theme.shader3, + ), hoverColor: theme.hover, onTap: () { - action.performAction(context); + if (action.enable()) { + action.performAction(context); + } onDismissed(); }, leftIcon: svgWidget(action.iconName(), color: theme.iconColor), @@ -120,13 +126,22 @@ extension _RowActionExtension on _RowAction { } } + bool enable() { + switch (this) { + case _RowAction.duplicate: + return false; + case _RowAction.delete: + return true; + } + } + void performAction(BuildContext context) { switch (this) { case _RowAction.duplicate: - // context.read().add(const RowActionSheetEvent.duplicateRow()); + context.read().add(const RowActionSheetEvent.duplicateRow()); break; case _RowAction.delete: - // context.read().add(const RowActionSheetEvent.deleteRow()); + context.read().add(const RowActionSheetEvent.deleteRow()); break; } } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index f613504047..e0fdcc33a5 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -858,7 +858,7 @@ class GridBlockOrder extends $pb.GeneratedMessage { class GridBlockOrderChangeset extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockOrderChangeset', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') - ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertedRows', $pb.PbFieldType.PM, subBuilder: IndexRowOrder.create) ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deletedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) ..pc(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'updatedRows', $pb.PbFieldType.PM, subBuilder: RowOrder.create) ..hasRequiredFields = false @@ -867,7 +867,7 @@ class GridBlockOrderChangeset extends $pb.GeneratedMessage { GridBlockOrderChangeset._() : super(); factory GridBlockOrderChangeset({ $core.String? blockId, - $core.Iterable? insertedRows, + $core.Iterable? insertedRows, $core.Iterable? deletedRows, $core.Iterable? updatedRows, }) { @@ -917,7 +917,7 @@ class GridBlockOrderChangeset extends $pb.GeneratedMessage { void clearBlockId() => clearField(1); @$pb.TagNumber(2) - $core.List get insertedRows => $_getList(1); + $core.List get insertedRows => $_getList(1); @$pb.TagNumber(3) $core.List get deletedRows => $_getList(2); @@ -926,6 +926,82 @@ class GridBlockOrderChangeset extends $pb.GeneratedMessage { $core.List get updatedRows => $_getList(3); } +enum IndexRowOrder_OneOfIndex { + index_, + notSet +} + +class IndexRowOrder extends $pb.GeneratedMessage { + static const $core.Map<$core.int, IndexRowOrder_OneOfIndex> _IndexRowOrder_OneOfIndexByTag = { + 2 : IndexRowOrder_OneOfIndex.index_, + 0 : IndexRowOrder_OneOfIndex.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IndexRowOrder', createEmptyInstance: create) + ..oo(0, [2]) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowOrder', subBuilder: RowOrder.create) + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'index', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + IndexRowOrder._() : super(); + factory IndexRowOrder({ + RowOrder? rowOrder, + $core.int? index, + }) { + final _result = create(); + if (rowOrder != null) { + _result.rowOrder = rowOrder; + } + if (index != null) { + _result.index = index; + } + return _result; + } + factory IndexRowOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory IndexRowOrder.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + IndexRowOrder clone() => IndexRowOrder()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + IndexRowOrder copyWith(void Function(IndexRowOrder) updates) => super.copyWith((message) => updates(message as IndexRowOrder)) as IndexRowOrder; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static IndexRowOrder create() => IndexRowOrder._(); + IndexRowOrder createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static IndexRowOrder getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static IndexRowOrder? _defaultInstance; + + IndexRowOrder_OneOfIndex whichOneOfIndex() => _IndexRowOrder_OneOfIndexByTag[$_whichOneof(0)]!; + void clearOneOfIndex() => clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + RowOrder get rowOrder => $_getN(0); + @$pb.TagNumber(1) + set rowOrder(RowOrder v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasRowOrder() => $_has(0); + @$pb.TagNumber(1) + void clearRowOrder() => clearField(1); + @$pb.TagNumber(1) + RowOrder ensureRowOrder() => $_ensure(0); + + @$pb.TagNumber(2) + $core.int get index => $_getIZ(1); + @$pb.TagNumber(2) + set index($core.int v) { $_setSignedInt32(1, v); } + @$pb.TagNumber(2) + $core.bool hasIndex() => $_has(1); + @$pb.TagNumber(2) + void clearIndex() => clearField(2); +} + class GridBlock extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlock', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 0c1abf778e..0a565b2b49 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -176,14 +176,28 @@ const GridBlockOrderChangeset$json = const { '1': 'GridBlockOrderChangeset', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, - const {'1': 'inserted_rows', '3': 2, '4': 3, '5': 11, '6': '.RowOrder', '10': 'insertedRows'}, + const {'1': 'inserted_rows', '3': 2, '4': 3, '5': 11, '6': '.IndexRowOrder', '10': 'insertedRows'}, const {'1': 'deleted_rows', '3': 3, '4': 3, '5': 11, '6': '.RowOrder', '10': 'deletedRows'}, const {'1': 'updated_rows', '3': 4, '4': 3, '5': 11, '6': '.RowOrder', '10': 'updatedRows'}, ], }; /// Descriptor for `GridBlockOrderChangeset`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockOrderChangesetDescriptor = $convert.base64Decode('ChdHcmlkQmxvY2tPcmRlckNoYW5nZXNldBIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIuCg1pbnNlcnRlZF9yb3dzGAIgAygLMgkuUm93T3JkZXJSDGluc2VydGVkUm93cxIsCgxkZWxldGVkX3Jvd3MYAyADKAsyCS5Sb3dPcmRlclILZGVsZXRlZFJvd3MSLAoMdXBkYXRlZF9yb3dzGAQgAygLMgkuUm93T3JkZXJSC3VwZGF0ZWRSb3dz'); +final $typed_data.Uint8List gridBlockOrderChangesetDescriptor = $convert.base64Decode('ChdHcmlkQmxvY2tPcmRlckNoYW5nZXNldBIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIzCg1pbnNlcnRlZF9yb3dzGAIgAygLMg4uSW5kZXhSb3dPcmRlclIMaW5zZXJ0ZWRSb3dzEiwKDGRlbGV0ZWRfcm93cxgDIAMoCzIJLlJvd09yZGVyUgtkZWxldGVkUm93cxIsCgx1cGRhdGVkX3Jvd3MYBCADKAsyCS5Sb3dPcmRlclILdXBkYXRlZFJvd3M='); +@$core.Deprecated('Use indexRowOrderDescriptor instead') +const IndexRowOrder$json = const { + '1': 'IndexRowOrder', + '2': const [ + const {'1': 'row_order', '3': 1, '4': 1, '5': 11, '6': '.RowOrder', '10': 'rowOrder'}, + const {'1': 'index', '3': 2, '4': 1, '5': 5, '9': 0, '10': 'index'}, + ], + '8': const [ + const {'1': 'one_of_index'}, + ], +}; + +/// Descriptor for `IndexRowOrder`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List indexRowOrderDescriptor = $convert.base64Decode('Cg1JbmRleFJvd09yZGVyEiYKCXJvd19vcmRlchgBIAEoCzIJLlJvd09yZGVyUghyb3dPcmRlchIWCgVpbmRleBgCIAEoBUgAUgVpbmRleEIOCgxvbmVfb2ZfaW5kZXg='); @$core.Deprecated('Use gridBlockDescriptor instead') const GridBlock$json = const { '1': 'GridBlock', diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs index 1f8e2e2006..652617146b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs @@ -42,17 +42,30 @@ impl ClientGridBlockMetaEditor { }) } - pub(crate) async fn create_row(&self, row: RowMeta, start_row_id: Option) -> FlowyResult { + /// return current number of rows and the inserted index. The inserted index will be None if the start_row_id is None + pub(crate) async fn create_row( + &self, + row: RowMeta, + start_row_id: Option, + ) -> FlowyResult<(i32, Option)> { let mut row_count = 0; + let mut row_index = None; let _ = self .modify(|pad| { + if let Some(start_row_id) = start_row_id.as_ref() { + match pad.index_of_row(start_row_id) { + None => {} + Some(index) => row_index = Some(index + 1), + } + } + let change = pad.add_row_meta(row, start_row_id)?; row_count = pad.number_of_rows(); Ok(change) }) .await?; - Ok(row_count) + Ok((row_count, row_index)) } pub async fn delete_rows(&self, ids: Vec>) -> FlowyResult { @@ -89,7 +102,10 @@ impl ClientGridBlockMetaEditor { Ok(cell_metas) } - pub async fn get_row_orders(&self, row_ids: Option>>) -> FlowyResult> { + pub async fn get_row_orders(&self, row_ids: Option>>) -> FlowyResult> + where + T: AsRef + ToOwned + ?Sized, + { let row_orders = self .pad .read() diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs index 1fcddbd4da..0c4d1a2efd 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -9,7 +9,7 @@ use dashmap::DashMap; use flowy_error::FlowyResult; use flowy_grid_data_model::entities::{ CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, - GridBlockOrder, GridBlockOrderChangeset, RowMeta, RowMetaChangeset, RowOrder, + GridBlockOrderChangeset, IndexRowOrder, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{RevisionManager, RevisionPersistence}; @@ -70,11 +70,13 @@ impl GridBlockMetaEditorManager { ) -> FlowyResult { let _ = self.persistence.insert_or_update(&row_meta.block_id, &row_meta.id)?; let editor = self.get_editor(&row_meta.block_id).await?; - let row_order = RowOrder::from(&row_meta); - let row_count = editor.create_row(row_meta, start_row_id).await?; + + let mut index_row_order = IndexRowOrder::from(&row_meta); + let (row_count, row_index) = editor.create_row(row_meta, start_row_id).await?; + index_row_order.index = row_index; let _ = self - .notify_block_did_update_row(GridBlockOrderChangeset::from_update(block_id, vec![row_order])) + .notify_did_update_grid_rows(GridBlockOrderChangeset::from_insert(block_id, vec![index_row_order])) .await?; Ok(row_count) } @@ -90,12 +92,13 @@ impl GridBlockMetaEditorManager { let mut row_count = 0; for row in row_metas { let _ = self.persistence.insert_or_update(&row.block_id, &row.id)?; - inserted_row_orders.push(RowOrder::from(&row)); - row_count = editor.create_row(row, None).await?; + inserted_row_orders.push(IndexRowOrder::from(&row)); + row_count = editor.create_row(row, None).await?.0; } changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); + let _ = self - .notify_block_did_update_row(GridBlockOrderChangeset::from_insert(&block_id, inserted_row_orders)) + .notify_did_update_grid_rows(GridBlockOrderChangeset::from_insert(&block_id, inserted_row_orders)) .await?; } @@ -114,13 +117,26 @@ impl GridBlockMetaEditorManager { None => {} Some(row_order) => { let block_order_changeset = GridBlockOrderChangeset::from_update(&editor.block_id, vec![row_order]); - let _ = self.notify_block_did_update_row(block_order_changeset).await?; + let _ = self.notify_did_update_grid_rows(block_order_changeset).await?; } } Ok(()) } + 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_editor(&block_id).await?; + let row_orders = editor.get_row_orders(Some(vec![Cow::Borrowed(&row_id)])).await?; + let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?; + let _ = self + .notify_did_update_grid_rows(GridBlockOrderChangeset::from_delete(&block_id, row_orders)) + .await?; + + Ok(()) + } + pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { let mut changesets = vec![]; for block_order in group_row_orders(row_orders) { @@ -167,7 +183,7 @@ impl GridBlockMetaEditorManager { pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult> { let editor = self.get_editor(block_id).await?; - editor.get_row_orders(None).await + editor.get_row_orders::<&str>(None).await } pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { @@ -197,7 +213,7 @@ impl GridBlockMetaEditorManager { Ok(block_cell_metas) } - async fn notify_block_did_update_row(&self, changeset: GridBlockOrderChangeset) -> FlowyResult<()> { + async fn notify_did_update_grid_rows(&self, changeset: GridBlockOrderChangeset) -> FlowyResult<()> { send_dart_notification(&self.grid_id, GridNotification::DidUpdateGridBlock) .payload(changeset) .send(); diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index bf63228287..f6029e360c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -70,7 +70,7 @@ impl CellDataOperation for DateTypeOption { ) -> Result { let changeset = changeset.into(); if changeset.parse::().is_err() || changeset.parse::().is_err() { - return Err(FlowyError::internal().context(format!("Parse {} failed", changeset.to_string()))); + return Err(FlowyError::internal().context(format!("Parse {} failed", changeset))); }; Ok(TypeOptionCellData::new(changeset, self.field_type()).json()) diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 30cd36b122..36ef357830 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -469,7 +469,7 @@ mod tests { let single_select = SingleSelectTypeOptionBuilder::default() .option(google_option.clone()) .option(facebook_option.clone()) - .option(twitter_option.clone()); + .option(twitter_option); let field_meta = FieldBuilder::new(single_select) .name("Platform") @@ -478,7 +478,7 @@ mod tests { let type_option = SingleSelectTypeOption::from(&field_meta); - let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); + let option_ids = vec![google_option.id.clone(), facebook_option.id].join(SELECTION_IDS_SEPARATOR); let data = SelectOptionCellChangeset::from_insert(&option_ids).cell_data(); let cell_data = type_option.apply_changeset(data, None).unwrap(); assert_eq!(type_option.decode_cell_data(cell_data, &field_meta), google_option.name,); @@ -511,7 +511,7 @@ mod tests { let multi_select = MultiSelectTypeOptionBuilder::default() .option(google_option.clone()) .option(facebook_option.clone()) - .option(twitter_option.clone()); + .option(twitter_option); let field_meta = FieldBuilder::new(multi_select) .name("Platform") @@ -525,7 +525,7 @@ mod tests { let cell_data = type_option.apply_changeset(data, None).unwrap(); assert_eq!( type_option.decode_cell_data(cell_data, &field_meta), - vec![google_option.name.clone(), facebook_option.name.clone()].join(SELECTION_IDS_SEPARATOR), + vec![google_option.name.clone(), facebook_option.name].join(SELECTION_IDS_SEPARATOR), ); let data = SelectOptionCellChangeset::from_insert(&google_option.id).cell_data(); 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 44fc4c4e76..b94efcef99 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -268,11 +268,12 @@ impl ClientGridEditor { } } pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> { - todo!() + let _ = self.block_meta_manager.delete_row(row_id).await?; + Ok(()) } - pub async fn duplicate_row(&self, row_id: &str) -> FlowyResult<()> { - todo!() + pub async fn duplicate_row(&self, _row_id: &str) -> FlowyResult<()> { + Ok(()) } pub async fn get_cell(&self, params: &CellIdentifier) -> Option { @@ -429,7 +430,7 @@ impl ClientGridEditor { debug_assert!(field_metas.len() == 1); if let Some(field_meta) = field_metas.pop() { - send_dart_notification(&field_id, GridNotification::DidUpdateField) + send_dart_notification(field_id, GridNotification::DidUpdateField) .payload(field_meta) .send(); } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index 26e889f1af..491b87b4c9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -4,7 +4,7 @@ use flowy_grid_data_model::entities::{ Cell, CellMeta, FieldMeta, GridBlock, GridBlockOrder, RepeatedGridBlock, Row, RowMeta, RowOrder, }; use rayon::iter::{IntoParallelIterator, ParallelIterator}; -use std::borrow::Cow; + use std::collections::HashMap; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index f031c00743..29396a7c4b 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -4,7 +4,7 @@ use chrono::NaiveDateTime; use flowy_grid::services::field::{ MultiSelectTypeOption, SelectOption, SelectOptionCellChangeset, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, }; -use flowy_grid::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation, CreateRowMetaBuilder}; +use flowy_grid::services::row::{decode_cell_data, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ CellMetaChangeset, FieldChangesetParams, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, TypeOptionDataEntry, diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index 9f09e4e975..d517b7f230 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -280,7 +280,7 @@ pub struct GridBlockOrderChangeset { pub block_id: String, #[pb(index = 2)] - pub inserted_rows: Vec, + pub inserted_rows: Vec, #[pb(index = 3)] pub deleted_rows: Vec, @@ -289,8 +289,30 @@ pub struct GridBlockOrderChangeset { pub updated_rows: Vec, } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct IndexRowOrder { + #[pb(index = 1)] + pub row_order: RowOrder, + + #[pb(index = 2, one_of)] + pub index: Option, +} + +impl std::convert::From for IndexRowOrder { + fn from(row_order: RowOrder) -> Self { + Self { row_order, index: None } + } +} + +impl std::convert::From<&RowMeta> for IndexRowOrder { + fn from(row: &RowMeta) -> Self { + let row_order = RowOrder::from(row); + Self::from(row_order) + } +} + impl GridBlockOrderChangeset { - pub fn from_insert(block_id: &str, inserted_rows: Vec) -> Self { + pub fn from_insert(block_id: &str, inserted_rows: Vec) -> Self { Self { block_id: block_id.to_owned(), inserted_rows, diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index 44c51f4a21..3d86c28702 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -2923,7 +2923,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockOrder { pub struct GridBlockOrderChangeset { // message fields pub block_id: ::std::string::String, - pub inserted_rows: ::protobuf::RepeatedField, + pub inserted_rows: ::protobuf::RepeatedField, pub deleted_rows: ::protobuf::RepeatedField, pub updated_rows: ::protobuf::RepeatedField, // special fields @@ -2968,10 +2968,10 @@ impl GridBlockOrderChangeset { ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } - // repeated .RowOrder inserted_rows = 2; + // repeated .IndexRowOrder inserted_rows = 2; - pub fn get_inserted_rows(&self) -> &[RowOrder] { + pub fn get_inserted_rows(&self) -> &[IndexRowOrder] { &self.inserted_rows } pub fn clear_inserted_rows(&mut self) { @@ -2979,17 +2979,17 @@ impl GridBlockOrderChangeset { } // Param is passed by value, moved - pub fn set_inserted_rows(&mut self, v: ::protobuf::RepeatedField) { + pub fn set_inserted_rows(&mut self, v: ::protobuf::RepeatedField) { self.inserted_rows = v; } // Mutable pointer to the field. - pub fn mut_inserted_rows(&mut self) -> &mut ::protobuf::RepeatedField { + pub fn mut_inserted_rows(&mut self) -> &mut ::protobuf::RepeatedField { &mut self.inserted_rows } // Take field - pub fn take_inserted_rows(&mut self) -> ::protobuf::RepeatedField { + pub fn take_inserted_rows(&mut self) -> ::protobuf::RepeatedField { ::std::mem::replace(&mut self.inserted_rows, ::protobuf::RepeatedField::new()) } @@ -3174,7 +3174,7 @@ impl ::protobuf::Message for GridBlockOrderChangeset { |m: &GridBlockOrderChangeset| { &m.block_id }, |m: &mut GridBlockOrderChangeset| { &mut m.block_id }, )); - fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "inserted_rows", |m: &GridBlockOrderChangeset| { &m.inserted_rows }, |m: &mut GridBlockOrderChangeset| { &mut m.inserted_rows }, @@ -3225,6 +3225,238 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockOrderChangeset { } } +#[derive(PartialEq,Clone,Default)] +pub struct IndexRowOrder { + // message fields + pub row_order: ::protobuf::SingularPtrField, + // message oneof groups + pub one_of_index: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a IndexRowOrder { + fn default() -> &'a IndexRowOrder { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum IndexRowOrder_oneof_one_of_index { + index(i32), +} + +impl IndexRowOrder { + pub fn new() -> IndexRowOrder { + ::std::default::Default::default() + } + + // .RowOrder row_order = 1; + + + pub fn get_row_order(&self) -> &RowOrder { + self.row_order.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_row_order(&mut self) { + self.row_order.clear(); + } + + pub fn has_row_order(&self) -> bool { + self.row_order.is_some() + } + + // Param is passed by value, moved + pub fn set_row_order(&mut self, v: RowOrder) { + self.row_order = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_order(&mut self) -> &mut RowOrder { + if self.row_order.is_none() { + self.row_order.set_default(); + } + self.row_order.as_mut().unwrap() + } + + // Take field + pub fn take_row_order(&mut self) -> RowOrder { + self.row_order.take().unwrap_or_else(|| RowOrder::new()) + } + + // int32 index = 2; + + + pub fn get_index(&self) -> i32 { + match self.one_of_index { + ::std::option::Option::Some(IndexRowOrder_oneof_one_of_index::index(v)) => v, + _ => 0, + } + } + pub fn clear_index(&mut self) { + self.one_of_index = ::std::option::Option::None; + } + + pub fn has_index(&self) -> bool { + match self.one_of_index { + ::std::option::Option::Some(IndexRowOrder_oneof_one_of_index::index(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_index(&mut self, v: i32) { + self.one_of_index = ::std::option::Option::Some(IndexRowOrder_oneof_one_of_index::index(v)) + } +} + +impl ::protobuf::Message for IndexRowOrder { + fn is_initialized(&self) -> bool { + for v in &self.row_order { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.row_order)?; + }, + 2 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_index = ::std::option::Option::Some(IndexRowOrder_oneof_one_of_index::index(is.read_int32()?)); + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(ref v) = self.row_order.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if let ::std::option::Option::Some(ref v) = self.one_of_index { + match v { + &IndexRowOrder_oneof_one_of_index::index(v) => { + my_size += ::protobuf::rt::value_size(2, v, ::protobuf::wire_format::WireTypeVarint); + }, + }; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if let Some(ref v) = self.row_order.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_index { + match v { + &IndexRowOrder_oneof_one_of_index::index(v) => { + os.write_int32(2, v)?; + }, + }; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> IndexRowOrder { + IndexRowOrder::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "row_order", + |m: &IndexRowOrder| { &m.row_order }, + |m: &mut IndexRowOrder| { &mut m.row_order }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_i32_accessor::<_>( + "index", + IndexRowOrder::has_index, + IndexRowOrder::get_index, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "IndexRowOrder", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static IndexRowOrder { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(IndexRowOrder::new) + } +} + +impl ::protobuf::Clear for IndexRowOrder { + fn clear(&mut self) { + self.row_order.clear(); + self.one_of_index = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for IndexRowOrder { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for IndexRowOrder { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct GridBlock { // message fields @@ -5640,34 +5872,36 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\ \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\ - \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"\xc0\x01\n\x17GridBlockOr\ - derChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12.\n\ - \rinserted_rows\x18\x02\x20\x03(\x0b2\t.RowOrderR\x0cinsertedRows\x12,\n\ - \x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0bdeletedRows\x12,\n\ - \x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0bupdatedRows\"E\n\t\ - GridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\ - \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08\ - field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\ - \x01(\tR\x07content\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07gri\ - d_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01\ - (\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\ - \n\x07content\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\ - \"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\ - \x05items\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\t\ - R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ - lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ - \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ - idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ - \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ - rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ - \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ - \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ - \x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPaylo\ - ad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_or\ - ders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\ - \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ - ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ - \x0bblockOrdersb\x06proto3\ + \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"\xc5\x01\n\x17GridBlockOr\ + derChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x123\n\ + \rinserted_rows\x18\x02\x20\x03(\x0b2\x0e.IndexRowOrderR\x0cinsertedRows\ + \x12,\n\x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0bdeletedRows\ + \x12,\n\x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0bupdatedRows\ + \"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrderR\ + \x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\ + \x0cone_of_index\"E\n\tGridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02\ + id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\ + \x04Cell\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\ + \x07content\x18\x02\x20\x01(\tR\x07content\"\x8f\x01\n\x14CellNotificati\ + onData\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08f\ + ield_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\ + \x01(\tR\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\x07content\ + B\x10\n\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\ + \x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\x12\ + \n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05va\ + lue\x18\x01\x20\x01(\tR\x05value\"#\n\x0bGridBlockId\x12\x14\n\x05value\ + \x18\x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayload\x12\x17\n\x07grid\ + _id\x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cstart_row_id\x18\x02\x20\ + \x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12Cre\ + ateFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ + \x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type\ + _option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_fie\ + ld_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_fiel\ + d_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ + \x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFiel\ + dOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_\ + id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\ + \x0b2\x0f.GridBlockOrderR\x0bblockOrdersb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index 8c1b48e7a4..cad2a6a108 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -61,10 +61,14 @@ message GridBlockOrder { } message GridBlockOrderChangeset { string block_id = 1; - repeated RowOrder inserted_rows = 2; + repeated IndexRowOrder inserted_rows = 2; repeated RowOrder deleted_rows = 3; repeated RowOrder updated_rows = 4; } +message IndexRowOrder { + RowOrder row_order = 1; + oneof one_of_index { int32 index = 2; }; +} message GridBlock { string id = 1; repeated RowOrder row_orders = 2; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index f416b55141..97c3ed963a 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -48,14 +48,11 @@ impl GridBlockMetaPad { ) -> CollaborateResult> { self.modify(|rows| { if let Some(start_row_id) = start_row_id { - if start_row_id.is_empty() { - rows.insert(0, Arc::new(row)); - return Ok(Some(())); - } - - if let Some(index) = rows.iter().position(|row| row.id == start_row_id) { - rows.insert(index + 1, Arc::new(row)); - return Ok(Some(())); + if !start_row_id.is_empty() { + if let Some(index) = rows.iter().position(|row| row.id == start_row_id) { + rows.insert(index + 1, Arc::new(row)); + return Ok(Some(())); + } } } @@ -121,6 +118,13 @@ impl GridBlockMetaPad { self.rows.len() as i32 } + pub fn index_of_row(&self, row_id: &str) -> Option { + self.rows + .iter() + .position(|row| row.id == row_id) + .map(|index| index as i32) + } + pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult> { let row_id = changeset.row_id.clone(); self.modify_row(&row_id, |row| { From fbb2f49b6f3f78f8da07022a58121e175dce0dd1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 14:33:34 +0800 Subject: [PATCH 8/9] chore: enable rust lint and test by remove path --- .github/workflows/rust_lint.yml | 6 ------ .github/workflows/rust_test.yml | 6 ------ .../flowy-grid-data-model/tests/serde_test.rs | 20 +------------------ .../src/client_grid/grid_block_meta_pad.rs | 10 +++++----- 4 files changed, 6 insertions(+), 36 deletions(-) diff --git a/.github/workflows/rust_lint.yml b/.github/workflows/rust_lint.yml index 9b39f28f2d..ac650b197b 100644 --- a/.github/workflows/rust_lint.yml +++ b/.github/workflows/rust_lint.yml @@ -3,14 +3,8 @@ name: Rust lint on: push: branches: [ main ] - paths: - - 'frontend/rust-lib' - - 'shared-lib' pull_request: branches: [ main ] - paths: - - 'frontend/rust-lib' - - 'shared-lib' env: diff --git a/.github/workflows/rust_test.yml b/.github/workflows/rust_test.yml index e58db025b4..84617fb2c2 100644 --- a/.github/workflows/rust_test.yml +++ b/.github/workflows/rust_test.yml @@ -4,15 +4,9 @@ on: push: branches: - 'main' - paths: - - 'frontend/rust-lib' - - 'shared-lib' pull_request: branches: - 'main' - paths: - - 'frontend/rust-lib' - - 'shared-lib' env: CARGO_TERM_COLOR: always diff --git a/shared-lib/flowy-grid-data-model/tests/serde_test.rs b/shared-lib/flowy-grid-data-model/tests/serde_test.rs index 0847950b98..2bae3f6a79 100644 --- a/shared-lib/flowy-grid-data-model/tests/serde_test.rs +++ b/shared-lib/flowy-grid-data-model/tests/serde_test.rs @@ -1,23 +1,5 @@ use flowy_grid_data_model::entities::*; -#[test] -fn grid_serde_test() { - let grid_id = "1".to_owned(); - let fields = vec![create_field("1")]; - let grid = GridMeta { - grid_id, - fields, - blocks: vec![], - }; - - let grid_1_json = serde_json::to_string(&grid).unwrap(); - let _: GridMeta = serde_json::from_str(&grid_1_json).unwrap(); - assert_eq!( - grid_1_json, - r#"{"id":"1","fields":[{"id":"1","name":"Text Field","desc":"","field_type":"RichText","frozen":false,"visibility":true,"width":150,"type_options":{"type_id":"","value":[]}}],"blocks":[]}"# - ) -} - #[test] fn grid_default_serde_test() { let grid_id = "1".to_owned(); @@ -28,7 +10,7 @@ fn grid_default_serde_test() { }; let json = serde_json::to_string(&grid).unwrap(); - assert_eq!(json, r#"{"id":"1","fields":[],"blocks":[]}"#) + assert_eq!(json, r#"{"grid_id":"1","fields":[],"blocks":[]}"#) } fn create_field(field_id: &str) -> FieldMeta { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index 97c3ed963a..39b38e2b84 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -309,8 +309,8 @@ mod tests { let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); let _ = pad.add_row_meta(row_3.clone(), Some("1".to_string())).unwrap().unwrap(); - assert_eq!(*pad.rows[0], row_3); - assert_eq!(*pad.rows[1], row_1); + assert_eq!(*pad.rows[0], row_1); + assert_eq!(*pad.rows[1], row_3); assert_eq!(*pad.rows[2], row_2); } @@ -325,9 +325,9 @@ mod tests { let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); let _ = pad.add_row_meta(row_3.clone(), Some("".to_string())).unwrap().unwrap(); - assert_eq!(*pad.rows[0], row_3); - assert_eq!(*pad.rows[1], row_1); - assert_eq!(*pad.rows[2], row_2); + assert_eq!(*pad.rows[0], row_1); + assert_eq!(*pad.rows[1], row_2); + assert_eq!(*pad.rows[2], row_3); } #[test] From df6871e777833185ca3b1bb4bb7649d91d552e59 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 10 Apr 2022 14:40:57 +0800 Subject: [PATCH 9/9] chore: fix wanrings --- .github/workflows/dart_lint.yml | 4 ---- frontend/app_flowy/lib/startup/deps_resolver.dart | 1 - .../app_flowy/lib/workspace/application/grid/grid_bloc.dart | 1 - .../presentation/plugins/grid/src/widgets/row/grid_row.dart | 1 - .../rust-lib/flowy-revision/src/cache/disk/folder_rev_impl.rs | 1 + frontend/rust-lib/flowy-sdk/src/deps_resolve/util.rs | 1 + 6 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dart_lint.yml b/.github/workflows/dart_lint.yml index 2b4a995cce..69cf8e46c7 100644 --- a/.github/workflows/dart_lint.yml +++ b/.github/workflows/dart_lint.yml @@ -8,12 +8,8 @@ name: Flutter lint on: push: branches: [ main ] - paths: - - 'frontend/app_flowy' pull_request: branches: [ main ] - paths: - - 'frontend/app_flowy' env: CARGO_TERM_COLOR: always diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 98ab00d0e4..abf6fffd21 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -5,7 +5,6 @@ import 'package:app_flowy/workspace/application/app/prelude.dart'; import 'package:app_flowy/workspace/application/doc/prelude.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/application/grid/row/row_listener.dart'; import 'package:app_flowy/workspace/application/trash/prelude.dart'; import 'package:app_flowy/workspace/application/workspace/prelude.dart'; import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index bf56b9d864..ddb1d41ca3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index a5b6a405a6..baeed922d7 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -5,7 +5,6 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/p import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; diff --git a/frontend/rust-lib/flowy-revision/src/cache/disk/folder_rev_impl.rs b/frontend/rust-lib/flowy-revision/src/cache/disk/folder_rev_impl.rs index e69de29bb2..8b13789179 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/disk/folder_rev_impl.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/disk/folder_rev_impl.rs @@ -0,0 +1 @@ + diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/util.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/util.rs index e69de29bb2..8b13789179 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/util.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/util.rs @@ -0,0 +1 @@ +