瀏覽代碼

Merge pull request #581 from AppFlowy-IO/refactor/grid_filter

Refactor/grid filter
Nathan.fooo 2 年之前
父節點
當前提交
582cde444e
共有 100 個文件被更改,包括 2136 次插入1633 次删除
  1. 1 1
      frontend/app_flowy/lib/workspace/application/doc/doc_service.dart
  2. 1 2
      frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart
  3. 1 2
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
  4. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart
  5. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart
  6. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart
  7. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart
  8. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart
  9. 1 2
      frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
  10. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart
  11. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart
  12. 0 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
  13. 4 3
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  14. 1 1
      frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart
  15. 4 2
      frontend/app_flowy/lib/workspace/application/grid/grid_service.dart
  16. 5 1
      frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart
  17. 6 2
      frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart
  18. 2 2
      frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart
  19. 52 39
      frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart
  20. 1 1
      frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart
  21. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/layout.dart
  22. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
  23. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart
  24. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart
  25. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart
  26. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart
  27. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart
  28. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart
  29. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart
  30. 1 7
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart
  31. 0 4
      frontend/rust-lib/Cargo.lock
  32. 1 1
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  33. 1 1
      frontend/rust-lib/flowy-folder/tests/workspace/script.rs
  34. 213 0
      frontend/rust-lib/flowy-grid/src/entities/block_entities.rs
  35. 84 0
      frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs
  36. 565 1
      frontend/rust-lib/flowy-grid/src/entities/field_entities.rs
  37. 96 31
      frontend/rust-lib/flowy-grid/src/entities/filter_entities.rs
  38. 106 0
      frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs
  39. 4 9
      frontend/rust-lib/flowy-grid/src/entities/group_entities.rs
  40. 12 0
      frontend/rust-lib/flowy-grid/src/entities/mod.rs
  41. 53 5
      frontend/rust-lib/flowy-grid/src/entities/row_entities.rs
  42. 38 53
      frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs
  43. 4 8
      frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs
  44. 23 14
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  45. 3 3
      frontend/rust-lib/flowy-grid/src/event_map.rs
  46. 10 5
      frontend/rust-lib/flowy-grid/src/macros.rs
  47. 58 50
      frontend/rust-lib/flowy-grid/src/services/block_manager.rs
  48. 8 8
      frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs
  49. 5 4
      frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs
  50. 8 4
      frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs
  51. 14 10
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs
  52. 3 3
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/format.rs
  53. 13 9
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs
  54. 20 8
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs
  55. 9 5
      frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs
  56. 8 4
      frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs
  57. 267 32
      frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs
  58. 44 42
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  59. 25 5
      frontend/rust-lib/flowy-grid/src/services/grid_editor_task.rs
  60. 23 21
      frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs
  61. 0 1
      frontend/rust-lib/flowy-grid/src/services/row/mod.rs
  62. 4 3
      frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs
  63. 0 31
      frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs
  64. 12 11
      frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs
  65. 5 4
      frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs
  66. 2 2
      frontend/rust-lib/flowy-grid/src/services/tasks/queue.rs
  67. 13 8
      frontend/rust-lib/flowy-grid/src/services/tasks/scheduler.rs
  68. 5 5
      frontend/rust-lib/flowy-grid/src/services/tasks/store.rs
  69. 11 7
      frontend/rust-lib/flowy-grid/src/services/tasks/task.rs
  70. 1 1
      frontend/rust-lib/flowy-grid/src/util.rs
  71. 3 2
      frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs
  72. 1 1
      frontend/rust-lib/flowy-grid/tests/grid/field_test.rs
  73. 6 5
      frontend/rust-lib/flowy-grid/tests/grid/field_util.rs
  74. 7 4
      frontend/rust-lib/flowy-grid/tests/grid/filter_test.rs
  75. 1 1
      frontend/rust-lib/flowy-grid/tests/grid/mod.rs
  76. 5 3
      frontend/rust-lib/flowy-grid/tests/grid/row_test.rs
  77. 6 2
      frontend/rust-lib/flowy-grid/tests/grid/row_util.rs
  78. 24 16
      frontend/rust-lib/flowy-grid/tests/grid/script.rs
  79. 1 1
      frontend/rust-lib/flowy-net/src/http_server/document.rs
  80. 1 1
      frontend/rust-lib/flowy-net/src/local_server/persistence.rs
  81. 1 1
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  82. 1 1
      frontend/rust-lib/flowy-text-block/src/editor.rs
  83. 1 1
      frontend/rust-lib/flowy-text-block/src/event_handler.rs
  84. 1 1
      frontend/rust-lib/flowy-text-block/src/lib.rs
  85. 1 1
      frontend/rust-lib/flowy-text-block/src/manager.rs
  86. 0 4
      shared-lib/Cargo.lock
  87. 1 4
      shared-lib/flowy-grid-data-model/Cargo.toml
  88. 0 2
      shared-lib/flowy-grid-data-model/Flowy.toml
  89. 0 5
      shared-lib/flowy-grid-data-model/build.rs
  90. 0 523
      shared-lib/flowy-grid-data-model/src/entities/field.rs
  91. 0 379
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  92. 0 13
      shared-lib/flowy-grid-data-model/src/entities/mod.rs
  93. 0 2
      shared-lib/flowy-grid-data-model/src/lib.rs
  94. 39 82
      shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs
  95. 85 3
      shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs
  96. 1 1
      shared-lib/flowy-sync/src/client_folder/builder.rs
  97. 2 2
      shared-lib/flowy-sync/src/client_folder/folder_pad.rs
  98. 0 33
      shared-lib/flowy-sync/src/client_grid/grid_builder.rs
  99. 81 44
      shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs
  100. 0 0
      shared-lib/flowy-sync/src/entities/folder.rs

+ 1 - 1
frontend/app_flowy/lib/workspace/application/doc/doc_service.dart

@@ -3,7 +3,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
 
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-sync/text_block_info.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-sync/text_block.pb.dart';
 
 class DocumentService {
   Future<Either<TextBlockDelta, FlowyError>> openDocument({

+ 1 - 2
frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart

@@ -7,13 +7,12 @@ import 'package:dartz/dartz.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 
 class GridBlockCache {
   final String gridId;
   void Function(GridBlockUpdateNotifierValue)? _onBlockChanged;
-
   final LinkedHashMap<String, _GridBlockListener> _listeners = LinkedHashMap();
   GridBlockCache({required this.gridId});
 

+ 1 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart

@@ -6,10 +6,9 @@ import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
 import 'package:flutter/foundation.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart

@@ -1,5 +1,5 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart

@@ -1,5 +1,5 @@
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart

@@ -1,4 +1,4 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart

@@ -1,11 +1,11 @@
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.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';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>;
 

+ 1 - 2
frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

@@ -2,9 +2,8 @@ import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:protobuf/protobuf.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart

@@ -1,11 +1,11 @@
 import 'package:dartz/dartz.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.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';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 typedef UpdateFieldNotifiedValue = Either<GridFieldChangeset, FlowyError>;
 

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart

@@ -86,7 +86,7 @@ extension NumberFormatExtension on NumberFormat {
         return "New Zealand dollar";
       case NumberFormat.NorwegianKrone:
         return "Norwegian krone";
-      case NumberFormat.Number:
+      case NumberFormat.Num:
         return "Number";
       case NumberFormat.Percent:
         return "Percent";

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:dartz/dartz.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/field.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';

+ 4 - 3
frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart

@@ -4,7 +4,7 @@ import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 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:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'block/block_listener.dart';
@@ -30,6 +30,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
         super(GridState.initial(view.id)) {
     rowCache = GridRowCache(
       gridId: view.id,
+      blockId: "",
       fieldDelegate: GridRowCacheDelegateImpl(fieldCache),
     );
 
@@ -96,8 +97,8 @@ class GridBloc extends Bloc<GridEvent, GridState> {
           for (final block in grid.blocks) {
             blockCache.addBlockListener(block.id);
           }
-          final rowOrders = grid.blocks.expand((block) => block.rowOrders).toList();
-          rowCache.initialRows(rowOrders);
+          final rowInfos = grid.blocks.expand((block) => block.rowInfos).toList();
+          rowCache.initialRows(rowInfos);
 
           await _loadFields(grid, emit);
         },

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart

@@ -1,6 +1,6 @@
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 4 - 2
frontend/app_flowy/lib/workspace/application/grid/grid_service.dart

@@ -6,8 +6,10 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'cell/cell_service/cell_service.dart';
 import 'row/row_service.dart';

+ 5 - 1
frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart

@@ -12,7 +12,11 @@ class RowActionSheetBloc extends Bloc<RowActionSheetEvent, RowActionSheetState>
   final RowService _rowService;
 
   RowActionSheetBloc({required GridRow rowData})
-      : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
+      : _rowService = RowService(
+          gridId: rowData.gridId,
+          blockId: rowData.blockId,
+          rowId: rowData.rowId,
+        ),
         super(RowActionSheetState.initial(rowData)) {
     on<RowActionSheetEvent>(
       (event, emit) async {

+ 6 - 2
frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart

@@ -1,7 +1,7 @@
 import 'dart:collection';
 import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
 import 'package:equatable/equatable.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -17,7 +17,11 @@ class RowBloc extends Bloc<RowEvent, RowState> {
   RowBloc({
     required GridRow rowData,
     required GridRowCache rowCache,
-  })  : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
+  })  : _rowService = RowService(
+          gridId: rowData.gridId,
+          blockId: rowData.blockId,
+          rowId: rowData.rowId,
+        ),
         _rowCache = rowCache,
         super(RowState.initial(rowData, rowCache.loadGridCells(rowData.rowId))) {
     on<RowEvent>(

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart

@@ -1,12 +1,12 @@
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.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';
 import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 typedef UpdateRowNotifiedValue = Either<Row, FlowyError>;
 typedef UpdateFieldNotifiedValue = Either<List<Field>, FlowyError>;

+ 52 - 39
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -5,8 +5,9 @@ import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -22,18 +23,23 @@ abstract class GridRowFieldDelegate {
 
 class GridRowCache {
   final String gridId;
+  final String blockId;
   final RowsNotifier _rowsNotifier;
   final GridRowFieldDelegate _fieldDelegate;
   List<GridRow> get clonedRows => _rowsNotifier.clonedRows;
 
-  GridRowCache({required this.gridId, required GridRowFieldDelegate fieldDelegate})
-      : _rowsNotifier = RowsNotifier(
-          rowBuilder: (rowOrder) {
+  GridRowCache({
+    required this.gridId,
+    required this.blockId,
+    required GridRowFieldDelegate fieldDelegate,
+  })  : _rowsNotifier = RowsNotifier(
+          rowBuilder: (rowInfo) {
             return GridRow(
               gridId: gridId,
+              blockId: "test",
               fields: fieldDelegate.fields,
-              rowId: rowOrder.rowId,
-              height: rowOrder.height.toDouble(),
+              rowId: rowInfo.rowId,
+              height: rowInfo.height.toDouble(),
             );
           },
         ),
@@ -119,13 +125,14 @@ class GridRowCache {
     return _makeGridCells(rowId, data);
   }
 
-  void initialRows(List<RowOrder> rowOrders) {
-    _rowsNotifier.initialRows(rowOrders);
+  void initialRows(List<BlockRowInfo> rowInfos) {
+    _rowsNotifier.initialRows(rowInfos);
   }
 
   Future<void> _loadRow(String rowId) async {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     final result = await GridEventGetRow(payload).send();
@@ -155,34 +162,34 @@ class GridRowCache {
 }
 
 class RowsNotifier extends ChangeNotifier {
-  List<GridRow> _rows = [];
-  HashMap<String, Row> _rowDataMap = HashMap();
+  List<GridRow> _allRows = [];
+  HashMap<String, Row> _rowByRowId = HashMap();
   GridRowChangeReason _changeReason = const InitialListState();
-  final GridRow Function(RowOrder) rowBuilder;
+  final GridRow Function(BlockRowInfo) rowBuilder;
 
   RowsNotifier({
     required this.rowBuilder,
   });
 
-  List<GridRow> get clonedRows => [..._rows];
+  List<GridRow> get clonedRows => [..._allRows];
 
-  void initialRows(List<RowOrder> rowOrders) {
-    _rowDataMap = HashMap();
-    final rows = rowOrders.map((rowOrder) => rowBuilder(rowOrder)).toList();
+  void initialRows(List<BlockRowInfo> rowInfos) {
+    _rowByRowId = HashMap();
+    final rows = rowInfos.map((rowOrder) => rowBuilder(rowOrder)).toList();
     _update(rows, const GridRowChangeReason.initial());
   }
 
-  void deleteRows(List<RowOrder> deletedRows) {
+  void deleteRows(List<GridRowId> deletedRows) {
     if (deletedRows.isEmpty) {
       return;
     }
 
     final List<GridRow> newRows = [];
     final DeletedIndexs deletedIndex = [];
-    final Map<String, RowOrder> deletedRowMap = {for (var e in deletedRows) e.rowId: e};
+    final Map<String, GridRowId> deletedRowByRowId = {for (var e in deletedRows) e.rowId: e};
 
-    _rows.asMap().forEach((index, row) {
-      if (deletedRowMap[row.rowId] == null) {
+    _allRows.asMap().forEach((index, row) {
+      if (deletedRowByRowId[row.rowId] == null) {
         newRows.add(row);
       } else {
         deletedIndex.add(DeletedIndex(index: index, row: row));
@@ -202,10 +209,10 @@ class RowsNotifier extends ChangeNotifier {
     for (final insertRow in insertRows) {
       final insertIndex = InsertedIndex(
         index: insertRow.index,
-        rowId: insertRow.rowOrder.rowId,
+        rowId: insertRow.rowInfo.rowId,
       );
       insertIndexs.add(insertIndex);
-      newRows.insert(insertRow.index, (rowBuilder(insertRow.rowOrder)));
+      newRows.insert(insertRow.index, (rowBuilder(insertRow.rowInfo)));
     }
     _update(newRows, GridRowChangeReason.insert(insertIndexs));
   }
@@ -218,14 +225,15 @@ class RowsNotifier extends ChangeNotifier {
     final UpdatedIndexs updatedIndexs = UpdatedIndexs();
     final List<GridRow> newRows = clonedRows;
     for (final updatedRow in updatedRows) {
-      final rowOrder = updatedRow.rowOrder;
-      final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
+      final rowOrder = updatedRow.rowInfo;
+      final rowId = updatedRow.rowInfo.rowId;
+      final index = newRows.indexWhere((row) => row.rowId == rowId);
       if (index != -1) {
-        _rowDataMap[rowOrder.rowId] = updatedRow.row;
+        _rowByRowId[rowId] = updatedRow.row;
 
         newRows.removeAt(index);
         newRows.insert(index, rowBuilder(rowOrder));
-        updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId);
+        updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId);
       }
     }
 
@@ -233,11 +241,11 @@ class RowsNotifier extends ChangeNotifier {
   }
 
   void fieldDidChange() {
-    _update(_rows, const GridRowChangeReason.fieldDidChange());
+    _update(_allRows, const GridRowChangeReason.fieldDidChange());
   }
 
   void _update(List<GridRow> rows, GridRowChangeReason reason) {
-    _rows = rows;
+    _allRows = rows;
     _changeReason = reason;
 
     _changeReason.map(
@@ -252,13 +260,13 @@ class RowsNotifier extends ChangeNotifier {
   set rowData(Row rowData) {
     rowData.freeze();
 
-    _rowDataMap[rowData.id] = rowData;
-    final index = _rows.indexWhere((row) => row.rowId == rowData.id);
+    _rowByRowId[rowData.id] = rowData;
+    final index = _allRows.indexWhere((row) => row.rowId == rowData.id);
     if (index != -1) {
       // update the corresponding row in _rows if they are not the same
-      if (_rows[index].data != rowData) {
-        final row = _rows.removeAt(index).copyWith(data: rowData);
-        _rows.insert(index, row);
+      if (_allRows[index].data != rowData) {
+        final row = _allRows.removeAt(index).copyWith(data: rowData);
+        _allRows.insert(index, row);
 
         // Calculate the update index
         final UpdatedIndexs updatedIndexs = UpdatedIndexs();
@@ -272,15 +280,16 @@ class RowsNotifier extends ChangeNotifier {
   }
 
   Row? rowDataWithId(String rowId) {
-    return _rowDataMap[rowId];
+    return _rowByRowId[rowId];
   }
 }
 
 class RowService {
   final String gridId;
+  final String blockId;
   final String rowId;
 
-  RowService({required this.gridId, required this.rowId});
+  RowService({required this.gridId, required this.blockId, required this.rowId});
 
   Future<Either<Row, FlowyError>> createRow() {
     CreateRowPayload payload = CreateRowPayload.create()
@@ -302,24 +311,27 @@ class RowService {
   }
 
   Future<Either<OptionalRow, FlowyError>> getRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventGetRow(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> deleteRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDeleteRow(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> duplicateRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDuplicateRow(payload).send();
@@ -330,6 +342,7 @@ class RowService {
 class GridRow with _$GridRow {
   const factory GridRow({
     required String gridId,
+    required String blockId,
     required String rowId,
     required UnmodifiableListView<Field> fields,
     required double height,

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:app_flowy/workspace/application/grid/grid_service.dart';
 import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/layout.dart

@@ -1,4 +1,4 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'sizes.dart';
 
 class GridLayout {

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart

@@ -1,5 +1,5 @@
 import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/material.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart

@@ -6,7 +6,7 @@ import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'field_type_extension.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart

@@ -10,7 +10,7 @@ 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/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart

@@ -1,6 +1,6 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:easy_localization/easy_localization.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 
 extension FieldTypeListExtension on FieldType {
   String iconName() {

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart

@@ -6,7 +6,7 @@ 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:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'field_type_extension.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart

@@ -5,7 +5,7 @@ import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:reorderables/reorderables.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart

@@ -14,9 +14,9 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:window_size/window_size.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart

@@ -12,7 +12,7 @@ import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/field.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 1 - 7
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart

@@ -4,15 +4,9 @@ import 'package:flowy_sdk/log.dart';
 // ignore: unnecessary_import
 import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/event_map.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/event_map.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/event_map.pb.dart';
 import 'package:isolates/isolates.dart';
 import 'package:isolates/ports.dart';
 import 'package:ffi/ffi.dart';
@@ -25,7 +19,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart';
 import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-text-block/protobuf.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-sync/protobuf.dart';
 
 // ignore: unused_import

+ 0 - 4
frontend/rust-lib/Cargo.lock

@@ -973,17 +973,13 @@ name = "flowy-grid-data-model"
 version = "0.1.0"
 dependencies = [
  "bytes",
- "flowy-derive",
  "flowy-error-code",
  "indexmap",
  "lib-infra",
  "nanoid",
- "protobuf",
  "serde",
  "serde_json",
  "serde_repr",
- "strum",
- "strum_macros",
 ]
 
 [[package]]

+ 1 - 1
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -17,7 +17,7 @@ use flowy_database::kv::KV;
 use flowy_folder_data_model::entities::view::{gen_view_id, ViewDataType};
 use flowy_folder_data_model::entities::ViewInfo;
 use flowy_folder_data_model::revision::ViewRevision;
-use flowy_sync::entities::text_block_info::TextBlockId;
+use flowy_sync::entities::text_block::TextBlockId;
 use futures::{FutureExt, StreamExt};
 use std::{collections::HashSet, sync::Arc};
 

+ 1 - 1
frontend/rust-lib/flowy-folder/tests/workspace/script.rs

@@ -17,7 +17,7 @@ use flowy_folder_data_model::entities::{
 
 use flowy_revision::disk::RevisionState;
 use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
-use flowy_sync::entities::text_block_info::TextBlockInfo;
+use flowy_sync::entities::text_block::TextBlockInfo;
 use flowy_test::{event_builder::*, FlowySDKTest};
 use std::{sync::Arc, time::Duration};
 use tokio::time::sleep;

+ 213 - 0
frontend/rust-lib/flowy-grid/src/entities/block_entities.rs

@@ -0,0 +1,213 @@
+use crate::entities::GridRowId;
+use flowy_derive::ProtoBuf;
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::RowRevision;
+use std::sync::Arc;
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct GridBlock {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub row_infos: Vec<BlockRowInfo>,
+}
+
+impl GridBlock {
+    pub fn new(block_id: &str, row_orders: Vec<BlockRowInfo>) -> Self {
+        Self {
+            id: block_id.to_owned(),
+            row_infos: row_orders,
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct BlockRowInfo {
+    #[pb(index = 1)]
+    pub block_id: String,
+
+    #[pb(index = 2)]
+    pub row_id: String,
+
+    #[pb(index = 3)]
+    pub height: i32,
+}
+
+impl BlockRowInfo {
+    pub fn row_id(&self) -> &str {
+        &self.row_id
+    }
+
+    pub fn block_id(&self) -> &str {
+        &self.block_id
+    }
+}
+
+impl std::convert::From<&RowRevision> for BlockRowInfo {
+    fn from(rev: &RowRevision) -> Self {
+        Self {
+            block_id: rev.block_id.clone(),
+            row_id: rev.id.clone(),
+            height: rev.height,
+        }
+    }
+}
+
+impl std::convert::From<&Arc<RowRevision>> for BlockRowInfo {
+    fn from(rev: &Arc<RowRevision>) -> Self {
+        Self {
+            block_id: rev.block_id.clone(),
+            row_id: rev.id.clone(),
+            height: rev.height,
+        }
+    }
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct Row {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub height: i32,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct OptionalRow {
+    #[pb(index = 1, one_of)]
+    pub row: Option<Row>,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RepeatedRow {
+    #[pb(index = 1)]
+    pub items: Vec<Row>,
+}
+
+impl std::convert::From<Vec<Row>> for RepeatedRow {
+    fn from(items: Vec<Row>) -> Self {
+        Self { items }
+    }
+}
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RepeatedGridBlock {
+    #[pb(index = 1)]
+    pub items: Vec<GridBlock>,
+}
+
+impl std::convert::From<Vec<GridBlock>> for RepeatedGridBlock {
+    fn from(items: Vec<GridBlock>) -> Self {
+        Self { items }
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct IndexRowOrder {
+    #[pb(index = 1)]
+    pub row_info: BlockRowInfo,
+
+    #[pb(index = 2, one_of)]
+    pub index: Option<i32>,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct UpdatedRowOrder {
+    #[pb(index = 1)]
+    pub row_info: BlockRowInfo,
+
+    #[pb(index = 2)]
+    pub row: Row,
+}
+
+impl UpdatedRowOrder {
+    pub fn new(row_rev: &RowRevision, row: Row) -> Self {
+        Self {
+            row_info: BlockRowInfo::from(row_rev),
+            row,
+        }
+    }
+}
+
+impl std::convert::From<BlockRowInfo> for IndexRowOrder {
+    fn from(row_info: BlockRowInfo) -> Self {
+        Self { row_info, index: None }
+    }
+}
+
+impl std::convert::From<&RowRevision> for IndexRowOrder {
+    fn from(row: &RowRevision) -> Self {
+        let row_order = BlockRowInfo::from(row);
+        Self::from(row_order)
+    }
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct GridRowsChangeset {
+    #[pb(index = 1)]
+    pub block_id: String,
+
+    #[pb(index = 2)]
+    pub inserted_rows: Vec<IndexRowOrder>,
+
+    #[pb(index = 3)]
+    pub deleted_rows: Vec<GridRowId>,
+
+    #[pb(index = 4)]
+    pub updated_rows: Vec<UpdatedRowOrder>,
+}
+impl GridRowsChangeset {
+    pub fn insert(block_id: &str, inserted_rows: Vec<IndexRowOrder>) -> Self {
+        Self {
+            block_id: block_id.to_owned(),
+            inserted_rows,
+            deleted_rows: vec![],
+            updated_rows: vec![],
+        }
+    }
+
+    pub fn delete(block_id: &str, deleted_rows: Vec<GridRowId>) -> Self {
+        Self {
+            block_id: block_id.to_owned(),
+            inserted_rows: vec![],
+            deleted_rows,
+            updated_rows: vec![],
+        }
+    }
+
+    pub fn update(block_id: &str, updated_rows: Vec<UpdatedRowOrder>) -> Self {
+        Self {
+            block_id: block_id.to_owned(),
+            inserted_rows: vec![],
+            deleted_rows: vec![],
+            updated_rows,
+        }
+    }
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct QueryGridBlocksPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub block_ids: Vec<String>,
+}
+
+pub struct QueryGridBlocksParams {
+    pub grid_id: String,
+    pub block_ids: Vec<String>,
+}
+
+impl TryInto<QueryGridBlocksParams> for QueryGridBlocksPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<QueryGridBlocksParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(QueryGridBlocksParams {
+            grid_id: grid_id.0,
+            block_ids: self.block_ids,
+        })
+    }
+}

+ 84 - 0
frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs

@@ -2,6 +2,8 @@ use crate::entities::{FieldIdentifier, FieldIdentifierPayload};
 use flowy_derive::ProtoBuf;
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::{CellRevision, RowMetaChangeset};
+use std::collections::HashMap;
 
 #[derive(ProtoBuf, Default)]
 pub struct CreateSelectOptionPayload {
@@ -70,3 +72,85 @@ impl TryInto<CellIdentifier> for CellIdentifierPayload {
         })
     }
 }
+#[derive(Debug, Default, ProtoBuf)]
+pub struct Cell {
+    #[pb(index = 1)]
+    pub field_id: String,
+
+    #[pb(index = 2)]
+    pub data: Vec<u8>,
+}
+
+impl Cell {
+    pub fn new(field_id: &str, data: Vec<u8>) -> Self {
+        Self {
+            field_id: field_id.to_owned(),
+            data,
+        }
+    }
+
+    pub fn empty(field_id: &str) -> Self {
+        Self {
+            field_id: field_id.to_owned(),
+            data: vec![],
+        }
+    }
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RepeatedCell {
+    #[pb(index = 1)]
+    pub items: Vec<Cell>,
+}
+
+impl std::ops::Deref for RepeatedCell {
+    type Target = Vec<Cell>;
+    fn deref(&self) -> &Self::Target {
+        &self.items
+    }
+}
+
+impl std::ops::DerefMut for RepeatedCell {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.items
+    }
+}
+
+impl std::convert::From<Vec<Cell>> for RepeatedCell {
+    fn from(items: Vec<Cell>) -> Self {
+        Self { items }
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct CellChangeset {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub row_id: String,
+
+    #[pb(index = 3)]
+    pub field_id: String,
+
+    #[pb(index = 4, one_of)]
+    pub cell_content_changeset: Option<String>,
+}
+
+impl std::convert::From<CellChangeset> for RowMetaChangeset {
+    fn from(changeset: CellChangeset) -> Self {
+        let mut cell_by_field_id = HashMap::with_capacity(1);
+        let field_id = changeset.field_id;
+        let cell_rev = CellRevision {
+            data: changeset.cell_content_changeset.unwrap_or_else(|| "".to_owned()),
+        };
+        cell_by_field_id.insert(field_id, cell_rev);
+
+        RowMetaChangeset {
+            row_id: changeset.row_id,
+            height: None,
+            visibility: None,
+            cell_by_field_id,
+        }
+    }
+}

+ 565 - 1
frontend/rust-lib/flowy-grid/src/entities/field_entities.rs

@@ -1,7 +1,571 @@
-use flowy_derive::ProtoBuf;
+use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision};
+use flowy_sync::entities::grid::FieldChangesetParams;
+use serde_repr::*;
+use std::sync::Arc;
 
+use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct Field {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub name: String,
+
+    #[pb(index = 3)]
+    pub desc: String,
+
+    #[pb(index = 4)]
+    pub field_type: FieldType,
+
+    #[pb(index = 5)]
+    pub frozen: bool,
+
+    #[pb(index = 6)]
+    pub visibility: bool,
+
+    #[pb(index = 7)]
+    pub width: i32,
+
+    #[pb(index = 8)]
+    pub is_primary: bool,
+}
+
+impl std::convert::From<FieldRevision> for Field {
+    fn from(field_rev: FieldRevision) -> Self {
+        Self {
+            id: field_rev.id,
+            name: field_rev.name,
+            desc: field_rev.desc,
+            field_type: field_rev.field_type_rev.into(),
+            frozen: field_rev.frozen,
+            visibility: field_rev.visibility,
+            width: field_rev.width,
+            is_primary: field_rev.is_primary,
+        }
+    }
+}
+
+impl std::convert::From<Arc<FieldRevision>> for Field {
+    fn from(field_rev: Arc<FieldRevision>) -> Self {
+        let field_rev = field_rev.as_ref().clone();
+        Field::from(field_rev)
+    }
+}
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct FieldOrder {
+    #[pb(index = 1)]
+    pub field_id: String,
+}
+
+impl std::convert::From<&str> for FieldOrder {
+    fn from(s: &str) -> Self {
+        FieldOrder { field_id: s.to_owned() }
+    }
+}
+
+impl std::convert::From<String> for FieldOrder {
+    fn from(s: String) -> Self {
+        FieldOrder { field_id: s }
+    }
+}
+
+impl std::convert::From<&Arc<FieldRevision>> for FieldOrder {
+    fn from(field_rev: &Arc<FieldRevision>) -> Self {
+        Self {
+            field_id: field_rev.id.clone(),
+        }
+    }
+}
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct GridFieldChangeset {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub inserted_fields: Vec<IndexField>,
+
+    #[pb(index = 3)]
+    pub deleted_fields: Vec<FieldOrder>,
+
+    #[pb(index = 4)]
+    pub updated_fields: Vec<Field>,
+}
+
+impl GridFieldChangeset {
+    pub fn insert(grid_id: &str, inserted_fields: Vec<IndexField>) -> Self {
+        Self {
+            grid_id: grid_id.to_owned(),
+            inserted_fields,
+            deleted_fields: vec![],
+            updated_fields: vec![],
+        }
+    }
+
+    pub fn delete(grid_id: &str, deleted_fields: Vec<FieldOrder>) -> Self {
+        Self {
+            grid_id: grid_id.to_string(),
+            inserted_fields: vec![],
+            deleted_fields,
+            updated_fields: vec![],
+        }
+    }
+
+    pub fn update(grid_id: &str, updated_fields: Vec<Field>) -> Self {
+        Self {
+            grid_id: grid_id.to_string(),
+            inserted_fields: vec![],
+            deleted_fields: vec![],
+            updated_fields,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct IndexField {
+    #[pb(index = 1)]
+    pub field: Field,
+
+    #[pb(index = 2)]
+    pub index: i32,
+}
+
+impl IndexField {
+    pub fn from_field_rev(field_rev: &Arc<FieldRevision>, index: usize) -> Self {
+        Self {
+            field: Field::from(field_rev.as_ref().clone()),
+            index: index as i32,
+        }
+    }
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct GetEditFieldContextPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2, one_of)]
+    pub field_id: Option<String>,
+
+    #[pb(index = 3)]
+    pub field_type: FieldType,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct EditFieldPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_id: String,
+
+    #[pb(index = 3)]
+    pub field_type: FieldType,
+
+    #[pb(index = 4)]
+    pub create_if_not_exist: bool,
+}
+
+pub struct EditFieldParams {
+    pub grid_id: String,
+    pub field_id: String,
+    pub field_type: FieldType,
+}
+
+impl TryInto<EditFieldParams> for EditFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<EditFieldParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+        Ok(EditFieldParams {
+            grid_id: grid_id.0,
+            field_id: field_id.0,
+            field_type: self.field_type,
+        })
+    }
+}
+
+pub struct CreateFieldParams {
+    pub grid_id: String,
+    pub field_type: FieldType,
+}
+
+impl TryInto<CreateFieldParams> for EditFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+
+        Ok(CreateFieldParams {
+            grid_id: grid_id.0,
+            field_type: self.field_type,
+        })
+    }
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct FieldTypeOptionContext {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub grid_field: Field,
+
+    #[pb(index = 3)]
+    pub type_option_data: Vec<u8>,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct FieldTypeOptionData {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field: Field,
+
+    #[pb(index = 3)]
+    pub type_option_data: Vec<u8>,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RepeatedField {
+    #[pb(index = 1)]
+    pub items: Vec<Field>,
+}
+impl std::ops::Deref for RepeatedField {
+    type Target = Vec<Field>;
+    fn deref(&self) -> &Self::Target {
+        &self.items
+    }
+}
+
+impl std::ops::DerefMut for RepeatedField {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.items
+    }
+}
+
+impl std::convert::From<Vec<Field>> for RepeatedField {
+    fn from(items: Vec<Field>) -> Self {
+        Self { items }
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct RepeatedFieldOrder {
+    #[pb(index = 1)]
+    pub items: Vec<FieldOrder>,
+}
+
+impl std::ops::Deref for RepeatedFieldOrder {
+    type Target = Vec<FieldOrder>;
+    fn deref(&self) -> &Self::Target {
+        &self.items
+    }
+}
+
+impl std::convert::From<Vec<FieldOrder>> for RepeatedFieldOrder {
+    fn from(field_orders: Vec<FieldOrder>) -> Self {
+        RepeatedFieldOrder { items: field_orders }
+    }
+}
+
+impl std::convert::From<String> for RepeatedFieldOrder {
+    fn from(s: String) -> Self {
+        RepeatedFieldOrder {
+            items: vec![FieldOrder::from(s)],
+        }
+    }
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct InsertFieldPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field: Field,
+
+    #[pb(index = 3)]
+    pub type_option_data: Vec<u8>,
+
+    #[pb(index = 4, one_of)]
+    pub start_field_id: Option<String>,
+}
+
+#[derive(Clone)]
+pub struct InsertFieldParams {
+    pub grid_id: String,
+    pub field: Field,
+    pub type_option_data: Vec<u8>,
+    pub start_field_id: Option<String>,
+}
+
+impl TryInto<InsertFieldParams> for InsertFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<InsertFieldParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let _ = NotEmptyStr::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+
+        let start_field_id = match self.start_field_id {
+            None => None,
+            Some(id) => Some(NotEmptyStr::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        Ok(InsertFieldParams {
+            grid_id: grid_id.0,
+            field: self.field,
+            type_option_data: self.type_option_data,
+            start_field_id,
+        })
+    }
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct UpdateFieldTypeOptionPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_id: String,
+
+    #[pb(index = 3)]
+    pub type_option_data: Vec<u8>,
+}
+
+#[derive(Clone)]
+pub struct UpdateFieldTypeOptionParams {
+    pub grid_id: String,
+    pub field_id: String,
+    pub type_option_data: Vec<u8>,
+}
+
+impl TryInto<UpdateFieldTypeOptionParams> for UpdateFieldTypeOptionPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<UpdateFieldTypeOptionParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let _ = NotEmptyStr::parse(self.field_id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+
+        Ok(UpdateFieldTypeOptionParams {
+            grid_id: grid_id.0,
+            field_id: self.field_id,
+            type_option_data: self.type_option_data,
+        })
+    }
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct QueryFieldPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_orders: RepeatedFieldOrder,
+}
+
+pub struct QueryFieldParams {
+    pub grid_id: String,
+    pub field_orders: RepeatedFieldOrder,
+}
+
+impl TryInto<QueryFieldParams> for QueryFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<QueryFieldParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(QueryFieldParams {
+            grid_id: grid_id.0,
+            field_orders: self.field_orders,
+        })
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct FieldChangesetPayload {
+    #[pb(index = 1)]
+    pub field_id: String,
+
+    #[pb(index = 2)]
+    pub grid_id: String,
+
+    #[pb(index = 3, one_of)]
+    pub name: Option<String>,
+
+    #[pb(index = 4, one_of)]
+    pub desc: Option<String>,
+
+    #[pb(index = 5, one_of)]
+    pub field_type: Option<FieldType>,
+
+    #[pb(index = 6, one_of)]
+    pub frozen: Option<bool>,
+
+    #[pb(index = 7, one_of)]
+    pub visibility: Option<bool>,
+
+    #[pb(index = 8, one_of)]
+    pub width: Option<i32>,
+
+    #[pb(index = 9, one_of)]
+    pub type_option_data: Option<Vec<u8>>,
+}
+
+impl TryInto<FieldChangesetParams> for FieldChangesetPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<FieldChangesetParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+        let field_type = self.field_type.map(FieldTypeRevision::from);
+        if let Some(type_option_data) = self.type_option_data.as_ref() {
+            if type_option_data.is_empty() {
+                return Err(ErrorCode::TypeOptionDataIsEmpty);
+            }
+        }
+
+        Ok(FieldChangesetParams {
+            field_id: field_id.0,
+            grid_id: grid_id.0,
+            name: self.name,
+            desc: self.desc,
+            field_type,
+            frozen: self.frozen,
+            visibility: self.visibility,
+            width: self.width,
+            type_option_data: self.type_option_data,
+        })
+    }
+}
+
+#[derive(
+    Debug,
+    Clone,
+    PartialEq,
+    Hash,
+    Eq,
+    ProtoBuf_Enum,
+    EnumCountMacro,
+    EnumString,
+    EnumIter,
+    Display,
+    Serialize_repr,
+    Deserialize_repr,
+)]
+#[repr(u8)]
+pub enum FieldType {
+    RichText = 0,
+    Number = 1,
+    DateTime = 2,
+    SingleSelect = 3,
+    MultiSelect = 4,
+    Checkbox = 5,
+    URL = 6,
+}
+
+impl std::default::Default for FieldType {
+    fn default() -> Self {
+        FieldType::RichText
+    }
+}
+
+impl AsRef<FieldType> for FieldType {
+    fn as_ref(&self) -> &FieldType {
+        self
+    }
+}
+
+impl From<&FieldType> for FieldType {
+    fn from(field_type: &FieldType) -> Self {
+        field_type.clone()
+    }
+}
+
+impl FieldType {
+    pub fn type_id(&self) -> String {
+        (self.clone() as u8).to_string()
+    }
+
+    pub fn default_cell_width(&self) -> i32 {
+        match self {
+            FieldType::DateTime => 180,
+            _ => 150,
+        }
+    }
+
+    pub fn is_number(&self) -> bool {
+        self == &FieldType::Number
+    }
+
+    pub fn is_text(&self) -> bool {
+        self == &FieldType::RichText
+    }
+
+    pub fn is_checkbox(&self) -> bool {
+        self == &FieldType::Checkbox
+    }
+
+    pub fn is_date(&self) -> bool {
+        self == &FieldType::DateTime
+    }
+
+    pub fn is_single_select(&self) -> bool {
+        self == &FieldType::SingleSelect
+    }
+
+    pub fn is_multi_select(&self) -> bool {
+        self == &FieldType::MultiSelect
+    }
+
+    pub fn is_url(&self) -> bool {
+        self == &FieldType::URL
+    }
+
+    pub fn is_select_option(&self) -> bool {
+        self == &FieldType::MultiSelect || self == &FieldType::SingleSelect
+    }
+}
+
+impl std::convert::From<&FieldType> for FieldTypeRevision {
+    fn from(ty: &FieldType) -> Self {
+        ty.clone() as u8
+    }
+}
+
+impl std::convert::From<FieldType> for FieldTypeRevision {
+    fn from(ty: FieldType) -> Self {
+        ty as u8
+    }
+}
+
+impl std::convert::From<&FieldTypeRevision> for FieldType {
+    fn from(ty: &FieldTypeRevision) -> Self {
+        FieldType::from(*ty)
+    }
+}
+impl std::convert::From<FieldTypeRevision> for FieldType {
+    fn from(ty: FieldTypeRevision) -> Self {
+        match ty {
+            0 => FieldType::RichText,
+            1 => FieldType::Number,
+            2 => FieldType::DateTime,
+            3 => FieldType::SingleSelect,
+            4 => FieldType::MultiSelect,
+            5 => FieldType::Checkbox,
+            6 => FieldType::URL,
+            _ => {
+                tracing::error!("Can't parser FieldTypeRevision: {} to FieldType", ty);
+                FieldType::RichText
+            }
+        }
+    }
+}
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct FieldIdentifierPayload {
     #[pb(index = 1)]

+ 96 - 31
shared-lib/flowy-grid-data-model/src/entities/grid_filter.rs → frontend/rust-lib/flowy-grid/src/entities/filter_entities.rs

@@ -1,10 +1,11 @@
-use crate::parser::NotEmptyStr;
-use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_error_code::ErrorCode;
-
 use crate::entities::FieldType;
-use crate::revision::{FieldRevision, GridFilterRevision};
+use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::{FieldRevision, GridFilterRevision};
+use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams};
 use std::convert::TryInto;
+use std::sync::Arc;
 
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 pub struct GridFilter {
@@ -18,14 +19,14 @@ pub struct RepeatedGridFilter {
     pub items: Vec<GridFilter>,
 }
 
-impl std::convert::From<&GridFilterRevision> for GridFilter {
-    fn from(rev: &GridFilterRevision) -> Self {
+impl std::convert::From<&Arc<GridFilterRevision>> for GridFilter {
+    fn from(rev: &Arc<GridFilterRevision>) -> Self {
         Self { id: rev.id.clone() }
     }
 }
 
-impl std::convert::From<&Vec<GridFilterRevision>> for RepeatedGridFilter {
-    fn from(revs: &Vec<GridFilterRevision>) -> Self {
+impl std::convert::From<&Vec<Arc<GridFilterRevision>>> for RepeatedGridFilter {
+    fn from(revs: &Vec<Arc<GridFilterRevision>>) -> Self {
         RepeatedGridFilter {
             items: revs.iter().map(|rev| rev.into()).collect(),
         }
@@ -38,6 +39,29 @@ impl std::convert::From<Vec<GridFilter>> for RepeatedGridFilter {
     }
 }
 
+#[derive(ProtoBuf, Debug, Default, Clone)]
+pub struct DeleteFilterPayload {
+    #[pb(index = 1)]
+    pub filter_id: String,
+
+    #[pb(index = 2)]
+    pub field_type: FieldType,
+}
+
+impl TryInto<DeleteFilterParams> for DeleteFilterPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<DeleteFilterParams, Self::Error> {
+        let filter_id = NotEmptyStr::parse(self.filter_id)
+            .map_err(|_| ErrorCode::UnexpectedEmptyString)?
+            .0;
+        Ok(DeleteFilterParams {
+            filter_id,
+            field_type_rev: self.field_type.into(),
+        })
+    }
+}
+
 #[derive(ProtoBuf, Debug, Default, Clone)]
 pub struct CreateGridFilterPayload {
     #[pb(index = 1)]
@@ -58,20 +82,13 @@ impl CreateGridFilterPayload {
     pub fn new<T: Into<i32>>(field_rev: &FieldRevision, condition: T, content: Option<String>) -> Self {
         Self {
             field_id: field_rev.id.clone(),
-            field_type: field_rev.field_type.clone(),
+            field_type: field_rev.field_type_rev.into(),
             condition: condition.into(),
             content,
         }
     }
 }
 
-pub struct CreateGridFilterParams {
-    pub field_id: String,
-    pub field_type: FieldType,
-    pub condition: u8,
-    pub content: Option<String>,
-}
-
 impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
     type Error = ErrorCode;
 
@@ -81,9 +98,12 @@ impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
             .0;
         let condition = self.condition as u8;
         match self.field_type {
-            FieldType::RichText | FieldType::Checkbox | FieldType::URL => {
+            FieldType::RichText | FieldType::URL => {
                 let _ = TextFilterCondition::try_from(condition)?;
             }
+            FieldType::Checkbox => {
+                let _ = CheckboxCondition::try_from(condition)?;
+            }
             FieldType::Number => {
                 let _ = NumberFilterCondition::try_from(condition)?;
             }
@@ -97,7 +117,7 @@ impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
 
         Ok(CreateGridFilterParams {
             field_id,
-            field_type: self.field_type,
+            field_type_rev: self.field_type.into(),
             condition,
             content: self.content,
         })
@@ -154,11 +174,11 @@ impl std::convert::TryFrom<u8> for TextFilterCondition {
     }
 }
 
-impl std::convert::From<GridFilterRevision> for GridTextFilter {
-    fn from(rev: GridFilterRevision) -> Self {
+impl std::convert::From<Arc<GridFilterRevision>> for GridTextFilter {
+    fn from(rev: Arc<GridFilterRevision>) -> Self {
         GridTextFilter {
             condition: TextFilterCondition::try_from(rev.condition).unwrap_or(TextFilterCondition::Is),
-            content: rev.content,
+            content: rev.content.clone(),
         }
     }
 }
@@ -213,11 +233,11 @@ impl std::convert::TryFrom<u8> for NumberFilterCondition {
     }
 }
 
-impl std::convert::From<GridFilterRevision> for GridNumberFilter {
-    fn from(rev: GridFilterRevision) -> Self {
+impl std::convert::From<Arc<GridFilterRevision>> for GridNumberFilter {
+    fn from(rev: Arc<GridFilterRevision>) -> Self {
         GridNumberFilter {
             condition: NumberFilterCondition::try_from(rev.condition).unwrap_or(NumberFilterCondition::Equal),
-            content: rev.content,
+            content: rev.content.clone(),
         }
     }
 }
@@ -266,11 +286,11 @@ impl std::convert::TryFrom<u8> for SelectOptionCondition {
     }
 }
 
-impl std::convert::From<GridFilterRevision> for GridSelectOptionFilter {
-    fn from(rev: GridFilterRevision) -> Self {
+impl std::convert::From<Arc<GridFilterRevision>> for GridSelectOptionFilter {
+    fn from(rev: Arc<GridFilterRevision>) -> Self {
         GridSelectOptionFilter {
             condition: SelectOptionCondition::try_from(rev.condition).unwrap_or(SelectOptionCondition::OptionIs),
-            content: rev.content,
+            content: rev.content.clone(),
         }
     }
 }
@@ -318,11 +338,56 @@ impl std::convert::TryFrom<u8> for DateFilterCondition {
         }
     }
 }
-impl std::convert::From<GridFilterRevision> for GridDateFilter {
-    fn from(rev: GridFilterRevision) -> Self {
+impl std::convert::From<Arc<GridFilterRevision>> for GridDateFilter {
+    fn from(rev: Arc<GridFilterRevision>) -> Self {
         GridDateFilter {
             condition: DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs),
-            content: rev.content,
+            content: rev.content.clone(),
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridCheckboxFilter {
+    #[pb(index = 1)]
+    pub condition: CheckboxCondition,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
+#[repr(u8)]
+pub enum CheckboxCondition {
+    IsChecked = 0,
+    IsUnChecked = 1,
+}
+
+impl std::convert::From<CheckboxCondition> for i32 {
+    fn from(value: CheckboxCondition) -> Self {
+        value as i32
+    }
+}
+
+impl std::default::Default for CheckboxCondition {
+    fn default() -> Self {
+        CheckboxCondition::IsChecked
+    }
+}
+
+impl std::convert::TryFrom<u8> for CheckboxCondition {
+    type Error = ErrorCode;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(CheckboxCondition::IsChecked),
+            1 => Ok(CheckboxCondition::IsUnChecked),
+            _ => Err(ErrorCode::InvalidData),
+        }
+    }
+}
+
+impl std::convert::From<Arc<GridFilterRevision>> for GridCheckboxFilter {
+    fn from(rev: Arc<GridFilterRevision>) -> Self {
+        GridCheckboxFilter {
+            condition: CheckboxCondition::try_from(rev.condition).unwrap_or(CheckboxCondition::IsChecked),
         }
     }
 }

+ 106 - 0
frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs

@@ -0,0 +1,106 @@
+use crate::entities::{FieldOrder, GridBlock};
+use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct Grid {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub field_orders: Vec<FieldOrder>,
+
+    #[pb(index = 3)]
+    pub blocks: Vec<GridBlock>,
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct CreateGridPayload {
+    #[pb(index = 1)]
+    pub name: String,
+}
+
+#[derive(Clone, ProtoBuf, Default, Debug)]
+pub struct GridId {
+    #[pb(index = 1)]
+    pub value: String,
+}
+
+impl AsRef<str> for GridId {
+    fn as_ref(&self) -> &str {
+        &self.value
+    }
+}
+
+#[derive(Clone, ProtoBuf, Default, Debug)]
+pub struct GridBlockId {
+    #[pb(index = 1)]
+    pub value: String,
+}
+
+impl AsRef<str> for GridBlockId {
+    fn as_ref(&self) -> &str {
+        &self.value
+    }
+}
+
+impl std::convert::From<&str> for GridBlockId {
+    fn from(s: &str) -> Self {
+        GridBlockId { value: s.to_owned() }
+    }
+}
+
+#[derive(Debug, Clone, ProtoBuf_Enum)]
+pub enum MoveItemType {
+    MoveField = 0,
+    MoveRow = 1,
+}
+
+impl std::default::Default for MoveItemType {
+    fn default() -> Self {
+        MoveItemType::MoveField
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct MoveItemPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub item_id: String,
+
+    #[pb(index = 3)]
+    pub from_index: i32,
+
+    #[pb(index = 4)]
+    pub to_index: i32,
+
+    #[pb(index = 5)]
+    pub ty: MoveItemType,
+}
+
+#[derive(Clone)]
+pub struct MoveItemParams {
+    pub grid_id: String,
+    pub item_id: String,
+    pub from_index: i32,
+    pub to_index: i32,
+    pub ty: MoveItemType,
+}
+
+impl TryInto<MoveItemParams> for MoveItemPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<MoveItemParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let item_id = NotEmptyStr::parse(self.item_id).map_err(|_| ErrorCode::InvalidData)?;
+        Ok(MoveItemParams {
+            grid_id: grid_id.0,
+            item_id: item_id.0,
+            from_index: self.from_index,
+            to_index: self.to_index,
+            ty: self.ty,
+        })
+    }
+}

+ 4 - 9
shared-lib/flowy-grid-data-model/src/entities/grid_group.rs → frontend/rust-lib/flowy-grid/src/entities/group_entities.rs

@@ -1,8 +1,8 @@
-use crate::parser::NotEmptyStr;
 use flowy_derive::ProtoBuf;
-use flowy_error_code::ErrorCode;
-
-use crate::revision::GridGroupRevision;
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::GridGroupRevision;
+use flowy_sync::entities::grid::CreateGridGroupParams;
 use std::convert::TryInto;
 
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
@@ -56,11 +56,6 @@ pub struct CreateGridGroupPayload {
     pub sub_field_id: Option<String>,
 }
 
-pub struct CreateGridGroupParams {
-    pub field_id: Option<String>,
-    pub sub_field_id: Option<String>,
-}
-
 impl TryInto<CreateGridGroupParams> for CreateGridGroupPayload {
     type Error = ErrorCode;
 

+ 12 - 0
frontend/rust-lib/flowy-grid/src/entities/mod.rs

@@ -1,7 +1,19 @@
+mod block_entities;
 mod cell_entities;
 mod field_entities;
+mod filter_entities;
+mod grid_entities;
+mod group_entities;
 mod row_entities;
+mod setting_entities;
+mod sort_entities;
 
+pub use block_entities::*;
 pub use cell_entities::*;
 pub use field_entities::*;
+pub use filter_entities::*;
+pub use grid_entities::*;
+pub use group_entities::*;
 pub use row_entities::*;
+pub use setting_entities::*;
+pub use sort_entities::*;

+ 53 - 5
frontend/rust-lib/flowy-grid/src/entities/row_entities.rs

@@ -3,29 +3,77 @@ use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
 
 #[derive(ProtoBuf, Default)]
-pub struct RowIdentifierPayload {
+pub struct GridRowIdPayload {
     #[pb(index = 1)]
     pub grid_id: String,
 
+    #[pb(index = 2)]
+    pub block_id: String,
+
     #[pb(index = 3)]
     pub row_id: String,
 }
 
-pub struct RowIdentifier {
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct GridRowId {
+    #[pb(index = 1)]
     pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub block_id: String,
+
+    #[pb(index = 3)]
     pub row_id: String,
 }
 
-impl TryInto<RowIdentifier> for RowIdentifierPayload {
+impl TryInto<GridRowId> for GridRowIdPayload {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<RowIdentifier, Self::Error> {
+    fn try_into(self) -> Result<GridRowId, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        // let block_id = NotEmptyStr::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
 
-        Ok(RowIdentifier {
+        Ok(GridRowId {
             grid_id: grid_id.0,
+            block_id: self.block_id,
             row_id: row_id.0,
         })
     }
 }
+
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct BlockRowId {
+    #[pb(index = 1)]
+    pub block_id: String,
+
+    #[pb(index = 2)]
+    pub row_id: String,
+}
+
+#[derive(ProtoBuf, Default)]
+pub struct CreateRowPayload {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2, one_of)]
+    pub start_row_id: Option<String>,
+}
+
+#[derive(Default)]
+pub struct CreateRowParams {
+    pub grid_id: String,
+    pub start_row_id: Option<String>,
+}
+
+impl TryInto<CreateRowParams> for CreateRowPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateRowParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(CreateRowParams {
+            grid_id: grid_id.0,
+            start_row_id: self.start_row_id,
+        })
+    }
+}

+ 38 - 53
shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs → frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs

@@ -1,11 +1,12 @@
 use crate::entities::{
-    CreateGridFilterParams, CreateGridFilterPayload, CreateGridGroupParams, CreateGridGroupPayload,
-    CreateGridSortParams, CreateGridSortPayload, RepeatedGridFilter, RepeatedGridGroup, RepeatedGridSort,
+    CreateGridFilterPayload, CreateGridGroupPayload, CreateGridSortPayload, DeleteFilterPayload, RepeatedGridFilter,
+    RepeatedGridGroup, RepeatedGridSort,
 };
-use crate::parser::NotEmptyStr;
-use crate::revision::{GridLayoutRevision, GridSettingRevision};
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_error_code::ErrorCode;
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::GridLayoutRevision;
+use flowy_sync::entities::grid::GridSettingChangesetParams;
 use std::collections::HashMap;
 use std::convert::TryInto;
 
@@ -21,34 +22,35 @@ pub struct GridSetting {
     pub sorts_by_layout_ty: HashMap<String, RepeatedGridSort>,
 }
 
-impl std::convert::From<&GridSettingRevision> for GridSetting {
-    fn from(rev: &GridSettingRevision) -> Self {
-        let filters_by_layout_ty: HashMap<String, RepeatedGridFilter> = rev
-            .filters
-            .iter()
-            .map(|(layout_rev, filter_revs)| (layout_rev.to_string(), filter_revs.into()))
-            .collect();
-
-        let groups_by_layout_ty: HashMap<String, RepeatedGridGroup> = rev
-            .groups
-            .iter()
-            .map(|(layout_rev, group_revs)| (layout_rev.to_string(), group_revs.into()))
-            .collect();
-
-        let sorts_by_layout_ty: HashMap<String, RepeatedGridSort> = rev
-            .sorts
-            .iter()
-            .map(|(layout_rev, sort_revs)| (layout_rev.to_string(), sort_revs.into()))
-            .collect();
-
-        GridSetting {
-            filters_by_layout_ty,
-            groups_by_layout_ty,
-            sorts_by_layout_ty,
-        }
-    }
-}
-
+//
+// impl std::convert::From<&GridSettingRevision> for GridSetting {
+//     fn from(rev: &GridSettingRevision) -> Self {
+//         let filters_by_layout_ty: HashMap<String, RepeatedGridFilter> = rev
+//             .filters
+//             .iter()
+//             .map(|(layout_rev, filter_revs)| (layout_rev.to_string(), filter_revs.into()))
+//             .collect();
+//
+//         let groups_by_layout_ty: HashMap<String, RepeatedGridGroup> = rev
+//             .groups
+//             .iter()
+//             .map(|(layout_rev, group_revs)| (layout_rev.to_string(), group_revs.into()))
+//             .collect();
+//
+//         let sorts_by_layout_ty: HashMap<String, RepeatedGridSort> = rev
+//             .sorts
+//             .iter()
+//             .map(|(layout_rev, sort_revs)| (layout_rev.to_string(), sort_revs.into()))
+//             .collect();
+//
+//         GridSetting {
+//             filters_by_layout_ty,
+//             groups_by_layout_ty,
+//             sorts_by_layout_ty,
+//         }
+//     }
+// }
+//
 #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
 #[repr(u8)]
 pub enum GridLayoutType {
@@ -92,7 +94,7 @@ pub struct GridSettingChangesetPayload {
     pub insert_filter: Option<CreateGridFilterPayload>,
 
     #[pb(index = 4, one_of)]
-    pub delete_filter: Option<String>,
+    pub delete_filter: Option<DeleteFilterPayload>,
 
     #[pb(index = 5, one_of)]
     pub insert_group: Option<CreateGridGroupPayload>,
@@ -107,23 +109,6 @@ pub struct GridSettingChangesetPayload {
     pub delete_sort: Option<String>,
 }
 
-pub struct GridSettingChangesetParams {
-    pub grid_id: String,
-    pub layout_type: GridLayoutType,
-    pub insert_filter: Option<CreateGridFilterParams>,
-    pub delete_filter: Option<String>,
-    pub insert_group: Option<CreateGridGroupParams>,
-    pub delete_group: Option<String>,
-    pub insert_sort: Option<CreateGridSortParams>,
-    pub delete_sort: Option<String>,
-}
-
-impl GridSettingChangesetParams {
-    pub fn is_filter_changed(&self) -> bool {
-        self.insert_filter.is_some() || self.delete_filter.is_some()
-    }
-}
-
 impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayload {
     type Error = ErrorCode;
 
@@ -139,7 +124,7 @@ impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayload {
 
         let delete_filter = match self.delete_filter {
             None => None,
-            Some(filter_id) => Some(NotEmptyStr::parse(filter_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+            Some(payload) => Some(payload.try_into()?),
         };
 
         let insert_group = match self.insert_group {
@@ -164,7 +149,7 @@ impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayload {
 
         Ok(GridSettingChangesetParams {
             grid_id: view_id,
-            layout_type: self.layout_type,
+            layout_type: self.layout_type.into(),
             insert_filter,
             delete_filter,
             insert_group,

+ 4 - 8
shared-lib/flowy-grid-data-model/src/entities/grid_sort.rs → frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs

@@ -1,8 +1,8 @@
-use crate::parser::NotEmptyStr;
 use flowy_derive::ProtoBuf;
-use flowy_error_code::ErrorCode;
-
-use crate::revision::GridSortRevision;
+use flowy_error::ErrorCode;
+use flowy_grid_data_model::parser::NotEmptyStr;
+use flowy_grid_data_model::revision::GridSortRevision;
+use flowy_sync::entities::grid::CreateGridSortParams;
 use std::convert::TryInto;
 
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
@@ -50,10 +50,6 @@ pub struct CreateGridSortPayload {
     pub field_id: Option<String>,
 }
 
-pub struct CreateGridSortParams {
-    pub field_id: Option<String>,
-}
-
 impl TryInto<CreateGridSortParams> for CreateGridSortPayload {
     type Error = ErrorCode;
 

+ 23 - 14
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -3,8 +3,8 @@ use crate::manager::GridManager;
 use crate::services::field::type_options::*;
 use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str};
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::*;
 use flowy_grid_data_model::revision::FieldRevision;
+use flowy_sync::entities::grid::{FieldChangesetParams, GridSettingChangesetParams};
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::sync::Arc;
 
@@ -59,7 +59,12 @@ pub(crate) async fn get_fields_handler(
 ) -> DataResult<RepeatedField, FlowyError> {
     let params: QueryFieldParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
-    let field_orders = params.field_orders.items;
+    let field_orders = params
+        .field_orders
+        .items
+        .into_iter()
+        .map(|field_order| field_order.field_id)
+        .collect();
     let field_revs = editor.get_field_revs(Some(field_orders)).await?;
     let repeated_field: RepeatedField = field_revs.into_iter().map(Field::from).collect::<Vec<_>>().into();
     data_result(repeated_field)
@@ -126,7 +131,7 @@ pub(crate) async fn switch_to_field_handler(
     let field_rev = editor
         .get_field_rev(&params.field_id)
         .await
-        .unwrap_or(editor.next_field_rev(&params.field_type).await?);
+        .unwrap_or(Arc::new(editor.next_field_rev(&params.field_type).await?));
 
     let type_option_data = get_type_option_data(&field_rev, &params.field_type).await?;
     let data = FieldTypeOptionData {
@@ -160,7 +165,8 @@ pub(crate) async fn get_field_type_option_data_handler(
     match editor.get_field_rev(&params.field_id).await {
         None => Err(FlowyError::record_not_found()),
         Some(field_rev) => {
-            let type_option_data = get_type_option_data(&field_rev, &field_rev.field_type).await?;
+            let field_type = field_rev.field_type_rev.into();
+            let type_option_data = get_type_option_data(&field_rev, &field_type).await?;
             let data = FieldTypeOptionData {
                 grid_id: params.grid_id,
                 field: field_rev.into(),
@@ -180,7 +186,8 @@ pub(crate) async fn create_field_type_option_data_handler(
     let params: CreateFieldParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let field_rev = editor.create_next_field_rev(&params.field_type).await?;
-    let type_option_data = get_type_option_data(&field_rev, &field_rev.field_type).await?;
+    let field_type: FieldType = field_rev.field_type_rev.into();
+    let type_option_data = get_type_option_data(&field_rev, &field_type).await?;
 
     data_result(FieldTypeOptionData {
         grid_id: params.grid_id,
@@ -205,7 +212,8 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType)
     let s = field_rev
         .get_type_option_str(field_type)
         .unwrap_or_else(|| default_type_option_builder_from_type(field_type).entry().json_str());
-    let builder = type_option_builder_from_json_str(&s, &field_rev.field_type);
+    let field_type: FieldType = field_rev.field_type_rev.into();
+    let builder = type_option_builder_from_json_str(&s, &field_type);
     let type_option_data = builder.entry().protobuf_bytes().to_vec();
 
     Ok(type_option_data)
@@ -213,10 +221,10 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType)
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn get_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<OptionalRow, FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let row = OptionalRow {
         row: editor.get_row(&params.row_id).await?,
@@ -226,10 +234,10 @@ pub(crate) async fn get_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn delete_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.delete_row(&params.row_id).await?;
     Ok(())
@@ -237,10 +245,10 @@ pub(crate) async fn delete_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn duplicate_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.duplicate_row(&params.row_id).await?;
     Ok(())
@@ -307,7 +315,8 @@ pub(crate) async fn update_select_option_handler(
     let editor = manager.get_grid_editor(&changeset.cell_identifier.grid_id)?;
 
     if let Some(mut field_rev) = editor.get_field_rev(&changeset.cell_identifier.field_id).await {
-        let mut type_option = select_option_operation(&field_rev)?;
+        let mut_field_rev = Arc::make_mut(&mut field_rev);
+        let mut type_option = select_option_operation(mut_field_rev)?;
         let mut cell_content_changeset = None;
 
         if let Some(option) = changeset.insert_option {
@@ -324,7 +333,7 @@ pub(crate) async fn update_select_option_handler(
             type_option.delete_option(option);
         }
 
-        field_rev.insert_type_option_entry(&*type_option);
+        mut_field_rev.insert_type_option_entry(&*type_option);
         let _ = editor.replace_field(field_rev).await?;
 
         let changeset = CellChangeset {

+ 3 - 3
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -99,13 +99,13 @@ pub enum GridEvent {
     #[event(input = "CreateRowPayload", output = "Row")]
     CreateRow = 50,
 
-    #[event(input = "RowIdentifierPayload", output = "OptionalRow")]
+    #[event(input = "GridRowIdPayload", output = "OptionalRow")]
     GetRow = 51,
 
-    #[event(input = "RowIdentifierPayload")]
+    #[event(input = "GridRowIdPayload")]
     DeleteRow = 52,
 
-    #[event(input = "RowIdentifierPayload")]
+    #[event(input = "GridRowIdPayload")]
     DuplicateRow = 53,
 
     #[event(input = "CellIdentifierPayload", output = "Cell")]

+ 10 - 5
frontend/rust-lib/flowy-grid/src/macros.rs

@@ -30,7 +30,16 @@ macro_rules! impl_type_option {
     ($target: ident, $field_type:expr) => {
         impl std::convert::From<&FieldRevision> for $target {
             fn from(field_rev: &FieldRevision) -> $target {
-                match field_rev.get_type_option_entry::<$target>(&$field_type) {
+                match field_rev.get_type_option_entry::<$target, _>(&$field_type) {
+                    None => $target::default(),
+                    Some(target) => target,
+                }
+            }
+        }
+
+        impl std::convert::From<&std::sync::Arc<FieldRevision>> for $target {
+            fn from(field_rev: &std::sync::Arc<FieldRevision>) -> $target {
+                match field_rev.get_type_option_entry::<$target, _>(&$field_type) {
                     None => $target::default(),
                     Some(target) => target,
                 }
@@ -44,10 +53,6 @@ macro_rules! impl_type_option {
         }
 
         impl TypeOptionDataEntry for $target {
-            fn field_type(&self) -> FieldType {
-                $field_type
-            }
-
             fn json_str(&self) -> String {
                 match serde_json::to_string(&self) {
                     Ok(s) => s,

+ 58 - 50
frontend/rust-lib/flowy-grid/src/services/block_manager.rs

@@ -1,15 +1,13 @@
 use crate::dart_notification::{send_dart_notification, GridNotification};
+use crate::entities::{BlockRowInfo, CellChangeset, GridRowId, GridRowsChangeset, IndexRowOrder, Row, UpdatedRowOrder};
 use crate::manager::GridUser;
 use crate::services::block_revision_editor::GridBlockRevisionEditor;
 use crate::services::persistence::block_index::BlockIndexCache;
 use crate::services::row::{block_from_row_orders, GridBlockSnapshot};
 use dashmap::DashMap;
 use flowy_error::FlowyResult;
-use flowy_grid_data_model::entities::{
-    CellChangeset, GridRowsChangeset, IndexRowOrder, Row, RowOrder, UpdatedRowOrder,
-};
 use flowy_grid_data_model::revision::{
-    CellRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
+    GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
 };
 use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence;
 use flowy_revision::{RevisionManager, RevisionPersistence};
@@ -23,7 +21,7 @@ pub(crate) struct GridBlockManager {
     grid_id: String,
     user: Arc<dyn GridUser>,
     persistence: Arc<BlockIndexCache>,
-    block_editor_map: DashMap<BlockId, Arc<GridBlockRevisionEditor>>,
+    block_editors: DashMap<BlockId, Arc<GridBlockRevisionEditor>>,
 }
 
 impl GridBlockManager {
@@ -33,13 +31,13 @@ impl GridBlockManager {
         block_meta_revs: Vec<Arc<GridBlockMetaRevision>>,
         persistence: Arc<BlockIndexCache>,
     ) -> FlowyResult<Self> {
-        let editor_map = make_block_meta_editor_map(user, block_meta_revs).await?;
+        let block_editors = make_block_editors(user, block_meta_revs).await?;
         let user = user.clone();
         let grid_id = grid_id.to_owned();
         let manager = Self {
             grid_id,
             user,
-            block_editor_map: editor_map,
+            block_editors,
             persistence,
         };
         Ok(manager)
@@ -48,11 +46,11 @@ impl GridBlockManager {
     // #[tracing::instrument(level = "trace", skip(self))]
     pub(crate) async fn get_editor(&self, block_id: &str) -> FlowyResult<Arc<GridBlockRevisionEditor>> {
         debug_assert!(!block_id.is_empty());
-        match self.block_editor_map.get(block_id) {
+        match self.block_editors.get(block_id) {
             None => {
                 tracing::error!("This is a fatal error, block with id:{} is not exist", block_id);
-                let editor = Arc::new(make_block_meta_editor(&self.user, block_id).await?);
-                self.block_editor_map.insert(block_id.to_owned(), editor.clone());
+                let editor = Arc::new(make_block_editor(&self.user, block_id).await?);
+                self.block_editors.insert(block_id.to_owned(), editor.clone());
                 Ok(editor)
             }
             Some(editor) => Ok(editor.clone()),
@@ -135,12 +133,18 @@ impl GridBlockManager {
         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?;
-        match editor.get_row_order(&row_id).await? {
+        match editor.get_row_info(&row_id).await? {
             None => {}
-            Some(row_order) => {
+            Some(row_info) => {
                 let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?;
+
+                let row_identifier = GridRowId {
+                    grid_id: self.grid_id.clone(),
+                    block_id: row_info.block_id,
+                    row_id: row_info.row_id,
+                };
                 let _ = self
-                    .notify_did_update_block(&block_id, GridRowsChangeset::delete(&block_id, vec![row_order]))
+                    .notify_did_update_block(&block_id, GridRowsChangeset::delete(&block_id, vec![row_identifier]))
                     .await?;
             }
         }
@@ -150,18 +154,18 @@ impl GridBlockManager {
 
     pub(crate) async fn delete_rows(
         &self,
-        row_orders: Vec<RowOrder>,
+        row_orders: Vec<BlockRowInfo>,
     ) -> FlowyResult<Vec<GridBlockMetaRevisionChangeset>> {
         let mut changesets = vec![];
-        for block_order in block_from_row_orders(row_orders) {
-            let editor = self.get_editor(&block_order.id).await?;
-            let row_ids = block_order
-                .row_orders
+        for grid_block in block_from_row_orders(row_orders) {
+            let editor = self.get_editor(&grid_block.id).await?;
+            let row_ids = grid_block
+                .row_infos
                 .into_iter()
-                .map(|row_order| Cow::Owned(row_order.row_id))
+                .map(|row_info| Cow::Owned(row_info.row_id().to_owned()))
                 .collect::<Vec<Cow<String>>>();
             let row_count = editor.delete_rows(row_ids).await?;
-            let changeset = GridBlockMetaRevisionChangeset::from_row_count(&block_order.id, row_count);
+            let changeset = GridBlockMetaRevisionChangeset::from_row_count(&grid_block.id, row_count);
             changesets.push(changeset);
         }
 
@@ -175,15 +179,21 @@ impl GridBlockManager {
         match editor.get_row_revs(Some(vec![Cow::Borrowed(row_id)])).await?.pop() {
             None => {}
             Some(row_rev) => {
-                let row_order = RowOrder::from(&row_rev);
+                let row_info = BlockRowInfo::from(&row_rev);
                 let insert_row = IndexRowOrder {
-                    row_order: row_order.clone(),
+                    row_info: row_info.clone(),
                     index: Some(to as i32),
                 };
+
+                let deleted_row = GridRowId {
+                    grid_id: self.grid_id.clone(),
+                    block_id: row_info.block_id,
+                    row_id: row_info.row_id,
+                };
                 let notified_changeset = GridRowsChangeset {
                     block_id: editor.block_id.clone(),
                     inserted_rows: vec![insert_row],
-                    deleted_rows: vec![row_order],
+                    deleted_rows: vec![deleted_row],
                     updated_rows: vec![],
                 };
 
@@ -217,38 +227,36 @@ impl GridBlockManager {
         }
     }
 
-    pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult<Vec<RowOrder>> {
+    pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult<Vec<BlockRowInfo>> {
         let editor = self.get_editor(block_id).await?;
-        editor.get_row_orders::<&str>(None).await
+        editor.get_row_infos::<&str>(None).await
     }
 
-    pub(crate) async fn make_block_snapshots(&self, block_ids: Vec<String>) -> FlowyResult<Vec<GridBlockSnapshot>> {
+    pub(crate) async fn get_block_snapshots(
+        &self,
+        block_ids: Option<Vec<String>>,
+    ) -> FlowyResult<Vec<GridBlockSnapshot>> {
         let mut snapshots = vec![];
-        for block_id in block_ids {
-            let editor = self.get_editor(&block_id).await?;
-            let row_revs = editor.get_row_revs::<&str>(None).await?;
-            snapshots.push(GridBlockSnapshot { block_id, row_revs });
+        match block_ids {
+            None => {
+                for iter in self.block_editors.iter() {
+                    let editor = iter.value();
+                    let block_id = editor.block_id.clone();
+                    let row_revs = editor.get_row_revs::<&str>(None).await?;
+                    snapshots.push(GridBlockSnapshot { block_id, row_revs });
+                }
+            }
+            Some(block_ids) => {
+                for block_id in block_ids {
+                    let editor = self.get_editor(&block_id).await?;
+                    let row_revs = editor.get_row_revs::<&str>(None).await?;
+                    snapshots.push(GridBlockSnapshot { block_id, row_revs });
+                }
+            }
         }
         Ok(snapshots)
     }
 
-    // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage.
-    #[allow(dead_code)]
-    pub async fn get_cell_revs(
-        &self,
-        block_ids: Vec<String>,
-        field_id: &str,
-        row_ids: Option<Vec<Cow<'_, String>>>,
-    ) -> FlowyResult<Vec<CellRevision>> {
-        let mut block_cell_revs = vec![];
-        for block_id in block_ids {
-            let editor = self.get_editor(&block_id).await?;
-            let cell_revs = editor.get_cell_revs(field_id, row_ids.clone()).await?;
-            block_cell_revs.extend(cell_revs);
-        }
-        Ok(block_cell_revs)
-    }
-
     async fn notify_did_update_block(&self, block_id: &str, changeset: GridRowsChangeset) -> FlowyResult<()> {
         send_dart_notification(block_id, GridNotification::DidUpdateGridBlock)
             .payload(changeset)
@@ -263,20 +271,20 @@ impl GridBlockManager {
     }
 }
 
-async fn make_block_meta_editor_map(
+async fn make_block_editors(
     user: &Arc<dyn GridUser>,
     block_meta_revs: Vec<Arc<GridBlockMetaRevision>>,
 ) -> FlowyResult<DashMap<String, Arc<GridBlockRevisionEditor>>> {
     let editor_map = DashMap::new();
     for block_meta_rev in block_meta_revs {
-        let editor = make_block_meta_editor(user, &block_meta_rev.block_id).await?;
+        let editor = make_block_editor(user, &block_meta_rev.block_id).await?;
         editor_map.insert(block_meta_rev.block_id.clone(), Arc::new(editor));
     }
 
     Ok(editor_map)
 }
 
-async fn make_block_meta_editor(user: &Arc<dyn GridUser>, block_id: &str) -> FlowyResult<GridBlockRevisionEditor> {
+async fn make_block_editor(user: &Arc<dyn GridUser>, block_id: &str) -> FlowyResult<GridBlockRevisionEditor> {
     tracing::trace!("Open block:{} meta editor", block_id);
     let token = user.token()?;
     let user_id = user.user_id()?;

+ 8 - 8
frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs

@@ -1,6 +1,6 @@
+use crate::entities::BlockRowInfo;
 use bytes::Bytes;
 use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::RowOrder;
 use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision};
 use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
 use flowy_sync::client_grid::{GridBlockMetaChange, GridBlockRevisionPad};
@@ -123,24 +123,24 @@ impl GridBlockRevisionEditor {
         Ok(cell_revs)
     }
 
-    pub async fn get_row_order(&self, row_id: &str) -> FlowyResult<Option<RowOrder>> {
+    pub async fn get_row_info(&self, row_id: &str) -> FlowyResult<Option<BlockRowInfo>> {
         let row_ids = Some(vec![Cow::Borrowed(row_id)]);
-        Ok(self.get_row_orders(row_ids).await?.pop())
+        Ok(self.get_row_infos(row_ids).await?.pop())
     }
 
-    pub async fn get_row_orders<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<RowOrder>>
+    pub async fn get_row_infos<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<BlockRowInfo>>
     where
         T: AsRef<str> + ToOwned + ?Sized,
     {
-        let row_orders = self
+        let row_infos = self
             .pad
             .read()
             .await
             .get_row_revs(row_ids)?
             .iter()
-            .map(RowOrder::from)
-            .collect::<Vec<RowOrder>>();
-        Ok(row_orders)
+            .map(BlockRowInfo::from)
+            .collect::<Vec<BlockRowInfo>>();
+        Ok(row_infos)
     }
 
     async fn modify<F>(&self, f: F) -> FlowyResult<()>

+ 5 - 4
frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs

@@ -1,6 +1,6 @@
+use crate::entities::{Field, FieldType};
 use crate::services::field::type_options::*;
 use bytes::Bytes;
-use flowy_grid_data_model::entities::{Field, FieldType};
 use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry};
 use indexmap::IndexMap;
 
@@ -14,7 +14,9 @@ pub type BoxTypeOptionBuilder = Box<dyn TypeOptionBuilder + 'static>;
 impl FieldBuilder {
     pub fn new<T: Into<BoxTypeOptionBuilder>>(type_option_builder: T) -> Self {
         let type_option_builder = type_option_builder.into();
-        let field_rev = FieldRevision::new("", "", type_option_builder.field_type(), false);
+        let field_type = type_option_builder.field_type();
+        let width = field_type.default_cell_width();
+        let field_rev = FieldRevision::new("", "", field_type, width, false);
         Self {
             field_rev,
             type_option_builder,
@@ -31,7 +33,7 @@ impl FieldBuilder {
             id: field.id,
             name: field.name,
             desc: field.desc,
-            field_type: field.field_type,
+            field_type_rev: field.field_type.into(),
             frozen: field.frozen,
             visibility: field.visibility,
             width: field.width,
@@ -75,7 +77,6 @@ impl FieldBuilder {
     }
 
     pub fn build(self) -> FieldRevision {
-        debug_assert_eq!(self.field_rev.field_type, self.type_option_builder.field_type());
         let mut field_rev = self.field_rev;
         field_rev.insert_type_option_entry(self.type_option_builder.entry());
         field_rev

+ 8 - 4
frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs

@@ -1,10 +1,10 @@
+use crate::entities::{FieldType, GridCheckboxFilter};
 use crate::impl_type_option;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
 use bytes::Bytes;
 use flowy_derive::ProtoBuf;
 use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use serde::{Deserialize, Serialize};
 
@@ -22,7 +22,7 @@ impl CheckboxTypeOptionBuilder {
 
 impl TypeOptionBuilder for CheckboxTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::Checkbox
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -40,7 +40,7 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
 const YES: &str = "Yes";
 const NO: &str = "No";
 
-impl CellDataOperation<String> for CheckboxTypeOption {
+impl CellDataOperation<String, GridCheckboxFilter> for CheckboxTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -62,6 +62,10 @@ impl CellDataOperation<String> for CheckboxTypeOption {
         Ok(DecodedCellData::default())
     }
 
+    fn apply_filter(&self, _filter: GridCheckboxFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -95,7 +99,7 @@ mod tests {
     use crate::services::field::FieldBuilder;
     use crate::services::row::{apply_cell_data_changeset, decode_cell_data};
 
-    use flowy_grid_data_model::entities::FieldType;
+    use crate::entities::FieldType;
 
     #[test]
     fn checkout_box_description_test() {

+ 14 - 10
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs

@@ -1,3 +1,4 @@
+use crate::entities::{CellChangeset, FieldType, GridDateFilter};
 use crate::entities::{CellIdentifier, CellIdentifierPayload};
 use crate::impl_type_option;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
@@ -7,7 +8,6 @@ use chrono::format::strftime::StrftimeItems;
 use chrono::{NaiveDateTime, Timelike};
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::{CellChangeset, FieldType};
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use serde::{Deserialize, Serialize};
 use strum_macros::EnumIter;
@@ -115,7 +115,7 @@ impl DateTypeOption {
     }
 }
 
-impl CellDataOperation<String> for DateTypeOption {
+impl CellDataOperation<String, GridDateFilter> for DateTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -138,6 +138,10 @@ impl CellDataOperation<String> for DateTypeOption {
         DecodedCellData::try_from_bytes(date)
     }
 
+    fn apply_filter(&self, _filter: GridDateFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -177,7 +181,7 @@ impl DateTypeOptionBuilder {
 }
 impl TypeOptionBuilder for DateTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::DateTime
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -354,11 +358,11 @@ impl std::convert::From<DateCellContentChangeset> for CellContentChangeset {
 
 #[cfg(test)]
 mod tests {
+    use crate::entities::FieldType;
     use crate::services::field::FieldBuilder;
     use crate::services::field::{DateCellContentChangeset, DateCellData, DateFormat, DateTypeOption, TimeFormat};
     use crate::services::row::CellDataOperation;
-    use flowy_grid_data_model::entities::FieldType;
-    use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry};
+    use flowy_grid_data_model::revision::FieldRevision;
     use strum::IntoEnumIterator;
 
     #[test]
@@ -530,7 +534,7 @@ mod tests {
     fn date_type_option_apply_changeset_error_test() {
         let mut type_option = DateTypeOption::new();
         type_option.include_time = true;
-        let field_rev = FieldBuilder::from_field_type(&type_option.field_type()).build();
+        let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
         let date_timestamp = "1653609600".to_owned();
 
         assert_changeset_result(
@@ -539,7 +543,7 @@ mod tests {
                 date: Some(date_timestamp.clone()),
                 time: Some("1:".to_owned()),
             },
-            &type_option.field_type(),
+            &FieldType::DateTime,
             &field_rev,
             "May 27,2022 01:00",
         );
@@ -550,7 +554,7 @@ mod tests {
                 date: Some(date_timestamp),
                 time: Some("1:00".to_owned()),
             },
-            &type_option.field_type(),
+            &FieldType::DateTime,
             &field_rev,
             "May 27,2022 01:00",
         );
@@ -561,7 +565,7 @@ mod tests {
     fn date_type_option_twelve_hours_to_twenty_four_hours() {
         let mut type_option = DateTypeOption::new();
         type_option.include_time = true;
-        let field_rev = FieldBuilder::from_field_type(&type_option.field_type()).build();
+        let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
         let date_timestamp = "1653609600".to_owned();
 
         assert_changeset_result(
@@ -570,7 +574,7 @@ mod tests {
                 date: Some(date_timestamp),
                 time: Some("1:00 am".to_owned()),
             },
-            &type_option.field_type(),
+            &FieldType::DateTime,
             &field_rev,
             "May 27,2022 01:00",
         );

+ 3 - 3
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/format.rs

@@ -15,7 +15,7 @@ lazy_static! {
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
 pub enum NumberFormat {
-    Number = 0,
+    Num = 0,
     USD = 1,
     CanadianDollar = 2,
     EUR = 4,
@@ -55,7 +55,7 @@ pub enum NumberFormat {
 
 impl std::default::Default for NumberFormat {
     fn default() -> Self {
-        NumberFormat::Number
+        NumberFormat::Num
     }
 }
 
@@ -400,7 +400,7 @@ define_currency_set!(
 impl NumberFormat {
     pub fn currency(&self) -> &'static number_currency::Currency {
         match self {
-            NumberFormat::Number => number_currency::NUMBER,
+            NumberFormat::Num => number_currency::NUMBER,
             NumberFormat::USD => number_currency::USD,
             NumberFormat::CanadianDollar => number_currency::CANADIAN_DOLLAR,
             NumberFormat::EUR => number_currency::EUR,

+ 13 - 9
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs

@@ -1,12 +1,12 @@
 use crate::impl_type_option;
 
+use crate::entities::{FieldType, GridNumberFilter};
 use crate::services::field::type_options::number_type_option::format::*;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
 use bytes::Bytes;
 use flowy_derive::ProtoBuf;
 use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use rust_decimal::Decimal;
 use serde::{Deserialize, Serialize};
@@ -41,7 +41,7 @@ impl NumberTypeOptionBuilder {
 
 impl TypeOptionBuilder for NumberTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::Number
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -76,7 +76,7 @@ impl NumberTypeOption {
 
     fn cell_content_from_number_str(&self, s: &str) -> FlowyResult<String> {
         match self.format {
-            NumberFormat::Number => {
+            NumberFormat::Num => {
                 if let Ok(v) = s.parse::<f64>() {
                     return Ok(v.to_string());
                 }
@@ -139,7 +139,7 @@ impl NumberTypeOption {
     }
 }
 
-impl CellDataOperation<String> for NumberTypeOption {
+impl CellDataOperation<String, GridNumberFilter> for NumberTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -155,7 +155,7 @@ impl CellDataOperation<String> for NumberTypeOption {
 
         let cell_data = encoded_data.into();
         match self.format {
-            NumberFormat::Number => {
+            NumberFormat::Num => {
                 if let Ok(v) = cell_data.parse::<f64>() {
                     return Ok(DecodedCellData::new(v.to_string()));
                 }
@@ -179,6 +179,10 @@ impl CellDataOperation<String> for NumberTypeOption {
         }
     }
 
+    fn apply_filter(&self, _filter: GridNumberFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -206,10 +210,10 @@ impl std::default::Default for NumberTypeOption {
 
 #[cfg(test)]
 mod tests {
+    use crate::entities::FieldType;
     use crate::services::field::FieldBuilder;
     use crate::services::field::{NumberFormat, NumberTypeOption};
     use crate::services::row::CellDataOperation;
-    use flowy_grid_data_model::entities::FieldType;
     use flowy_grid_data_model::revision::FieldRevision;
     use strum::IntoEnumIterator;
 
@@ -241,7 +245,7 @@ mod tests {
         for format in NumberFormat::iter() {
             type_option.format = format;
             match format {
-                NumberFormat::Number => {
+                NumberFormat::Num => {
                     assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
                 }
                 NumberFormat::USD => {
@@ -270,7 +274,7 @@ mod tests {
         for format in NumberFormat::iter() {
             type_option.format = format;
             match format {
-                NumberFormat::Number => {
+                NumberFormat::Num => {
                     assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
                     assert_equal(&type_option, "0.2", "0.2", &field_type, &field_rev);
                 }
@@ -310,7 +314,7 @@ mod tests {
         for format in NumberFormat::iter() {
             type_option.format = format;
             match format {
-                NumberFormat::Number => {
+                NumberFormat::Num => {
                     assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
                 }
                 NumberFormat::USD => {

+ 20 - 8
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs

@@ -1,3 +1,4 @@
+use crate::entities::{CellChangeset, FieldType, GridSelectOptionFilter};
 use crate::entities::{CellIdentifier, CellIdentifierPayload};
 use crate::impl_type_option;
 use crate::services::field::type_options::util::get_cell_data;
@@ -6,7 +7,6 @@ use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellD
 use bytes::Bytes;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::{CellChangeset, FieldType};
 use flowy_grid_data_model::parser::NotEmptyStr;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use nanoid::nanoid;
@@ -49,7 +49,8 @@ pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync {
 }
 
 pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn SelectOptionOperation>> {
-    match &field_rev.field_type {
+    let field_type: FieldType = field_rev.field_type_rev.into();
+    match &field_type {
         FieldType::SingleSelect => {
             let type_option = SingleSelectTypeOption::from(field_rev);
             Ok(Box::new(type_option))
@@ -94,7 +95,7 @@ impl SelectOptionOperation for SingleSelectTypeOption {
     }
 }
 
-impl CellDataOperation<String> for SingleSelectTypeOption {
+impl CellDataOperation<String, GridSelectOptionFilter> for SingleSelectTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -122,6 +123,10 @@ impl CellDataOperation<String> for SingleSelectTypeOption {
         DecodedCellData::try_from_bytes(cell_data)
     }
 
+    fn apply_filter(&self, _filter: GridSelectOptionFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -155,7 +160,7 @@ impl SingleSelectTypeOptionBuilder {
 
 impl TypeOptionBuilder for SingleSelectTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::SingleSelect
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -192,7 +197,7 @@ impl SelectOptionOperation for MultiSelectTypeOption {
     }
 }
 
-impl CellDataOperation<String> for MultiSelectTypeOption {
+impl CellDataOperation<String, GridSelectOptionFilter> for MultiSelectTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -220,6 +225,10 @@ impl CellDataOperation<String> for MultiSelectTypeOption {
         DecodedCellData::try_from_bytes(cell_data)
     }
 
+    fn apply_filter(&self, _filter: GridSelectOptionFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<T>(&self, changeset: T, cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         T: Into<CellContentChangeset>,
@@ -269,7 +278,7 @@ impl MultiSelectTypeOptionBuilder {
 
 impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::MultiSelect
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -502,6 +511,7 @@ fn make_select_context_from(cell_rev: &Option<CellRevision>, options: &[SelectOp
 
 #[cfg(test)]
 mod tests {
+    use crate::entities::FieldType;
     use crate::services::field::FieldBuilder;
     use crate::services::field::{
         MultiSelectTypeOption, MultiSelectTypeOptionBuilder, SelectOption, SelectOptionCellContentChangeset,
@@ -606,10 +616,11 @@ mod tests {
         field_rev: &FieldRevision,
         expected: Vec<SelectOption>,
     ) {
+        let field_type: FieldType = field_rev.field_type_rev.into();
         assert_eq!(
             expected,
             type_option
-                .decode_cell_data(cell_data, &field_rev.field_type, field_rev)
+                .decode_cell_data(cell_data, &field_type, field_rev)
                 .unwrap()
                 .parse::<SelectOptionCellData>()
                 .unwrap()
@@ -623,10 +634,11 @@ mod tests {
         field_rev: &FieldRevision,
         expected: Vec<SelectOption>,
     ) {
+        let field_type: FieldType = field_rev.field_type_rev.into();
         assert_eq!(
             expected,
             type_option
-                .decode_cell_data(cell_data, &field_rev.field_type, field_rev)
+                .decode_cell_data(cell_data, &field_type, field_rev)
                 .unwrap()
                 .parse::<SelectOptionCellData>()
                 .unwrap()

+ 9 - 5
frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs

@@ -1,10 +1,10 @@
+use crate::entities::{FieldType, GridTextFilter};
 use crate::impl_type_option;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use crate::services::row::{try_decode_cell_data, CellContentChangeset, CellDataOperation, DecodedCellData};
 use bytes::Bytes;
 use flowy_derive::ProtoBuf;
 use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use serde::{Deserialize, Serialize};
 
@@ -15,7 +15,7 @@ impl_builder_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTy
 
 impl TypeOptionBuilder for RichTextTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::RichText
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -30,7 +30,7 @@ pub struct RichTextTypeOption {
 }
 impl_type_option!(RichTextTypeOption, FieldType::RichText);
 
-impl CellDataOperation<String> for RichTextTypeOption {
+impl CellDataOperation<String, GridTextFilter> for RichTextTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -45,13 +45,17 @@ impl CellDataOperation<String> for RichTextTypeOption {
             || decoded_field_type.is_multi_select()
             || decoded_field_type.is_number()
         {
-            try_decode_cell_data(encoded_data, field_rev, decoded_field_type, decoded_field_type)
+            try_decode_cell_data(encoded_data.into(), field_rev, decoded_field_type, decoded_field_type)
         } else {
             let cell_data = encoded_data.into();
             Ok(DecodedCellData::new(cell_data))
         }
     }
 
+    fn apply_filter(&self, _filter: GridTextFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -67,10 +71,10 @@ impl CellDataOperation<String> for RichTextTypeOption {
 
 #[cfg(test)]
 mod tests {
+    use crate::entities::FieldType;
     use crate::services::field::FieldBuilder;
     use crate::services::field::*;
     use crate::services::row::CellDataOperation;
-    use flowy_grid_data_model::entities::FieldType;
 
     #[test]
     fn text_description_test() {

+ 8 - 4
frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option.rs

@@ -1,3 +1,4 @@
+use crate::entities::{FieldType, GridTextFilter};
 use crate::impl_type_option;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, EncodedCellData};
@@ -5,7 +6,6 @@ use bytes::Bytes;
 use fancy_regex::Regex;
 use flowy_derive::ProtoBuf;
 use flowy_error::{internal_error, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry};
 use lazy_static::lazy_static;
 use serde::{Deserialize, Serialize};
@@ -18,7 +18,7 @@ impl_builder_from_json_str_and_from_bytes!(URLTypeOptionBuilder, URLTypeOption);
 
 impl TypeOptionBuilder for URLTypeOptionBuilder {
     fn field_type(&self) -> FieldType {
-        self.0.field_type()
+        FieldType::URL
     }
 
     fn entry(&self) -> &dyn TypeOptionDataEntry {
@@ -33,7 +33,7 @@ pub struct URLTypeOption {
 }
 impl_type_option!(URLTypeOption, FieldType::URL);
 
-impl CellDataOperation<EncodedCellData<URLCellData>> for URLTypeOption {
+impl CellDataOperation<EncodedCellData<URLCellData>, GridTextFilter> for URLTypeOption {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -50,6 +50,10 @@ impl CellDataOperation<EncodedCellData<URLCellData>> for URLTypeOption {
         DecodedCellData::try_from_bytes(cell_data)
     }
 
+    fn apply_filter(&self, _filter: GridTextFilter) -> bool {
+        todo!()
+    }
+
     fn apply_changeset<C>(&self, changeset: C, _cell_rev: Option<CellRevision>) -> Result<String, FlowyError>
     where
         C: Into<CellContentChangeset>,
@@ -122,10 +126,10 @@ lazy_static! {
 
 #[cfg(test)]
 mod tests {
+    use crate::entities::FieldType;
     use crate::services::field::FieldBuilder;
     use crate::services::field::{URLCellData, URLTypeOption};
     use crate::services::row::{CellDataOperation, EncodedCellData};
-    use flowy_grid_data_model::entities::FieldType;
     use flowy_grid_data_model::revision::FieldRevision;
 
     #[test]

+ 267 - 32
frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs

@@ -1,58 +1,293 @@
-use crate::manager::GridTaskSchedulerRwLock;
+use crate::entities::{
+    FieldType, GridCheckboxFilter, GridDateFilter, GridNumberFilter, GridSelectOptionFilter, GridTextFilter,
+};
 use crate::services::block_manager::GridBlockManager;
-use crate::services::tasks::Task;
+use crate::services::grid_editor_task::GridServiceTaskScheduler;
+use crate::services::row::GridBlockSnapshot;
+use crate::services::tasks::{FilterTaskContext, Task, TaskContent};
 use flowy_error::FlowyResult;
-
+use flowy_grid_data_model::revision::{CellRevision, FieldId, FieldRevision, RowRevision};
 use flowy_sync::client_grid::GridRevisionPad;
+use flowy_sync::entities::grid::GridSettingChangesetParams;
+use std::collections::HashMap;
 use std::sync::Arc;
 use tokio::sync::RwLock;
 
 pub(crate) struct GridFilterService {
     #[allow(dead_code)]
-    scheduler: GridTaskSchedulerRwLock,
-    #[allow(dead_code)]
+    grid_id: String,
+    scheduler: Arc<dyn GridServiceTaskScheduler>,
     grid_pad: Arc<RwLock<GridRevisionPad>>,
-    #[allow(dead_code)]
     block_manager: Arc<GridBlockManager>,
+    filter_cache: Arc<RwLock<FilterCache>>,
+    filter_result_cache: Arc<RwLock<FilterResultCache>>,
 }
 impl GridFilterService {
-    pub fn new(
+    pub async fn new<S: GridServiceTaskScheduler>(
         grid_pad: Arc<RwLock<GridRevisionPad>>,
         block_manager: Arc<GridBlockManager>,
-        scheduler: GridTaskSchedulerRwLock,
+        scheduler: S,
     ) -> Self {
+        let grid_id = grid_pad.read().await.grid_id();
+        let filter_cache = Arc::new(RwLock::new(FilterCache::from_grid_pad(&grid_pad).await));
+        let filter_result_cache = Arc::new(RwLock::new(FilterResultCache::default()));
         Self {
+            grid_id,
             grid_pad,
             block_manager,
-            scheduler,
+            scheduler: Arc::new(scheduler),
+            filter_cache,
+            filter_result_cache,
         }
     }
 
-    pub async fn process_task(&self, _task: Task) -> FlowyResult<()> {
+    pub async fn process(&self, task_context: FilterTaskContext) -> FlowyResult<()> {
+        let field_revs = self
+            .grid_pad
+            .read()
+            .await
+            .get_field_revs(None)?
+            .into_iter()
+            .map(|field_rev| (field_rev.id.clone(), field_rev))
+            .collect::<HashMap<String, Arc<FieldRevision>>>();
+
+        let mut show_rows = vec![];
+        let mut hide_rows = vec![];
+        for block in task_context.blocks {
+            block.row_revs.iter().for_each(|row_rev| {
+                let result = filter_row(row_rev, &self.filter_cache, &self.filter_result_cache, &field_revs);
+
+                if result.is_row_hidden() {
+                    hide_rows.push(result.row_id);
+                } else {
+                    show_rows.push(result.row_id);
+                }
+            });
+        }
+        self.notify(hide_rows, show_rows).await;
         Ok(())
     }
 
-    pub async fn notify_changed(&self) {
-        //
-        // let grid_pad = self.grid_pad.read().await;
-        // match grid_pad.get_filters(None) {
-        //     None => {}
-        //     Some(filter_revs) => {
-        //         filter_revs
-        //             .iter()
-        //             .for_each(|filter_rev| match grid_pad.get_field_rev(&filter_rev.field_id) {
-        //                 None => {}
-        //                 Some((_, _field_rev)) => match field_rev.field_type {
-        //                     FieldType::RichText => {}
-        //                     FieldType::Number => {}
-        //                     FieldType::DateTime => {}
-        //                     FieldType::SingleSelect => {}
-        //                     FieldType::MultiSelect => {}
-        //                     FieldType::Checkbox => {}
-        //                     FieldType::URL => {}
-        //                 },
-        //             });
-        //     }
-        // }
+    pub async fn apply_changeset(&self, changeset: GridFilterChangeset) {
+        if !changeset.is_changed() {
+            return;
+        }
+
+        if let Some(filter_id) = &changeset.insert_filter {
+            let mut cache = self.filter_cache.write().await;
+            let field_ids = Some(vec![filter_id.field_id.clone()]);
+            reload_filter_cache(&mut cache, field_ids, &self.grid_pad).await;
+        }
+
+        if let Some(filter_id) = &changeset.delete_filter {
+            self.filter_cache.write().await.remove(filter_id);
+        }
+
+        if let Ok(blocks) = self.block_manager.get_block_snapshots(None).await {
+            let task = self.gen_task(blocks).await;
+            let _ = self.scheduler.register_task(task).await;
+        }
+    }
+
+    async fn gen_task(&self, blocks: Vec<GridBlockSnapshot>) -> Task {
+        let task_id = self.scheduler.gen_task_id().await;
+        let handler_id = self.grid_pad.read().await.grid_id();
+
+        let context = FilterTaskContext { blocks };
+        Task {
+            handler_id,
+            id: task_id,
+            content: TaskContent::Filter(context),
+        }
+    }
+
+    async fn notify(&self, _hide_rows: Vec<String>, _show_rows: Vec<String>) {
+        // let notification = GridNotification {};
+        // send_dart_notification(grid_id, GridNotification::DidUpdateGridBlock)
+        //     .payload(notification)
+        //     .send();
+    }
+}
+
+fn filter_row(
+    row_rev: &Arc<RowRevision>,
+    _filter_cache: &Arc<RwLock<FilterCache>>,
+    _filter_result_cache: &Arc<RwLock<FilterResultCache>>,
+    _field_revs: &HashMap<FieldId, Arc<FieldRevision>>,
+) -> FilterResult {
+    let filter_result = FilterResult::new(row_rev);
+    row_rev.cells.iter().for_each(|(_k, cell_rev)| {
+        let _cell_rev: &CellRevision = cell_rev;
+    });
+    filter_result
+}
+
+pub struct GridFilterChangeset {
+    insert_filter: Option<FilterId>,
+    delete_filter: Option<FilterId>,
+}
+
+impl GridFilterChangeset {
+    fn is_changed(&self) -> bool {
+        self.insert_filter.is_some() || self.delete_filter.is_some()
+    }
+}
+
+impl std::convert::From<&GridSettingChangesetParams> for GridFilterChangeset {
+    fn from(params: &GridSettingChangesetParams) -> Self {
+        let insert_filter = params.insert_filter.as_ref().map(|insert_filter_params| FilterId {
+            field_id: insert_filter_params.field_id.clone(),
+            field_type: insert_filter_params.field_type_rev.into(),
+        });
+
+        let delete_filter = params.delete_filter.as_ref().map(|delete_filter_params| FilterId {
+            field_id: delete_filter_params.filter_id.clone(),
+            field_type: delete_filter_params.field_type_rev.into(),
+        });
+        GridFilterChangeset {
+            insert_filter,
+            delete_filter,
+        }
+    }
+}
+
+#[derive(Default)]
+struct FilterResultCache {
+    #[allow(dead_code)]
+    rows: HashMap<String, FilterResult>,
+}
+
+impl FilterResultCache {
+    #[allow(dead_code)]
+    fn insert(&mut self, row_id: &str, result: FilterResult) {
+        self.rows.insert(row_id.to_owned(), result);
+    }
+}
+
+#[derive(Default)]
+struct FilterResult {
+    row_id: String,
+    #[allow(dead_code)]
+    cell_by_field_id: HashMap<String, bool>,
+}
+
+impl FilterResult {
+    fn new(row_rev: &RowRevision) -> Self {
+        Self {
+            row_id: row_rev.id.clone(),
+            cell_by_field_id: row_rev.cells.iter().map(|(k, _)| (k.clone(), true)).collect(),
+        }
+    }
+
+    #[allow(dead_code)]
+    fn update_cell(&mut self, cell_id: &str, exist: bool) {
+        self.cell_by_field_id.insert(cell_id.to_owned(), exist);
+    }
+
+    fn is_row_hidden(&self) -> bool {
+        todo!()
+    }
+}
+
+#[derive(Default)]
+struct FilterCache {
+    text_filter: HashMap<FilterId, GridTextFilter>,
+    url_filter: HashMap<FilterId, GridTextFilter>,
+    number_filter: HashMap<FilterId, GridNumberFilter>,
+    date_filter: HashMap<FilterId, GridDateFilter>,
+    select_option_filter: HashMap<FilterId, GridSelectOptionFilter>,
+    checkbox_filter: HashMap<FilterId, GridCheckboxFilter>,
+}
+
+impl FilterCache {
+    async fn from_grid_pad(grid_pad: &Arc<RwLock<GridRevisionPad>>) -> Self {
+        let mut this = Self::default();
+        let _ = reload_filter_cache(&mut this, None, grid_pad).await;
+        this
+    }
+
+    fn remove(&mut self, filter_id: &FilterId) {
+        let _ = match filter_id.field_type {
+            FieldType::RichText => {
+                let _ = self.text_filter.remove(filter_id);
+            }
+            FieldType::Number => {
+                let _ = self.number_filter.remove(filter_id);
+            }
+            FieldType::DateTime => {
+                let _ = self.date_filter.remove(filter_id);
+            }
+            FieldType::SingleSelect => {
+                let _ = self.select_option_filter.remove(filter_id);
+            }
+            FieldType::MultiSelect => {
+                let _ = self.select_option_filter.remove(filter_id);
+            }
+            FieldType::Checkbox => {
+                let _ = self.checkbox_filter.remove(filter_id);
+            }
+            FieldType::URL => {
+                let _ = self.url_filter.remove(filter_id);
+            }
+        };
+    }
+}
+
+async fn reload_filter_cache(
+    cache: &mut FilterCache,
+    field_ids: Option<Vec<String>>,
+    grid_pad: &Arc<RwLock<GridRevisionPad>>,
+) {
+    let grid_pad = grid_pad.read().await;
+    let filters_revs = grid_pad.get_filters(None, field_ids).unwrap_or_default();
+
+    for filter_rev in filters_revs {
+        match grid_pad.get_field_rev(&filter_rev.field_id) {
+            None => {}
+            Some((_, field_rev)) => {
+                let filter_id = FilterId::from(field_rev);
+                let field_type: FieldType = field_rev.field_type_rev.into();
+                match &field_type {
+                    FieldType::RichText => {
+                        let _ = cache.text_filter.insert(filter_id, GridTextFilter::from(filter_rev));
+                    }
+                    FieldType::Number => {
+                        let _ = cache
+                            .number_filter
+                            .insert(filter_id, GridNumberFilter::from(filter_rev));
+                    }
+                    FieldType::DateTime => {
+                        let _ = cache.date_filter.insert(filter_id, GridDateFilter::from(filter_rev));
+                    }
+                    FieldType::SingleSelect | FieldType::MultiSelect => {
+                        let _ = cache
+                            .select_option_filter
+                            .insert(filter_id, GridSelectOptionFilter::from(filter_rev));
+                    }
+                    FieldType::Checkbox => {
+                        let _ = cache
+                            .checkbox_filter
+                            .insert(filter_id, GridCheckboxFilter::from(filter_rev));
+                    }
+                    FieldType::URL => {
+                        let _ = cache.url_filter.insert(filter_id, GridTextFilter::from(filter_rev));
+                    }
+                }
+            }
+        }
+    }
+}
+#[derive(Hash, Eq, PartialEq)]
+struct FilterId {
+    field_id: String,
+    field_type: FieldType,
+}
+
+impl std::convert::From<&Arc<FieldRevision>> for FilterId {
+    fn from(rev: &Arc<FieldRevision>) -> Self {
+        Self {
+            field_id: rev.id.clone(),
+            field_type: rev.field_type_rev.into(),
+        }
     }
 }

+ 44 - 42
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -3,16 +3,17 @@ use crate::entities::CellIdentifier;
 use crate::manager::{GridTaskSchedulerRwLock, GridUser};
 use crate::services::block_manager::GridBlockManager;
 use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
-use crate::services::filter::GridFilterService;
+use crate::services::filter::{GridFilterChangeset, GridFilterService};
 use crate::services::persistence::block_index::BlockIndexCache;
 use crate::services::row::*;
 
+use crate::entities::*;
 use bytes::Bytes;
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::*;
 use flowy_grid_data_model::revision::*;
 use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
 use flowy_sync::client_grid::{GridChangeset, GridRevisionPad, JsonDeserializer};
+use flowy_sync::entities::grid::{FieldChangesetParams, GridSettingChangesetParams};
 use flowy_sync::entities::revision::Revision;
 use flowy_sync::errors::CollaborateResult;
 use flowy_sync::util::make_delta_from_revisions;
@@ -53,11 +54,8 @@ impl GridRevisionEditor {
         let grid_pad = Arc::new(RwLock::new(grid_pad));
         let block_meta_revs = grid_pad.read().await.get_block_meta_revs();
         let block_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_meta_revs, persistence).await?);
-        let filter_service = Arc::new(GridFilterService::new(
-            grid_pad.clone(),
-            block_manager.clone(),
-            task_scheduler.clone(),
-        ));
+        let filter_service =
+            Arc::new(GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await);
         let editor = Arc::new(Self {
             grid_id: grid_id.to_owned(),
             user,
@@ -87,7 +85,7 @@ impl GridRevisionEditor {
                         grid_id,
                         name: Some(field.name),
                         desc: Some(field.desc),
-                        field_type: Some(field.field_type),
+                        field_type: Some(field.field_type.into()),
                         frozen: Some(field.frozen),
                         visibility: Some(field.visibility),
                         width: Some(field.width),
@@ -126,7 +124,8 @@ impl GridRevisionEditor {
         let field_rev = result.unwrap();
         let _ = self
             .modify(|grid| {
-                let deserializer = TypeOptionJsonDeserializer(field_rev.field_type.clone());
+                let field_type = field_rev.field_type_rev.into();
+                let deserializer = TypeOptionJsonDeserializer(field_type);
                 let changeset = FieldChangesetParams {
                     field_id: field_id.to_owned(),
                     grid_id: grid_id.to_owned(),
@@ -164,7 +163,7 @@ impl GridRevisionEditor {
         let field_id = params.field_id.clone();
         let json_deserializer = match self.grid_pad.read().await.get_field_rev(params.field_id.as_str()) {
             None => return Err(ErrorCode::FieldDoesNotExist.into()),
-            Some((_, field_rev)) => TypeOptionJsonDeserializer(field_rev.field_type.clone()),
+            Some((_, field_rev)) => TypeOptionJsonDeserializer(field_rev.field_type_rev.into()),
         };
 
         let _ = self
@@ -175,7 +174,7 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn replace_field(&self, field_rev: FieldRevision) -> FlowyResult<()> {
+    pub async fn replace_field(&self, field_rev: Arc<FieldRevision>) -> FlowyResult<()> {
         let field_id = field_rev.id.clone();
         let _ = self
             .modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev)?))
@@ -204,8 +203,9 @@ impl GridRevisionEditor {
         //     .get_cell_revs(block_ids, field_id, None)
         //     .await?;
 
-        let type_option_json_builder = |field_type: &FieldType| -> String {
-            return default_type_option_builder_from_type(field_type).entry().json_str();
+        let type_option_json_builder = |field_type: &FieldTypeRevision| -> String {
+            let field_type: FieldType = field_type.into();
+            return default_type_option_builder_from_type(&field_type).entry().json_str();
         };
 
         let _ = self
@@ -227,24 +227,20 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn get_field_rev(&self, field_id: &str) -> Option<FieldRevision> {
+    pub async fn get_field_rev(&self, field_id: &str) -> Option<Arc<FieldRevision>> {
         let field_rev = self.grid_pad.read().await.get_field_rev(field_id)?.1.clone();
         Some(field_rev)
     }
 
-    pub async fn get_field_revs<T>(&self, field_ids: Option<Vec<T>>) -> FlowyResult<Vec<FieldRevision>>
-    where
-        T: Into<FieldOrder>,
-    {
+    pub async fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> FlowyResult<Vec<Arc<FieldRevision>>> {
         if field_ids.is_none() {
             let field_revs = self.grid_pad.read().await.get_field_revs(None)?;
             return Ok(field_revs);
         }
 
-        let to_field_orders = |item: Vec<T>| item.into_iter().map(|data| data.into()).collect();
-        let field_orders = field_ids.map_or(vec![], to_field_orders);
-        let expected_len = field_orders.len();
-        let field_revs = self.grid_pad.read().await.get_field_revs(Some(field_orders))?;
+        let field_ids = field_ids.unwrap_or_default();
+        let expected_len = field_ids.len();
+        let field_revs = self.grid_pad.read().await.get_field_revs(Some(field_ids))?;
         if expected_len != 0 && field_revs.len() != expected_len {
             tracing::error!(
                 "This is a bug. The len of the field_revs should equal to {}",
@@ -269,14 +265,14 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn create_row(&self, start_row_id: Option<String>) -> FlowyResult<RowOrder> {
+    pub async fn create_row(&self, start_row_id: Option<String>) -> FlowyResult<BlockRowInfo> {
         let field_revs = self.grid_pad.read().await.get_field_revs(None)?;
         let block_id = self.block_id().await?;
 
         // insert empty row below the row whose id is upper_row_id
         let row_rev_ctx = CreateRowRevisionBuilder::new(&field_revs).build();
         let row_rev = make_row_rev_from_context(&block_id, row_rev_ctx);
-        let row_order = RowOrder::from(&row_rev);
+        let row_order = BlockRowInfo::from(&row_rev);
 
         // insert the row
         let row_count = self.block_manager.create_row(&block_id, row_rev, start_row_id).await?;
@@ -287,13 +283,13 @@ impl GridRevisionEditor {
         Ok(row_order)
     }
 
-    pub async fn insert_rows(&self, contexts: Vec<CreateRowRevisionPayload>) -> FlowyResult<Vec<RowOrder>> {
+    pub async fn insert_rows(&self, contexts: Vec<CreateRowRevisionPayload>) -> FlowyResult<Vec<BlockRowInfo>> {
         let block_id = self.block_id().await?;
         let mut rows_by_block_id: HashMap<String, Vec<RowRevision>> = HashMap::new();
         let mut row_orders = vec![];
         for ctx in contexts {
             let row_rev = make_row_rev_from_context(&block_id, ctx);
-            row_orders.push(RowOrder::from(&row_rev));
+            row_orders.push(BlockRowInfo::from(&row_rev));
             rows_by_block_id
                 .entry(block_id.clone())
                 .or_insert_with(Vec::new)
@@ -307,7 +303,7 @@ impl GridRevisionEditor {
     }
 
     pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
-        let field_revs = self.get_field_revs::<FieldOrder>(None).await?;
+        let field_revs = self.get_field_revs(None).await?;
         self.block_manager
             .update_row(changeset, |row_rev| make_row_from_row_rev(&field_revs, row_rev))
             .await
@@ -322,7 +318,7 @@ impl GridRevisionEditor {
         debug_assert_eq!(grid_block_snapshot.len(), 1);
         if grid_block_snapshot.len() == 1 {
             let snapshot = grid_block_snapshot.pop().unwrap();
-            let field_revs = self.get_field_revs::<FieldOrder>(None).await?;
+            let field_revs = self.get_field_revs(None).await?;
             let rows = make_rows_from_row_revs(&field_revs, &snapshot.row_revs);
             Ok(rows.into())
         } else {
@@ -334,7 +330,7 @@ impl GridRevisionEditor {
         match self.block_manager.get_row_rev(row_id).await? {
             None => Ok(None),
             Some(row_rev) => {
-                let field_revs = self.get_field_revs::<FieldOrder>(None).await?;
+                let field_revs = self.get_field_revs(None).await?;
                 let row_revs = vec![row_rev];
                 let mut rows = make_rows_from_row_revs(&field_revs, &row_revs);
                 debug_assert!(rows.len() == 1);
@@ -399,7 +395,7 @@ impl GridRevisionEditor {
                     cell_rev,
                     field_rev,
                 )?);
-                let field_revs = self.get_field_revs::<FieldOrder>(None).await?;
+                let field_revs = self.get_field_revs(None).await?;
                 let cell_changeset = CellChangeset {
                     grid_id,
                     row_id,
@@ -425,7 +421,7 @@ impl GridRevisionEditor {
         Ok(block_meta_revs)
     }
 
-    pub async fn delete_rows(&self, row_orders: Vec<RowOrder>) -> FlowyResult<()> {
+    pub async fn delete_rows(&self, row_orders: Vec<BlockRowInfo>) -> FlowyResult<()> {
         let changesets = self.block_manager.delete_rows(row_orders).await?;
         for changeset in changesets {
             let _ = self.update_block(changeset).await?;
@@ -435,13 +431,17 @@ impl GridRevisionEditor {
 
     pub async fn get_grid_data(&self) -> FlowyResult<Grid> {
         let pad_read_guard = self.grid_pad.read().await;
-        let field_orders = pad_read_guard.get_field_orders();
+        let field_orders = pad_read_guard
+            .get_field_revs(None)?
+            .iter()
+            .map(FieldOrder::from)
+            .collect();
         let mut block_orders = vec![];
         for block_rev in pad_read_guard.get_block_meta_revs() {
             let row_orders = self.block_manager.get_row_orders(&block_rev.block_id).await?;
             let block_order = GridBlock {
                 id: block_rev.block_id.clone(),
-                row_orders,
+                row_infos: row_orders,
             };
             block_orders.push(block_order);
         }
@@ -454,29 +454,31 @@ impl GridRevisionEditor {
     }
 
     pub async fn get_grid_setting(&self) -> FlowyResult<GridSetting> {
-        let read_guard = self.grid_pad.read().await;
-        let grid_setting_rev = read_guard.get_grid_setting_rev();
-        Ok(grid_setting_rev.into())
+        // let read_guard = self.grid_pad.read().await;
+        // let grid_setting_rev = read_guard.get_grid_setting_rev();
+        // Ok(grid_setting_rev.into())
+        todo!()
     }
 
     pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult<Vec<GridFilter>> {
         let read_guard = self.grid_pad.read().await;
         let layout_rev = layout_type.clone().into();
-        match read_guard.get_filters(Some(&layout_rev)) {
+        match read_guard.get_filters(Some(&layout_rev), None) {
             Some(filter_revs) => Ok(filter_revs.iter().map(GridFilter::from).collect::<Vec<GridFilter>>()),
             None => Ok(vec![]),
         }
     }
 
     pub async fn update_grid_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> {
-        let is_filter_changed = params.is_filter_changed();
+        let filter_changeset = GridFilterChangeset::from(&params);
         let _ = self
             .modify(|grid_pad| Ok(grid_pad.update_grid_setting_rev(params)?))
             .await?;
 
-        if is_filter_changed {
-            self.filter_service.notify_changed().await;
-        }
+        let filter_service = self.filter_service.clone();
+        tokio::spawn(async move {
+            filter_service.apply_changeset(filter_changeset).await;
+        });
         Ok(())
     }
 
@@ -492,7 +494,7 @@ impl GridRevisionEditor {
                 .collect::<Vec<String>>(),
             Some(block_ids) => block_ids,
         };
-        let snapshots = self.block_manager.make_block_snapshots(block_ids).await?;
+        let snapshots = self.block_manager.get_block_snapshots(Some(block_ids)).await?;
         Ok(snapshots)
     }
 

+ 25 - 5
frontend/rust-lib/flowy-grid/src/services/grid_editor_task.rs

@@ -1,9 +1,15 @@
+use crate::manager::GridTaskSchedulerRwLock;
 use crate::services::grid_editor::GridRevisionEditor;
-use crate::services::tasks::{GridTaskHandler, Task, TaskContent, TaskHandlerId};
+use crate::services::tasks::{GridTaskHandler, Task, TaskContent, TaskHandlerId, TaskId};
 use flowy_error::FlowyError;
-
+use futures::future::BoxFuture;
 use lib_infra::future::BoxResultFuture;
 
+pub(crate) trait GridServiceTaskScheduler: Send + Sync + 'static {
+    fn gen_task_id(&self) -> BoxFuture<TaskId>;
+    fn register_task(&self, task: Task) -> BoxFuture<()>;
+}
+
 impl GridTaskHandler for GridRevisionEditor {
     fn handler_id(&self) -> &TaskHandlerId {
         &self.grid_id
@@ -11,11 +17,25 @@ impl GridTaskHandler for GridRevisionEditor {
 
     fn process_task(&self, task: Task) -> BoxResultFuture<(), FlowyError> {
         Box::pin(async move {
-            match &task.content {
-                TaskContent::Snapshot { .. } => {}
-                TaskContent::Filter => self.filter_service.process_task(task).await?,
+            match task.content {
+                TaskContent::Snapshot => {}
+                TaskContent::Filter(context) => self.filter_service.process(context).await?,
             }
             Ok(())
         })
     }
 }
+
+impl GridServiceTaskScheduler for GridTaskSchedulerRwLock {
+    fn gen_task_id(&self) -> BoxFuture<TaskId> {
+        let this = self.clone();
+        Box::pin(async move { this.read().await.next_task_id() })
+    }
+
+    fn register_task(&self, task: Task) -> BoxFuture<()> {
+        let this = self.clone();
+        Box::pin(async move {
+            this.write().await.register_task(task);
+        })
+    }
+}

+ 23 - 21
frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs

@@ -1,13 +1,13 @@
+use crate::entities::FieldType;
 use crate::services::field::*;
 use bytes::Bytes;
 use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::{CellRevision, FieldRevision};
 use serde::{Deserialize, Serialize};
 use std::fmt::Formatter;
 use std::str::FromStr;
 
-pub trait CellDataOperation<ED> {
+pub trait CellDataOperation<D, F> {
     fn decode_cell_data<T>(
         &self,
         encoded_data: T,
@@ -15,9 +15,10 @@ pub trait CellDataOperation<ED> {
         field_rev: &FieldRevision,
     ) -> FlowyResult<DecodedCellData>
     where
-        T: Into<ED>;
+        T: Into<D>;
+
+    fn apply_filter(&self, filter: F) -> bool;
 
-    //
     fn apply_changeset<C: Into<CellContentChangeset>>(
         &self,
         changeset: C,
@@ -115,12 +116,14 @@ impl TypeOptionCellData {
 
 /// The changeset will be deserialized into specific data base on the FieldType.
 /// For example, it's String on FieldType::RichText, and SelectOptionChangeset on FieldType::SingleSelect
-pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
-    changeset: T,
+pub fn apply_cell_data_changeset<C: Into<CellContentChangeset>, T: AsRef<FieldRevision>>(
+    changeset: C,
     cell_rev: Option<CellRevision>,
-    field_rev: &FieldRevision,
+    field_rev: T,
 ) -> Result<String, FlowyError> {
-    let s = match field_rev.field_type {
+    let field_rev = field_rev.as_ref();
+    let field_type = field_rev.field_type_rev.into();
+    let s = match field_type {
         FieldType::RichText => RichTextTypeOption::from(field_rev).apply_changeset(changeset, cell_rev),
         FieldType::Number => NumberTypeOption::from(field_rev).apply_changeset(changeset, cell_rev),
         FieldType::DateTime => DateTypeOption::from(field_rev).apply_changeset(changeset, cell_rev),
@@ -130,14 +133,14 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
         FieldType::URL => URLTypeOption::from(field_rev).apply_changeset(changeset, cell_rev),
     }?;
 
-    Ok(TypeOptionCellData::new(s, field_rev.field_type.clone()).json())
+    Ok(TypeOptionCellData::new(s, field_type).json())
 }
 
 pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(data: T, field_rev: &FieldRevision) -> DecodedCellData {
     if let Ok(type_option_cell_data) = data.try_into() {
         let TypeOptionCellData { data, field_type } = type_option_cell_data;
-        let to_field_type = &field_rev.field_type;
-        match try_decode_cell_data(data, field_rev, &field_type, to_field_type) {
+        let to_field_type = field_rev.field_type_rev.into();
+        match try_decode_cell_data(data, field_rev, &field_type, &to_field_type) {
             Ok(cell_data) => cell_data,
             Err(e) => {
                 tracing::error!("Decode cell data failed, {:?}", e);
@@ -150,35 +153,34 @@ pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(data: T, field_rev: &Fie
     }
 }
 
-pub fn try_decode_cell_data<T: Into<String>>(
-    encoded_data: T,
+pub fn try_decode_cell_data(
+    encoded_data: String,
     field_rev: &FieldRevision,
     s_field_type: &FieldType,
     t_field_type: &FieldType,
 ) -> FlowyResult<DecodedCellData> {
-    let encoded_data = encoded_data.into();
     let get_cell_data = || {
         let data = match t_field_type {
             FieldType::RichText => field_rev
-                .get_type_option_entry::<RichTextTypeOption>(t_field_type)?
+                .get_type_option_entry::<RichTextTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::Number => field_rev
-                .get_type_option_entry::<NumberTypeOption>(t_field_type)?
+                .get_type_option_entry::<NumberTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::DateTime => field_rev
-                .get_type_option_entry::<DateTypeOption>(t_field_type)?
+                .get_type_option_entry::<DateTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::SingleSelect => field_rev
-                .get_type_option_entry::<SingleSelectTypeOption>(t_field_type)?
+                .get_type_option_entry::<SingleSelectTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::MultiSelect => field_rev
-                .get_type_option_entry::<MultiSelectTypeOption>(t_field_type)?
+                .get_type_option_entry::<MultiSelectTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::Checkbox => field_rev
-                .get_type_option_entry::<CheckboxTypeOption>(t_field_type)?
+                .get_type_option_entry::<CheckboxTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
             FieldType::URL => field_rev
-                .get_type_option_entry::<URLTypeOption>(t_field_type)?
+                .get_type_option_entry::<URLTypeOption, _>(t_field_type)?
                 .decode_cell_data(encoded_data, s_field_type, field_rev),
         };
         Some(data)

+ 0 - 1
frontend/rust-lib/flowy-grid/src/services/row/mod.rs

@@ -1,6 +1,5 @@
 mod cell_data_operation;
 mod row_builder;
-pub mod row_entities;
 mod row_loader;
 
 pub use cell_data_operation::*;

+ 4 - 3
frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs

@@ -4,18 +4,19 @@ use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::revision::{gen_row_id, CellRevision, FieldRevision, RowRevision, DEFAULT_ROW_HEIGHT};
 use indexmap::IndexMap;
 use std::collections::HashMap;
+use std::sync::Arc;
 
 pub struct CreateRowRevisionBuilder<'a> {
-    field_rev_map: HashMap<&'a String, &'a FieldRevision>,
+    field_rev_map: HashMap<&'a String, &'a Arc<FieldRevision>>,
     payload: CreateRowRevisionPayload,
 }
 
 impl<'a> CreateRowRevisionBuilder<'a> {
-    pub fn new(fields: &'a [FieldRevision]) -> Self {
+    pub fn new(fields: &'a [Arc<FieldRevision>]) -> Self {
         let field_rev_map = fields
             .iter()
             .map(|field| (&field.id, field))
-            .collect::<HashMap<&String, &FieldRevision>>();
+            .collect::<HashMap<&String, &Arc<FieldRevision>>>();
 
         let payload = CreateRowRevisionPayload {
             row_id: gen_row_id(),

+ 0 - 31
frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs

@@ -1,31 +0,0 @@
-use flowy_derive::ProtoBuf;
-use flowy_error::ErrorCode;
-use flowy_grid_data_model::parser::NotEmptyStr;
-
-#[derive(ProtoBuf, Default)]
-pub struct RowIdentifierPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 3)]
-    pub row_id: String,
-}
-
-pub struct RowIdentifier {
-    pub grid_id: String,
-    pub row_id: String,
-}
-
-impl TryInto<RowIdentifier> for RowIdentifierPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<RowIdentifier, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
-
-        Ok(RowIdentifier {
-            grid_id: grid_id.0,
-            row_id: row_id.0,
-        })
-    }
-}

+ 12 - 11
frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs

@@ -1,5 +1,5 @@
+use crate::entities::{BlockRowInfo, GridBlock, RepeatedGridBlock, Row};
 use flowy_error::FlowyResult;
-use flowy_grid_data_model::entities::{GridBlock, RepeatedGridBlock, Row, RowOrder};
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
 use std::collections::HashMap;
 use std::sync::Arc;
@@ -9,15 +9,16 @@ pub struct GridBlockSnapshot {
     pub row_revs: Vec<Arc<RowRevision>>,
 }
 
-pub(crate) fn block_from_row_orders(row_orders: Vec<RowOrder>) -> Vec<GridBlock> {
+pub(crate) fn block_from_row_orders(row_orders: Vec<BlockRowInfo>) -> Vec<GridBlock> {
     let mut map: HashMap<String, GridBlock> = HashMap::new();
-    row_orders.into_iter().for_each(|row_order| {
+    row_orders.into_iter().for_each(|row_info| {
         // Memory Optimization: escape clone block_id
-        let block_id = row_order.block_id.clone();
+        let block_id = row_info.block_id().to_owned();
+        let cloned_block_id = block_id.clone();
         map.entry(block_id)
-            .or_insert_with(|| GridBlock::new(&row_order.block_id, vec![]))
-            .row_orders
-            .push(row_order);
+            .or_insert_with(|| GridBlock::new(&cloned_block_id, vec![]))
+            .row_infos
+            .push(row_info);
     });
     map.into_values().collect::<Vec<_>>()
 }
@@ -34,15 +35,15 @@ pub(crate) fn block_from_row_orders(row_orders: Vec<RowOrder>) -> Vec<GridBlock>
 //     Some((field_id, cell))
 // }
 
-pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<RowOrder> {
-    row_revs.iter().map(RowOrder::from).collect::<Vec<_>>()
+pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<BlockRowInfo> {
+    row_revs.iter().map(BlockRowInfo::from).collect::<Vec<_>>()
 }
 
-pub(crate) fn make_row_from_row_rev(fields: &[FieldRevision], row_rev: Arc<RowRevision>) -> Option<Row> {
+pub(crate) fn make_row_from_row_rev(fields: &[Arc<FieldRevision>], row_rev: Arc<RowRevision>) -> Option<Row> {
     make_rows_from_row_revs(fields, &[row_rev]).pop()
 }
 
-pub(crate) fn make_rows_from_row_revs(_fields: &[FieldRevision], row_revs: &[Arc<RowRevision>]) -> Vec<Row> {
+pub(crate) fn make_rows_from_row_revs(_fields: &[Arc<FieldRevision>], row_revs: &[Arc<RowRevision>]) -> Vec<Row> {
     // let field_rev_map = fields
     //     .iter()
     //     .map(|field_rev| (&field_rev.id, field_rev))

+ 5 - 4
frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs

@@ -1,4 +1,5 @@
-use flowy_grid_data_model::entities::{CreateGridFilterParams, GridLayoutType, GridSettingChangesetParams};
+use crate::entities::GridLayoutType;
+use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, GridSettingChangesetParams};
 
 pub struct GridSettingChangesetBuilder {
     params: GridSettingChangesetParams,
@@ -8,7 +9,7 @@ impl GridSettingChangesetBuilder {
     pub fn new(grid_id: &str, layout_type: &GridLayoutType) -> Self {
         let params = GridSettingChangesetParams {
             grid_id: grid_id.to_string(),
-            layout_type: layout_type.clone(),
+            layout_type: layout_type.clone().into(),
             insert_filter: None,
             delete_filter: None,
             insert_group: None,
@@ -24,8 +25,8 @@ impl GridSettingChangesetBuilder {
         self
     }
 
-    pub fn delete_filter(mut self, filter_id: &str) -> Self {
-        self.params.delete_filter = Some(filter_id.to_string());
+    pub fn delete_filter(mut self, params: DeleteFilterParams) -> Self {
+        self.params.delete_filter = Some(params);
         self
     }
 

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/tasks/queue.rs

@@ -21,8 +21,8 @@ impl GridTaskQueue {
 
     pub(crate) fn push(&mut self, task: &Task) {
         let task_type = match task.content {
-            TaskContent::Snapshot { .. } => TaskType::Snapshot,
-            TaskContent::Filter => TaskType::Filter,
+            TaskContent::Snapshot => TaskType::Snapshot,
+            TaskContent::Filter { .. } => TaskType::Filter,
         };
         let pending_task = PendingTask {
             ty: task_type,

+ 13 - 8
frontend/rust-lib/flowy-grid/src/services/tasks/scheduler.rs

@@ -3,6 +3,7 @@ use crate::services::tasks::runner::GridTaskRunner;
 use crate::services::tasks::store::GridTaskStore;
 use crate::services::tasks::task::Task;
 
+use crate::services::tasks::TaskId;
 use flowy_error::{FlowyError, FlowyResult};
 use lib_infra::future::BoxResultFuture;
 use std::collections::HashMap;
@@ -10,7 +11,7 @@ use std::sync::Arc;
 use std::time::Duration;
 use tokio::sync::{watch, RwLock};
 
-pub trait GridTaskHandler: Send + Sync + 'static {
+pub(crate) trait GridTaskHandler: Send + Sync + 'static {
     fn handler_id(&self) -> &TaskHandlerId;
 
     fn process_task(&self, task: Task) -> BoxResultFuture<(), FlowyError>;
@@ -24,7 +25,7 @@ pub struct GridTaskScheduler {
 }
 
 impl GridTaskScheduler {
-    pub fn new() -> Arc<RwLock<Self>> {
+    pub(crate) fn new() -> Arc<RwLock<Self>> {
         let (notifier, rx) = watch::channel(());
 
         let scheduler = Self {
@@ -44,7 +45,7 @@ impl GridTaskScheduler {
         scheduler
     }
 
-    pub fn register_handler<T>(&mut self, handler: Arc<T>)
+    pub(crate) fn register_handler<T>(&mut self, handler: Arc<T>)
     where
         T: GridTaskHandler,
     {
@@ -52,11 +53,11 @@ impl GridTaskScheduler {
         self.handlers.insert(handler_id, handler);
     }
 
-    pub fn unregister_handler<T: AsRef<str>>(&mut self, handler_id: T) {
+    pub(crate) fn unregister_handler<T: AsRef<str>>(&mut self, handler_id: T) {
         let _ = self.handlers.remove(handler_id.as_ref());
     }
 
-    pub async fn process_next_task(&mut self) -> FlowyResult<()> {
+    pub(crate) async fn process_next_task(&mut self) -> FlowyResult<()> {
         let mut get_next_task = || {
             let pending_task = self.queue.mut_head(|list| list.pop())?;
             let task = self.store.remove_task(&pending_task.id)?;
@@ -64,7 +65,7 @@ impl GridTaskScheduler {
         };
 
         if let Some(task) = get_next_task() {
-            match self.handlers.get(&task.hid) {
+            match self.handlers.get(&task.handler_id) {
                 None => {}
                 Some(handler) => {
                     let _ = handler.process_task(task).await;
@@ -74,14 +75,18 @@ impl GridTaskScheduler {
         Ok(())
     }
 
-    pub fn register_task(&mut self, task: Task) {
+    pub(crate) fn register_task(&mut self, task: Task) {
         assert!(!task.is_finished());
         self.queue.push(&task);
         self.store.insert_task(task);
         self.notify();
     }
 
-    pub fn notify(&self) {
+    pub(crate) fn next_task_id(&self) -> TaskId {
+        self.store.next_task_id()
+    }
+
+    pub(crate) fn notify(&self) {
         let _ = self.notifier.send(());
     }
 }

+ 5 - 5
frontend/rust-lib/flowy-grid/src/services/tasks/store.rs

@@ -4,7 +4,7 @@ use std::collections::HashMap;
 use std::sync::atomic::AtomicU32;
 use std::sync::atomic::Ordering::SeqCst;
 
-pub struct GridTaskStore {
+pub(crate) struct GridTaskStore {
     tasks: HashMap<TaskId, Task>,
     task_id_counter: AtomicU32,
 }
@@ -17,15 +17,15 @@ impl GridTaskStore {
         }
     }
 
-    pub fn insert_task(&mut self, task: Task) {
+    pub(crate) fn insert_task(&mut self, task: Task) {
         self.tasks.insert(task.id, task);
     }
 
-    pub fn remove_task(&mut self, task_id: &TaskId) -> Option<Task> {
+    pub(crate) fn remove_task(&mut self, task_id: &TaskId) -> Option<Task> {
         self.tasks.remove(task_id)
     }
-    #[allow(dead_code)]
-    pub fn next_task_id(&self) -> TaskId {
+
+    pub(crate) fn next_task_id(&self) -> TaskId {
         let _ = self.task_id_counter.fetch_add(1, SeqCst);
         self.task_id_counter.load(SeqCst)
     }

+ 11 - 7
frontend/rust-lib/flowy-grid/src/services/tasks/task.rs

@@ -1,3 +1,4 @@
+use crate::services::row::GridBlockSnapshot;
 use crate::services::tasks::queue::TaskHandlerId;
 use std::cmp::Ordering;
 
@@ -44,20 +45,23 @@ impl Ord for PendingTask {
             (TaskType::Snapshot, TaskType::Snapshot) => Ordering::Equal,
             (TaskType::Snapshot, _) => Ordering::Greater,
             (_, TaskType::Snapshot) => Ordering::Less,
-            (TaskType::Filter, TaskType::Filter) => self.id.cmp(&other.id),
+            (TaskType::Filter, TaskType::Filter) => self.id.cmp(&other.id).reverse(),
         }
     }
 }
 
-pub type ContentId = String;
+pub(crate) struct FilterTaskContext {
+    pub blocks: Vec<GridBlockSnapshot>,
+}
 
-pub enum TaskContent {
-    Snapshot { content_id: ContentId },
-    Filter,
+pub(crate) enum TaskContent {
+    #[allow(dead_code)]
+    Snapshot,
+    Filter(FilterTaskContext),
 }
 
-pub struct Task {
-    pub hid: TaskHandlerId,
+pub(crate) struct Task {
+    pub handler_id: TaskHandlerId,
     pub id: TaskId,
     pub content: TaskContent,
 }

+ 1 - 1
frontend/rust-lib/flowy-grid/src/util.rs

@@ -1,5 +1,5 @@
+use crate::entities::FieldType;
 use crate::services::field::*;
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::BuildGridContext;
 use flowy_sync::client_grid::GridBuilder;
 

+ 3 - 2
frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs

@@ -1,8 +1,8 @@
 use crate::grid::field_util::make_date_cell_string;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
+use flowy_grid::entities::{CellChangeset, FieldType};
 use flowy_grid::services::field::{MultiSelectTypeOption, SelectOptionCellContentChangeset, SingleSelectTypeOption};
-use flowy_grid_data_model::entities::{CellChangeset, FieldType};
 
 #[tokio::test]
 async fn grid_cell_update() {
@@ -17,7 +17,8 @@ async fn grid_cell_update() {
     let mut scripts = vec![];
     for (_, row_rev) in row_revs.iter().enumerate() {
         for field_rev in field_revs {
-            let data = match field_rev.field_type {
+            let field_type: FieldType = field_rev.field_type_rev.into();
+            let data = match field_type {
                 FieldType::RichText => "".to_string(),
                 FieldType::Number => "123".to_string(),
                 FieldType::DateTime => make_date_cell_string("123"),

+ 1 - 1
frontend/rust-lib/flowy-grid/tests/grid/field_test.rs

@@ -2,8 +2,8 @@ use crate::grid::field_util::*;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use flowy_grid::services::field::{SelectOption, SingleSelectTypeOption};
-use flowy_grid_data_model::entities::FieldChangesetParams;
 use flowy_grid_data_model::revision::TypeOptionDataEntry;
+use flowy_sync::entities::grid::FieldChangesetParams;
 
 #[tokio::test]
 async fn grid_create_field() {

+ 6 - 5
frontend/rust-lib/flowy-grid/tests/grid/field_util.rs

@@ -1,6 +1,6 @@
 use flowy_grid::services::field::*;
 
-use flowy_grid_data_model::entities::*;
+use flowy_grid::entities::*;
 use flowy_grid_data_model::revision::*;
 
 pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
@@ -12,7 +12,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
     let cloned_field_rev = field_rev.clone();
 
     let type_option_data = field_rev
-        .get_type_option_entry::<RichTextTypeOption>(&field_rev.field_type)
+        .get_type_option_entry::<RichTextTypeOption, _>(field_rev.field_type_rev)
         .unwrap()
         .protobuf_bytes()
         .to_vec();
@@ -21,7 +21,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
         id: field_rev.id,
         name: field_rev.name,
         desc: field_rev.desc,
-        field_type: field_rev.field_type,
+        field_type: field_rev.field_type_rev.into(),
         frozen: field_rev.frozen,
         visibility: field_rev.visibility,
         width: field_rev.width,
@@ -44,8 +44,9 @@ pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRev
 
     let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
     let cloned_field_rev = field_rev.clone();
+    let field_type: FieldType = field_rev.field_type_rev.into();
     let type_option_data = field_rev
-        .get_type_option_entry::<SingleSelectTypeOption>(&field_rev.field_type)
+        .get_type_option_entry::<SingleSelectTypeOption, _>(&field_type)
         .unwrap()
         .protobuf_bytes()
         .to_vec();
@@ -54,7 +55,7 @@ pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRev
         id: field_rev.id,
         name: field_rev.name,
         desc: field_rev.desc,
-        field_type: field_rev.field_type,
+        field_type,
         frozen: field_rev.frozen,
         visibility: field_rev.visibility,
         width: field_rev.width,

+ 7 - 4
frontend/rust-lib/flowy-grid/tests/grid/filter_test.rs

@@ -1,6 +1,6 @@
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
-use flowy_grid_data_model::entities::{CreateGridFilterPayload, TextFilterCondition};
+use flowy_grid::entities::CreateGridFilterPayload;
 
 #[tokio::test]
 async fn grid_filter_create_test() {
@@ -26,14 +26,17 @@ async fn grid_filter_invalid_condition_panic_test() {
 #[tokio::test]
 async fn grid_filter_delete_test() {
     let mut test = GridEditorTest::new().await;
-    let field_rev = test.text_field();
-    let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
+    let field_rev = test.text_field().clone();
+    let payload = CreateGridFilterPayload::new(&field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
     let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
     test.run_scripts(scripts).await;
 
     let filter = test.grid_filters().await.pop().unwrap();
     test.run_scripts(vec![
-        DeleteGridTableFilter { filter_id: filter.id },
+        DeleteGridTableFilter {
+            filter_id: filter.id,
+            field_type: field_rev.field_type.clone(),
+        },
         AssertTableFilterCount { count: 0 },
     ])
     .await;

+ 1 - 1
frontend/rust-lib/flowy-grid/tests/grid/mod.rs

@@ -2,7 +2,7 @@ mod block_test;
 mod cell_test;
 mod field_test;
 mod field_util;
-mod filter_test;
+// mod filter_test;
 mod row_test;
 mod row_util;
 mod script;

+ 5 - 3
frontend/rust-lib/flowy-grid/tests/grid/row_test.rs

@@ -3,11 +3,11 @@ use crate::grid::row_util::GridRowTestBuilder;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use chrono::NaiveDateTime;
+use flowy_grid::entities::FieldType;
 use flowy_grid::services::field::{
     DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
 };
 use flowy_grid::services::row::{decode_cell_data, CreateRowRevisionBuilder};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::RowMetaChangeset;
 
 #[tokio::test]
@@ -75,7 +75,8 @@ async fn grid_row_add_cells_test() {
     let mut test = GridEditorTest::new().await;
     let mut builder = CreateRowRevisionBuilder::new(&test.field_revs);
     for field in &test.field_revs {
-        match field.field_type {
+        let field_type: FieldType = field.field_type_rev.into();
+        match field_type {
             FieldType::RichText => {
                 builder.add_cell(&field.id, "hello world".to_owned()).unwrap();
             }
@@ -122,7 +123,8 @@ async fn grid_row_add_date_cell_test() {
     let mut date_field = None;
     let timestamp = 1647390674;
     for field in &test.field_revs {
-        if field.field_type == FieldType::DateTime {
+        let field_type: FieldType = field.field_type_rev.into();
+        if field_type == FieldType::DateTime {
             date_field = Some(field.clone());
             NaiveDateTime::from_timestamp(123, 0);
             // The data should not be empty

+ 6 - 2
frontend/rust-lib/flowy-grid/tests/grid/row_util.rs

@@ -1,7 +1,7 @@
 use crate::grid::script::GridEditorTest;
+use flowy_grid::entities::FieldType;
 use flowy_grid::services::field::DateCellContentChangeset;
 use flowy_grid::services::row::{CreateRowRevisionBuilder, CreateRowRevisionPayload};
-use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::revision::FieldRevision;
 use strum::EnumCount;
 
@@ -61,8 +61,12 @@ impl<'a> GridRowTestBuilder<'a> {
         self.test
             .field_revs
             .iter()
-            .find(|field_rev| &field_rev.field_type == field_type)
+            .find(|field_rev| {
+                let t_field_type: FieldType = field_rev.field_type_rev.into();
+                &t_field_type == field_type
+            })
             .unwrap()
+            .as_ref()
             .clone()
     }
 

+ 24 - 16
frontend/rust-lib/flowy-grid/tests/grid/script.rs

@@ -1,10 +1,13 @@
 #![cfg_attr(rustfmt, rustfmt::skip)]
+#![allow(clippy::all)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
 use bytes::Bytes;
 use flowy_grid::services::field::*;
 use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor};
 use flowy_grid::services::row::CreateRowRevisionPayload;
 use flowy_grid::services::setting::GridSettingChangesetBuilder;
-use flowy_grid_data_model::entities::*;
+use flowy_grid::entities::*;
 use flowy_grid_data_model::revision::*;
 use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
 use flowy_sync::client_grid::GridBuilder;
@@ -15,6 +18,7 @@ use std::sync::Arc;
 use std::time::Duration;
 use strum::EnumCount;
 use tokio::time::sleep;
+use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, FieldChangesetParams, GridSettingChangesetParams};
 
 pub enum EditorScript {
     CreateField {
@@ -77,6 +81,7 @@ pub enum EditorScript {
     },
     DeleteGridTableFilter {
         filter_id: String,
+        field_type: FieldType,
     },
     #[allow(dead_code)]
     AssertGridSetting {
@@ -89,12 +94,12 @@ pub struct GridEditorTest {
     pub sdk: FlowySDKTest,
     pub grid_id: String,
     pub editor: Arc<GridRevisionEditor>,
-    pub field_revs: Vec<FieldRevision>,
+    pub field_revs: Vec<Arc<FieldRevision>>,
     pub block_meta_revs: Vec<Arc<GridBlockMetaRevision>>,
     pub row_revs: Vec<Arc<RowRevision>>,
     pub field_count: usize,
 
-    pub row_order_by_row_id: HashMap<String, RowOrder>,
+    pub row_order_by_row_id: HashMap<String, BlockRowInfo>,
 }
 
 impl GridEditorTest {
@@ -105,7 +110,7 @@ impl GridEditorTest {
         let view_data: Bytes = build_context.into();
         let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await;
         let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
-        let field_revs = editor.get_field_revs::<FieldOrder>(None).await.unwrap();
+        let field_revs = editor.get_field_revs(None).await.unwrap();
         let block_meta_revs = editor.get_block_meta_revs().await.unwrap();
         let row_revs = editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs;
         assert_eq!(row_revs.len(), 3);
@@ -147,12 +152,12 @@ impl GridEditorTest {
                 }
 
                 self.editor.insert_field(params).await.unwrap();
-                self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
+                self.field_revs = self.editor.get_field_revs(None).await.unwrap();
                 assert_eq!(self.field_count, self.field_revs.len());
             }
             EditorScript::UpdateField { changeset: change } => {
                 self.editor.update_field(change).await.unwrap();
-                self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
+                self.field_revs = self.editor.get_field_revs(None).await.unwrap();
             }
             EditorScript::DeleteField { field_rev } => {
                 if self.editor.contain_field(&field_rev.id).await {
@@ -160,18 +165,18 @@ impl GridEditorTest {
                 }
 
                 self.editor.delete_field(&field_rev.id).await.unwrap();
-                self.field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
+                self.field_revs = self.editor.get_field_revs(None).await.unwrap();
                 assert_eq!(self.field_count, self.field_revs.len());
             }
             EditorScript::AssertFieldCount(count) => {
                 assert_eq!(
-                    self.editor.get_field_revs::<FieldOrder>(None).await.unwrap().len(),
+                    self.editor.get_field_revs(None).await.unwrap().len(),
                     count
                 );
             }
             EditorScript::AssertFieldEqual { field_index, field_rev } => {
-                let field_revs = self.editor.get_field_revs::<FieldOrder>(None).await.unwrap();
-                assert_eq!(field_revs[field_index].clone(), field_rev);
+                let field_revs = self.editor.get_field_revs(None).await.unwrap();
+                assert_eq!(field_revs[field_index].as_ref(), &field_rev);
             }
             EditorScript::CreateBlock { block } => {
                 self.editor.create_block(block).await.unwrap();
@@ -198,14 +203,14 @@ impl GridEditorTest {
             }
             EditorScript::CreateEmptyRow => {
                 let row_order = self.editor.create_row(None).await.unwrap();
-                self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
+                self.row_order_by_row_id.insert(row_order.row_id().to_owned(), row_order);
                 self.row_revs = self.get_row_revs().await;
                 self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();
             }
             EditorScript::CreateRow { payload: context } => {
                 let row_orders = self.editor.insert_rows(vec![context]).await.unwrap();
                 for row_order in row_orders {
-                    self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
+                    self.row_order_by_row_id.insert(row_order.row_id().to_owned(), row_order);
                 }
                 self.row_revs = self.get_row_revs().await;
                 self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();
@@ -215,7 +220,7 @@ impl GridEditorTest {
                 let row_orders = row_ids
                     .into_iter()
                     .map(|row_id| self.row_order_by_row_id.get(&row_id).unwrap().clone())
-                    .collect::<Vec<RowOrder>>();
+                    .collect::<Vec<BlockRowInfo>>();
 
                 self.editor.delete_rows(row_orders).await.unwrap();
                 self.row_revs = self.get_row_revs().await;
@@ -265,10 +270,10 @@ impl GridEditorTest {
                 let filters = self.editor.get_grid_filter(&layout_type).await.unwrap();
                 assert_eq!(count as usize, filters.len());
             }
-            EditorScript::DeleteGridTableFilter { filter_id } => {
+            EditorScript::DeleteGridTableFilter { filter_id ,field_type} => {
                 let layout_type = GridLayoutType::Table;
                 let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type)
-                    .delete_filter(&filter_id)
+                    .delete_filter(DeleteFilterParams { filter_id, field_type_rev: field_type.into() })
                     .build();
                 let _ = self.editor.update_grid_setting(params).await.unwrap();
             }
@@ -303,7 +308,10 @@ impl GridEditorTest {
     pub fn text_field(&self) -> &FieldRevision {
         self.field_revs
             .iter()
-            .filter(|field_rev| field_rev.field_type == FieldType::RichText)
+            .filter(|field_rev| {
+                let t_field_type: FieldType = field_rev.field_type_rev.into();
+                t_field_type == FieldType::RichText
+            })
             .collect::<Vec<_>>()
             .pop()
             .unwrap()

+ 1 - 1
frontend/rust-lib/flowy-net/src/http_server/document.rs

@@ -3,7 +3,7 @@ use crate::{
     request::{HttpRequestBuilder, ResponseMiddleware},
 };
 use flowy_error::FlowyError;
-use flowy_sync::entities::text_block_info::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo};
+use flowy_sync::entities::text_block::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo};
 use flowy_text_block::BlockCloudService;
 use http_flowy::response::FlowyResponse;
 use lazy_static::lazy_static;

+ 1 - 1
frontend/rust-lib/flowy-net/src/local_server/persistence.rs

@@ -1,5 +1,5 @@
 use flowy_sync::{
-    entities::{folder_info::FolderInfo, text_block_info::TextBlockInfo},
+    entities::{folder::FolderInfo, text_block::TextBlockInfo},
     errors::CollaborateError,
     protobuf::{RepeatedRevision as RepeatedRevisionPB, Revision as RevisionPB},
     server_document::*,

+ 1 - 1
frontend/rust-lib/flowy-net/src/local_server/server.rs

@@ -6,7 +6,7 @@ use flowy_folder::event_map::FolderCouldServiceV1;
 use flowy_sync::{
     client_document::default::initial_quill_delta_string,
     entities::{
-        text_block_info::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo},
+        text_block::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo},
         ws_data::{ClientRevisionWSData, ClientRevisionWSDataType},
     },
     errors::CollaborateError,

+ 1 - 1
frontend/rust-lib/flowy-text-block/src/editor.rs

@@ -9,7 +9,7 @@ use flowy_error::{internal_error, FlowyResult};
 use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder, RevisionWebSocket};
 use flowy_sync::entities::ws_data::ServerRevisionWSData;
 use flowy_sync::{
-    entities::{revision::Revision, text_block_info::TextBlockInfo},
+    entities::{revision::Revision, text_block::TextBlockInfo},
     errors::CollaborateResult,
     util::make_delta_from_revisions,
 };

+ 1 - 1
frontend/rust-lib/flowy-text-block/src/event_handler.rs

@@ -1,7 +1,7 @@
 use crate::entities::{ExportData, ExportParams, ExportPayload};
 use crate::TextBlockManager;
 use flowy_error::FlowyError;
-use flowy_sync::entities::text_block_info::{TextBlockDelta, TextBlockId};
+use flowy_sync::entities::text_block::{TextBlockDelta, TextBlockId};
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::convert::TryInto;
 use std::sync::Arc;

+ 1 - 1
frontend/rust-lib/flowy-text-block/src/lib.rs

@@ -15,7 +15,7 @@ pub mod errors {
 pub const TEXT_BLOCK_SYNC_INTERVAL_IN_MILLIS: u64 = 1000;
 
 use crate::errors::FlowyError;
-use flowy_sync::entities::text_block_info::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo};
+use flowy_sync::entities::text_block::{CreateTextBlockParams, ResetTextBlockParams, TextBlockId, TextBlockInfo};
 use lib_infra::future::FutureResult;
 
 pub trait BlockCloudService: Send + Sync {

+ 1 - 1
frontend/rust-lib/flowy-text-block/src/manager.rs

@@ -7,7 +7,7 @@ use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
 use flowy_revision::{RevisionCloudService, RevisionManager, RevisionPersistence, RevisionWebSocket};
 use flowy_sync::entities::{
     revision::{md5, RepeatedRevision, Revision},
-    text_block_info::{TextBlockDelta, TextBlockId},
+    text_block::{TextBlockDelta, TextBlockId},
     ws_data::ServerRevisionWSData,
 };
 use lib_infra::future::FutureResult;

+ 0 - 4
shared-lib/Cargo.lock

@@ -447,17 +447,13 @@ name = "flowy-grid-data-model"
 version = "0.1.0"
 dependencies = [
  "bytes",
- "flowy-derive",
  "flowy-error-code",
  "indexmap",
  "lib-infra",
  "nanoid",
- "protobuf",
  "serde",
  "serde_json",
  "serde_repr",
- "strum",
- "strum_macros",
 ]
 
 [[package]]

+ 1 - 4
shared-lib/flowy-grid-data-model/Cargo.toml

@@ -6,17 +6,14 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-flowy-derive = { path = "../flowy-derive" }
-protobuf = {version = "2.18.0"}
 bytes = "1.0"
-strum = "0.21"
-strum_macros = "0.21"
 serde = { version = "1.0", features = ["derive", "rc"] }
 serde_json = {version = "1.0"}
 serde_repr = "0.1"
 nanoid = "0.4.0"
 flowy-error-code = { path = "../flowy-error-code"}
 indexmap = {version = "1.8.1", features = ["serde"]}
+
 [build-dependencies]
 lib-infra = { path = "../lib-infra", features = ["protobuf_file_gen"] }
 

+ 0 - 2
shared-lib/flowy-grid-data-model/Flowy.toml

@@ -1,2 +0,0 @@
-# Check out the FlowyConfig (located in flowy_toml.rs) for more details.
-proto_input = ["src/entities/",]

+ 0 - 5
shared-lib/flowy-grid-data-model/build.rs

@@ -1,5 +0,0 @@
-use lib_infra::code_gen;
-
-fn main() {
-    code_gen::protobuf_file::gen(env!("CARGO_PKG_NAME"));
-}

+ 0 - 523
shared-lib/flowy-grid-data-model/src/entities/field.rs

@@ -1,523 +0,0 @@
-use crate::parser::NotEmptyStr;
-use crate::revision::FieldRevision;
-use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_error_code::ErrorCode;
-use serde_repr::*;
-use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct Field {
-    #[pb(index = 1)]
-    pub id: String,
-
-    #[pb(index = 2)]
-    pub name: String,
-
-    #[pb(index = 3)]
-    pub desc: String,
-
-    #[pb(index = 4)]
-    pub field_type: FieldType,
-
-    #[pb(index = 5)]
-    pub frozen: bool,
-
-    #[pb(index = 6)]
-    pub visibility: bool,
-
-    #[pb(index = 7)]
-    pub width: i32,
-
-    #[pb(index = 8)]
-    pub is_primary: bool,
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct FieldOrder {
-    #[pb(index = 1)]
-    pub field_id: String,
-}
-
-impl std::convert::From<&str> for FieldOrder {
-    fn from(s: &str) -> Self {
-        FieldOrder { field_id: s.to_owned() }
-    }
-}
-
-impl std::convert::From<String> for FieldOrder {
-    fn from(s: String) -> Self {
-        FieldOrder { field_id: s }
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct GridFieldChangeset {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub inserted_fields: Vec<IndexField>,
-
-    #[pb(index = 3)]
-    pub deleted_fields: Vec<FieldOrder>,
-
-    #[pb(index = 4)]
-    pub updated_fields: Vec<Field>,
-}
-
-impl GridFieldChangeset {
-    pub fn insert(grid_id: &str, inserted_fields: Vec<IndexField>) -> Self {
-        Self {
-            grid_id: grid_id.to_owned(),
-            inserted_fields,
-            deleted_fields: vec![],
-            updated_fields: vec![],
-        }
-    }
-
-    pub fn delete(grid_id: &str, deleted_fields: Vec<FieldOrder>) -> Self {
-        Self {
-            grid_id: grid_id.to_string(),
-            inserted_fields: vec![],
-            deleted_fields,
-            updated_fields: vec![],
-        }
-    }
-
-    pub fn update(grid_id: &str, updated_fields: Vec<Field>) -> Self {
-        Self {
-            grid_id: grid_id.to_string(),
-            inserted_fields: vec![],
-            deleted_fields: vec![],
-            updated_fields,
-        }
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct IndexField {
-    #[pb(index = 1)]
-    pub field: Field,
-
-    #[pb(index = 2)]
-    pub index: i32,
-}
-
-impl IndexField {
-    pub fn from_field_rev(field_rev: &FieldRevision, index: usize) -> Self {
-        Self {
-            field: Field::from(field_rev.clone()),
-            index: index as i32,
-        }
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct GetEditFieldContextPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2, one_of)]
-    pub field_id: Option<String>,
-
-    #[pb(index = 3)]
-    pub field_type: FieldType,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct EditFieldPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub field_id: String,
-
-    #[pb(index = 3)]
-    pub field_type: FieldType,
-
-    #[pb(index = 4)]
-    pub create_if_not_exist: bool,
-}
-
-pub struct EditFieldParams {
-    pub grid_id: String,
-    pub field_id: String,
-    pub field_type: FieldType,
-}
-
-impl TryInto<EditFieldParams> for EditFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<EditFieldParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-        Ok(EditFieldParams {
-            grid_id: grid_id.0,
-            field_id: field_id.0,
-            field_type: self.field_type,
-        })
-    }
-}
-
-pub struct CreateFieldParams {
-    pub grid_id: String,
-    pub field_type: FieldType,
-}
-
-impl TryInto<CreateFieldParams> for EditFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-
-        Ok(CreateFieldParams {
-            grid_id: grid_id.0,
-            field_type: self.field_type,
-        })
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct FieldTypeOptionContext {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub grid_field: Field,
-
-    #[pb(index = 3)]
-    pub type_option_data: Vec<u8>,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct FieldTypeOptionData {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub field: Field,
-
-    #[pb(index = 3)]
-    pub type_option_data: Vec<u8>,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedField {
-    #[pb(index = 1)]
-    pub items: Vec<Field>,
-}
-impl std::ops::Deref for RepeatedField {
-    type Target = Vec<Field>;
-    fn deref(&self) -> &Self::Target {
-        &self.items
-    }
-}
-
-impl std::ops::DerefMut for RepeatedField {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.items
-    }
-}
-
-impl std::convert::From<Vec<Field>> for RepeatedField {
-    fn from(items: Vec<Field>) -> Self {
-        Self { items }
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct RepeatedFieldOrder {
-    #[pb(index = 1)]
-    pub items: Vec<FieldOrder>,
-}
-
-impl std::ops::Deref for RepeatedFieldOrder {
-    type Target = Vec<FieldOrder>;
-    fn deref(&self) -> &Self::Target {
-        &self.items
-    }
-}
-
-impl std::convert::From<Vec<FieldOrder>> for RepeatedFieldOrder {
-    fn from(field_orders: Vec<FieldOrder>) -> Self {
-        RepeatedFieldOrder { items: field_orders }
-    }
-}
-
-impl std::convert::From<String> for RepeatedFieldOrder {
-    fn from(s: String) -> Self {
-        RepeatedFieldOrder {
-            items: vec![FieldOrder::from(s)],
-        }
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct InsertFieldPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub field: Field,
-
-    #[pb(index = 3)]
-    pub type_option_data: Vec<u8>,
-
-    #[pb(index = 4, one_of)]
-    pub start_field_id: Option<String>,
-}
-
-#[derive(Clone)]
-pub struct InsertFieldParams {
-    pub grid_id: String,
-    pub field: Field,
-    pub type_option_data: Vec<u8>,
-    pub start_field_id: Option<String>,
-}
-
-impl TryInto<InsertFieldParams> for InsertFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<InsertFieldParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let _ = NotEmptyStr::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-
-        let start_field_id = match self.start_field_id {
-            None => None,
-            Some(id) => Some(NotEmptyStr::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
-        };
-
-        Ok(InsertFieldParams {
-            grid_id: grid_id.0,
-            field: self.field,
-            type_option_data: self.type_option_data,
-            start_field_id,
-        })
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct UpdateFieldTypeOptionPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub field_id: String,
-
-    #[pb(index = 3)]
-    pub type_option_data: Vec<u8>,
-}
-
-#[derive(Clone)]
-pub struct UpdateFieldTypeOptionParams {
-    pub grid_id: String,
-    pub field_id: String,
-    pub type_option_data: Vec<u8>,
-}
-
-impl TryInto<UpdateFieldTypeOptionParams> for UpdateFieldTypeOptionPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<UpdateFieldTypeOptionParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let _ = NotEmptyStr::parse(self.field_id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-
-        Ok(UpdateFieldTypeOptionParams {
-            grid_id: grid_id.0,
-            field_id: self.field_id,
-            type_option_data: self.type_option_data,
-        })
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct QueryFieldPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub field_orders: RepeatedFieldOrder,
-}
-
-pub struct QueryFieldParams {
-    pub grid_id: String,
-    pub field_orders: RepeatedFieldOrder,
-}
-
-impl TryInto<QueryFieldParams> for QueryFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<QueryFieldParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(QueryFieldParams {
-            grid_id: grid_id.0,
-            field_orders: self.field_orders,
-        })
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct FieldChangesetPayload {
-    #[pb(index = 1)]
-    pub field_id: String,
-
-    #[pb(index = 2)]
-    pub grid_id: String,
-
-    #[pb(index = 3, one_of)]
-    pub name: Option<String>,
-
-    #[pb(index = 4, one_of)]
-    pub desc: Option<String>,
-
-    #[pb(index = 5, one_of)]
-    pub field_type: Option<FieldType>,
-
-    #[pb(index = 6, one_of)]
-    pub frozen: Option<bool>,
-
-    #[pb(index = 7, one_of)]
-    pub visibility: Option<bool>,
-
-    #[pb(index = 8, one_of)]
-    pub width: Option<i32>,
-
-    #[pb(index = 9, one_of)]
-    pub type_option_data: Option<Vec<u8>>,
-}
-
-#[derive(Debug, Clone, Default)]
-pub struct FieldChangesetParams {
-    pub field_id: String,
-
-    pub grid_id: String,
-
-    pub name: Option<String>,
-
-    pub desc: Option<String>,
-
-    pub field_type: Option<FieldType>,
-
-    pub frozen: Option<bool>,
-
-    pub visibility: Option<bool>,
-
-    pub width: Option<i32>,
-
-    pub type_option_data: Option<Vec<u8>>,
-}
-
-impl TryInto<FieldChangesetParams> for FieldChangesetPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<FieldChangesetParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-
-        if let Some(type_option_data) = self.type_option_data.as_ref() {
-            if type_option_data.is_empty() {
-                return Err(ErrorCode::TypeOptionDataIsEmpty);
-            }
-        }
-
-        Ok(FieldChangesetParams {
-            field_id: field_id.0,
-            grid_id: grid_id.0,
-            name: self.name,
-            desc: self.desc,
-            field_type: self.field_type,
-            frozen: self.frozen,
-            visibility: self.visibility,
-            width: self.width,
-            type_option_data: self.type_option_data,
-        })
-    }
-}
-
-#[derive(
-    Debug,
-    Clone,
-    PartialEq,
-    Eq,
-    ProtoBuf_Enum,
-    EnumCountMacro,
-    EnumString,
-    EnumIter,
-    Display,
-    Serialize_repr,
-    Deserialize_repr,
-)]
-#[repr(u8)]
-pub enum FieldType {
-    RichText = 0,
-    Number = 1,
-    DateTime = 2,
-    SingleSelect = 3,
-    MultiSelect = 4,
-    Checkbox = 5,
-    URL = 6,
-}
-
-impl std::default::Default for FieldType {
-    fn default() -> Self {
-        FieldType::RichText
-    }
-}
-
-impl AsRef<FieldType> for FieldType {
-    fn as_ref(&self) -> &FieldType {
-        self
-    }
-}
-
-impl From<&FieldType> for FieldType {
-    fn from(field_type: &FieldType) -> Self {
-        field_type.clone()
-    }
-}
-
-impl FieldType {
-    pub fn type_id(&self) -> String {
-        let ty = self.clone() as u8;
-        ty.to_string()
-    }
-
-    pub fn default_cell_width(&self) -> i32 {
-        match self {
-            FieldType::DateTime => 180,
-            _ => 150,
-        }
-    }
-
-    pub fn is_number(&self) -> bool {
-        self == &FieldType::Number
-    }
-
-    pub fn is_text(&self) -> bool {
-        self == &FieldType::RichText
-    }
-
-    pub fn is_checkbox(&self) -> bool {
-        self == &FieldType::Checkbox
-    }
-
-    pub fn is_date(&self) -> bool {
-        self == &FieldType::DateTime
-    }
-
-    pub fn is_single_select(&self) -> bool {
-        self == &FieldType::SingleSelect
-    }
-
-    pub fn is_multi_select(&self) -> bool {
-        self == &FieldType::MultiSelect
-    }
-
-    pub fn is_url(&self) -> bool {
-        self == &FieldType::URL
-    }
-
-    pub fn is_select_option(&self) -> bool {
-        self == &FieldType::MultiSelect || self == &FieldType::SingleSelect
-    }
-}

+ 0 - 379
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -1,379 +0,0 @@
-use crate::entities::FieldOrder;
-use crate::parser::NotEmptyStr;
-use crate::revision::RowRevision;
-use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_error_code::ErrorCode;
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct Grid {
-    #[pb(index = 1)]
-    pub id: String,
-
-    #[pb(index = 2)]
-    pub field_orders: Vec<FieldOrder>,
-
-    #[pb(index = 3)]
-    pub blocks: Vec<GridBlock>,
-}
-
-#[derive(Debug, Default, Clone, ProtoBuf)]
-pub struct RowOrder {
-    #[pb(index = 1)]
-    pub row_id: String,
-
-    #[pb(index = 2)]
-    pub block_id: String,
-
-    #[pb(index = 3)]
-    pub height: i32,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct Row {
-    #[pb(index = 1)]
-    pub id: String,
-
-    #[pb(index = 2)]
-    pub height: i32,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct OptionalRow {
-    #[pb(index = 1, one_of)]
-    pub row: Option<Row>,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedRow {
-    #[pb(index = 1)]
-    pub items: Vec<Row>,
-}
-
-impl std::convert::From<Vec<Row>> for RepeatedRow {
-    fn from(items: Vec<Row>) -> Self {
-        Self { items }
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedGridBlock {
-    #[pb(index = 1)]
-    pub items: Vec<GridBlock>,
-}
-
-impl std::convert::From<Vec<GridBlock>> for RepeatedGridBlock {
-    fn from(items: Vec<GridBlock>) -> Self {
-        Self { items }
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct IndexRowOrder {
-    #[pb(index = 1)]
-    pub row_order: RowOrder,
-
-    #[pb(index = 2, one_of)]
-    pub index: Option<i32>,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct UpdatedRowOrder {
-    #[pb(index = 1)]
-    pub row_order: RowOrder,
-
-    #[pb(index = 2)]
-    pub row: Row,
-}
-
-impl UpdatedRowOrder {
-    pub fn new(row_rev: &RowRevision, row: Row) -> Self {
-        Self {
-            row_order: RowOrder::from(row_rev),
-            row,
-        }
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct GridRowsChangeset {
-    #[pb(index = 1)]
-    pub block_id: String,
-
-    #[pb(index = 2)]
-    pub inserted_rows: Vec<IndexRowOrder>,
-
-    #[pb(index = 3)]
-    pub deleted_rows: Vec<RowOrder>,
-
-    #[pb(index = 4)]
-    pub updated_rows: Vec<UpdatedRowOrder>,
-}
-
-impl std::convert::From<RowOrder> for IndexRowOrder {
-    fn from(row_order: RowOrder) -> Self {
-        Self { row_order, index: None }
-    }
-}
-
-impl std::convert::From<&RowRevision> for IndexRowOrder {
-    fn from(row: &RowRevision) -> Self {
-        let row_order = RowOrder::from(row);
-        Self::from(row_order)
-    }
-}
-
-impl GridRowsChangeset {
-    pub fn insert(block_id: &str, inserted_rows: Vec<IndexRowOrder>) -> Self {
-        Self {
-            block_id: block_id.to_owned(),
-            inserted_rows,
-            deleted_rows: vec![],
-            updated_rows: vec![],
-        }
-    }
-
-    pub fn delete(block_id: &str, deleted_rows: Vec<RowOrder>) -> Self {
-        Self {
-            block_id: block_id.to_owned(),
-            inserted_rows: vec![],
-            deleted_rows,
-            updated_rows: vec![],
-        }
-    }
-
-    pub fn update(block_id: &str, updated_rows: Vec<UpdatedRowOrder>) -> Self {
-        Self {
-            block_id: block_id.to_owned(),
-            inserted_rows: vec![],
-            deleted_rows: vec![],
-            updated_rows,
-        }
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct GridBlock {
-    #[pb(index = 1)]
-    pub id: String,
-
-    #[pb(index = 2)]
-    pub row_orders: Vec<RowOrder>,
-}
-
-impl GridBlock {
-    pub fn new(block_id: &str, row_orders: Vec<RowOrder>) -> Self {
-        Self {
-            id: block_id.to_owned(),
-            row_orders,
-        }
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct Cell {
-    #[pb(index = 1)]
-    pub field_id: String,
-
-    #[pb(index = 2)]
-    pub data: Vec<u8>,
-}
-
-impl Cell {
-    pub fn new(field_id: &str, data: Vec<u8>) -> Self {
-        Self {
-            field_id: field_id.to_owned(),
-            data,
-        }
-    }
-
-    pub fn empty(field_id: &str) -> Self {
-        Self {
-            field_id: field_id.to_owned(),
-            data: vec![],
-        }
-    }
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedCell {
-    #[pb(index = 1)]
-    pub items: Vec<Cell>,
-}
-
-impl std::ops::Deref for RepeatedCell {
-    type Target = Vec<Cell>;
-    fn deref(&self) -> &Self::Target {
-        &self.items
-    }
-}
-
-impl std::ops::DerefMut for RepeatedCell {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.items
-    }
-}
-
-impl std::convert::From<Vec<Cell>> for RepeatedCell {
-    fn from(items: Vec<Cell>) -> Self {
-        Self { items }
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct CreateGridPayload {
-    #[pb(index = 1)]
-    pub name: String,
-}
-
-#[derive(Clone, ProtoBuf, Default, Debug)]
-pub struct GridId {
-    #[pb(index = 1)]
-    pub value: String,
-}
-
-impl AsRef<str> for GridId {
-    fn as_ref(&self) -> &str {
-        &self.value
-    }
-}
-
-#[derive(Clone, ProtoBuf, Default, Debug)]
-pub struct GridBlockId {
-    #[pb(index = 1)]
-    pub value: String,
-}
-
-impl AsRef<str> for GridBlockId {
-    fn as_ref(&self) -> &str {
-        &self.value
-    }
-}
-
-impl std::convert::From<&str> for GridBlockId {
-    fn from(s: &str) -> Self {
-        GridBlockId { value: s.to_owned() }
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct CreateRowPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2, one_of)]
-    pub start_row_id: Option<String>,
-}
-
-#[derive(Default)]
-pub struct CreateRowParams {
-    pub grid_id: String,
-    pub start_row_id: Option<String>,
-}
-
-impl TryInto<CreateRowParams> for CreateRowPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<CreateRowParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(CreateRowParams {
-            grid_id: grid_id.0,
-            start_row_id: self.start_row_id,
-        })
-    }
-}
-
-#[derive(ProtoBuf, Default)]
-pub struct QueryGridBlocksPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub block_ids: Vec<String>,
-}
-
-pub struct QueryGridBlocksParams {
-    pub grid_id: String,
-    pub block_ids: Vec<String>,
-}
-
-impl TryInto<QueryGridBlocksParams> for QueryGridBlocksPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<QueryGridBlocksParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(QueryGridBlocksParams {
-            grid_id: grid_id.0,
-            block_ids: self.block_ids,
-        })
-    }
-}
-
-#[derive(Debug, Clone, ProtoBuf_Enum)]
-pub enum MoveItemType {
-    MoveField = 0,
-    MoveRow = 1,
-}
-
-impl std::default::Default for MoveItemType {
-    fn default() -> Self {
-        MoveItemType::MoveField
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct MoveItemPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub item_id: String,
-
-    #[pb(index = 3)]
-    pub from_index: i32,
-
-    #[pb(index = 4)]
-    pub to_index: i32,
-
-    #[pb(index = 5)]
-    pub ty: MoveItemType,
-}
-
-#[derive(Clone)]
-pub struct MoveItemParams {
-    pub grid_id: String,
-    pub item_id: String,
-    pub from_index: i32,
-    pub to_index: i32,
-    pub ty: MoveItemType,
-}
-
-impl TryInto<MoveItemParams> for MoveItemPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<MoveItemParams, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let item_id = NotEmptyStr::parse(self.item_id).map_err(|_| ErrorCode::InvalidData)?;
-        Ok(MoveItemParams {
-            grid_id: grid_id.0,
-            item_id: item_id.0,
-            from_index: self.from_index,
-            to_index: self.to_index,
-            ty: self.ty,
-        })
-    }
-}
-
-#[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct CellChangeset {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 2)]
-    pub row_id: String,
-
-    #[pb(index = 3)]
-    pub field_id: String,
-
-    #[pb(index = 4, one_of)]
-    pub cell_content_changeset: Option<String>,
-}

+ 0 - 13
shared-lib/flowy-grid-data-model/src/entities/mod.rs

@@ -1,13 +0,0 @@
-mod field;
-mod grid;
-mod grid_filter;
-mod grid_group;
-mod grid_setting;
-mod grid_sort;
-
-pub use field::*;
-pub use grid::*;
-pub use grid_filter::*;
-pub use grid_group::*;
-pub use grid_setting::*;
-pub use grid_sort::*;

+ 0 - 2
shared-lib/flowy-grid-data-model/src/lib.rs

@@ -1,4 +1,2 @@
-pub mod entities;
 pub mod parser;
-pub mod protobuf;
 pub mod revision;

+ 39 - 82
shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs

@@ -1,4 +1,3 @@
-use crate::entities::{CellChangeset, Field, FieldOrder, FieldType, RowOrder};
 use crate::revision::GridSettingRevision;
 use bytes::Bytes;
 use indexmap::IndexMap;
@@ -29,7 +28,7 @@ pub fn gen_field_id() -> String {
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
 pub struct GridRevision {
     pub grid_id: String,
-    pub fields: Vec<FieldRevision>,
+    pub fields: Vec<Arc<FieldRevision>>,
     pub blocks: Vec<Arc<GridBlockMetaRevision>>,
 
     #[serde(default, skip)]
@@ -49,7 +48,7 @@ impl GridRevision {
     pub fn from_build_context(grid_id: &str, context: BuildGridContext) -> Self {
         Self {
             grid_id: grid_id.to_owned(),
-            fields: context.field_revs,
+            fields: context.field_revs.into_iter().map(Arc::new).collect(),
             blocks: context.blocks.into_iter().map(Arc::new).collect(),
             setting: Default::default(),
         }
@@ -112,7 +111,8 @@ pub struct FieldRevision {
 
     pub desc: String,
 
-    pub field_type: FieldType,
+    #[serde(rename = "field_type")]
+    pub field_type_rev: FieldTypeRevision,
 
     pub frozen: bool,
 
@@ -131,16 +131,27 @@ pub struct FieldRevision {
     pub is_primary: bool,
 }
 
+impl AsRef<FieldRevision> for FieldRevision {
+    fn as_ref(&self) -> &FieldRevision {
+        self
+    }
+}
+
 const DEFAULT_IS_PRIMARY: fn() -> bool = || false;
 
 impl FieldRevision {
-    pub fn new(name: &str, desc: &str, field_type: FieldType, is_primary: bool) -> Self {
-        let width = field_type.default_cell_width();
+    pub fn new<T: Into<FieldTypeRevision>>(
+        name: &str,
+        desc: &str,
+        field_type: T,
+        width: i32,
+        is_primary: bool,
+    ) -> Self {
         Self {
             id: gen_field_id(),
             name: name.to_string(),
             desc: desc.to_string(),
-            field_type,
+            field_type_rev: field_type.into(),
             frozen: false,
             visibility: true,
             width,
@@ -153,49 +164,32 @@ impl FieldRevision {
     where
         T: TypeOptionDataEntry + ?Sized,
     {
-        self.type_options.insert(entry.field_type().type_id(), entry.json_str());
-    }
-
-    pub fn get_type_option_entry<T: TypeOptionDataDeserializer>(&self, field_type: &FieldType) -> Option<T> {
-        self.type_options
-            .get(&field_type.type_id())
-            .map(|s| T::from_json_str(s))
+        let id = self.field_type_rev.to_string();
+        self.type_options.insert(id, entry.json_str());
     }
 
-    pub fn insert_type_option_str(&mut self, field_type: &FieldType, json_str: String) {
-        self.type_options.insert(field_type.type_id(), json_str);
+    pub fn get_type_option_entry<T1: TypeOptionDataDeserializer, T2: Into<FieldTypeRevision>>(
+        &self,
+        field_type: T2,
+    ) -> Option<T1> {
+        let field_type_rev = field_type.into();
+        let id = field_type_rev.to_string();
+        self.type_options.get(&id).map(|s| T1::from_json_str(s))
     }
 
-    pub fn get_type_option_str(&self, field_type: &FieldType) -> Option<String> {
-        self.type_options.get(&field_type.type_id()).map(|s| s.to_owned())
+    pub fn insert_type_option_str(&mut self, field_type: &FieldTypeRevision, json_str: String) {
+        let id = field_type.to_string();
+        self.type_options.insert(id, json_str);
     }
-}
 
-impl std::convert::From<FieldRevision> for Field {
-    fn from(field_rev: FieldRevision) -> Self {
-        Self {
-            id: field_rev.id,
-            name: field_rev.name,
-            desc: field_rev.desc,
-            field_type: field_rev.field_type,
-            frozen: field_rev.frozen,
-            visibility: field_rev.visibility,
-            width: field_rev.width,
-            is_primary: field_rev.is_primary,
-        }
-    }
-}
-
-impl std::convert::From<&FieldRevision> for FieldOrder {
-    fn from(field_rev: &FieldRevision) -> Self {
-        Self {
-            field_id: field_rev.id.clone(),
-        }
+    pub fn get_type_option_str<T: Into<FieldTypeRevision>>(&self, field_type: T) -> Option<String> {
+        let field_type_rev = field_type.into();
+        let id = field_type_rev.to_string();
+        self.type_options.get(&id).map(|s| s.to_owned())
     }
 }
 
 pub trait TypeOptionDataEntry {
-    fn field_type(&self) -> FieldType;
     fn json_str(&self) -> String;
     fn protobuf_bytes(&self) -> Bytes;
 }
@@ -204,7 +198,7 @@ pub trait TypeOptionDataDeserializer {
     fn from_json_str(s: &str) -> Self;
     fn from_protobuf_bytes(bytes: Bytes) -> Self;
 }
-
+pub type FieldId = String;
 #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
 pub struct RowRevision {
     pub id: String,
@@ -213,7 +207,7 @@ pub struct RowRevision {
     /// key: field id,
     /// value: CellMeta
     #[serde(with = "indexmap::serde_seq")]
-    pub cells: IndexMap<String, CellRevision>,
+    pub cells: IndexMap<FieldId, CellRevision>,
     pub height: i32,
     pub visibility: bool,
 }
@@ -229,51 +223,12 @@ impl RowRevision {
         }
     }
 }
-
-impl std::convert::From<&RowRevision> for RowOrder {
-    fn from(row: &RowRevision) -> Self {
-        Self {
-            row_id: row.id.clone(),
-            block_id: row.block_id.clone(),
-            height: row.height,
-        }
-    }
-}
-
-impl std::convert::From<&Arc<RowRevision>> for RowOrder {
-    fn from(row: &Arc<RowRevision>) -> Self {
-        Self {
-            row_id: row.id.clone(),
-            block_id: row.block_id.clone(),
-            height: row.height,
-        }
-    }
-}
-
 #[derive(Debug, Clone, Default)]
 pub struct RowMetaChangeset {
     pub row_id: String,
     pub height: Option<i32>,
     pub visibility: Option<bool>,
-    pub cell_by_field_id: HashMap<String, CellRevision>,
-}
-
-impl std::convert::From<CellChangeset> for RowMetaChangeset {
-    fn from(changeset: CellChangeset) -> Self {
-        let mut cell_by_field_id = HashMap::with_capacity(1);
-        let field_id = changeset.field_id;
-        let cell_rev = CellRevision {
-            data: changeset.cell_content_changeset.unwrap_or_else(|| "".to_owned()),
-        };
-        cell_by_field_id.insert(field_id, cell_rev);
-
-        RowMetaChangeset {
-            row_id: changeset.row_id,
-            height: None,
-            visibility: None,
-            cell_by_field_id,
-        }
-    }
+    pub cell_by_field_id: HashMap<FieldId, CellRevision>,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
@@ -315,3 +270,5 @@ impl std::convert::TryFrom<Bytes> for BuildGridContext {
         Ok(ctx)
     }
 }
+
+pub type FieldTypeRevision = u8;

+ 85 - 3
shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs

@@ -1,7 +1,9 @@
+use crate::revision::FieldTypeRevision;
 use indexmap::IndexMap;
 use nanoid::nanoid;
 use serde::{Deserialize, Serialize};
 use serde_repr::*;
+use std::sync::Arc;
 
 pub fn gen_grid_filter_id() -> String {
     nanoid!(6)
@@ -18,9 +20,17 @@ pub fn gen_grid_sort_id() -> String {
 #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
 pub struct GridSettingRevision {
     pub layout: GridLayoutRevision,
-
+    // layout:
+    //       field_id:
+    //               FieldType: GridFilterRevision
+    //               FieldType: GridFilterRevision
+    // layout:
+    //       field_id:
+    //               FieldType: GridFilterRevision
+    //       field_id:
+    //               FieldType: GridFilterRevision
     #[serde(with = "indexmap::serde_seq")]
-    pub filters: IndexMap<GridLayoutRevision, Vec<GridFilterRevision>>,
+    pub filters: IndexMap<GridLayoutRevision, IndexMap<String, GridFilterRevisionMap>>,
 
     #[serde(skip, with = "indexmap::serde_seq")]
     pub groups: IndexMap<GridLayoutRevision, Vec<GridGroupRevision>>,
@@ -29,6 +39,78 @@ pub struct GridSettingRevision {
     pub sorts: IndexMap<GridLayoutRevision, Vec<GridSortRevision>>,
 }
 
+impl GridSettingRevision {
+    pub fn get_mut_filters(
+        &mut self,
+        layout: &GridLayoutRevision,
+        field_id: &str,
+        field_type: &FieldTypeRevision,
+    ) -> Option<&mut Vec<Arc<GridFilterRevision>>> {
+        self.filters
+            .get_mut(layout)
+            .and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get_mut(field_id))
+            .and_then(|filter_rev_map| filter_rev_map.get_mut(field_type))
+    }
+
+    pub fn get_filters(
+        &self,
+        layout: &GridLayoutRevision,
+        field_id: &str,
+        field_type: &FieldTypeRevision,
+    ) -> Option<Vec<Arc<GridFilterRevision>>> {
+        self.filters
+            .get(layout)
+            .and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get(field_id))
+            .and_then(|filter_rev_map| filter_rev_map.get(field_type))
+            .cloned()
+    }
+
+    pub fn insert_filter(
+        &mut self,
+        layout: &GridLayoutRevision,
+        field_id: &str,
+        field_type: &FieldTypeRevision,
+        filter_rev: GridFilterRevision,
+    ) {
+        let filter_rev_map_by_field_id = self.filters.entry(layout.clone()).or_insert_with(IndexMap::new);
+        let filter_rev_map = filter_rev_map_by_field_id
+            .entry(field_id.to_string())
+            .or_insert_with(GridFilterRevisionMap::new);
+
+        filter_rev_map
+            .entry(field_type.to_owned())
+            .or_insert_with(Vec::new)
+            .push(Arc::new(filter_rev))
+    }
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
+#[serde(transparent)]
+pub struct GridFilterRevisionMap {
+    #[serde(with = "indexmap::serde_seq")]
+    pub filter_by_field_type: IndexMap<FieldTypeRevision, Vec<Arc<GridFilterRevision>>>,
+}
+
+impl GridFilterRevisionMap {
+    pub fn new() -> Self {
+        GridFilterRevisionMap::default()
+    }
+}
+
+impl std::ops::Deref for GridFilterRevisionMap {
+    type Target = IndexMap<FieldTypeRevision, Vec<Arc<GridFilterRevision>>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.filter_by_field_type
+    }
+}
+
+impl std::ops::DerefMut for GridFilterRevisionMap {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.filter_by_field_type
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
 #[repr(u8)]
 pub enum GridLayoutRevision {
@@ -49,7 +131,7 @@ impl std::default::Default for GridLayoutRevision {
     }
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
+#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
 pub struct GridFilterRevision {
     pub id: String,
     pub field_id: String,

+ 1 - 1
shared-lib/flowy-sync/src/client_folder/builder.rs

@@ -1,4 +1,4 @@
-use crate::entities::folder_info::FolderDelta;
+use crate::entities::folder::FolderDelta;
 use crate::util::make_delta_from_revisions;
 use crate::{
     client_folder::{default_folder_delta, FolderPad},

+ 2 - 2
shared-lib/flowy-sync/src/client_folder/folder_pad.rs

@@ -3,7 +3,7 @@ use crate::util::cal_diff;
 use crate::{
     client_folder::builder::FolderPadBuilder,
     entities::{
-        folder_info::FolderDelta,
+        folder::FolderDelta,
         revision::{md5, Revision},
     },
     errors::{CollaborateError, CollaborateResult},
@@ -431,7 +431,7 @@ pub struct FolderChange {
 #[cfg(test)]
 mod tests {
     #![allow(clippy::all)]
-    use crate::{client_folder::folder_pad::FolderPad, entities::folder_info::FolderDelta};
+    use crate::{client_folder::folder_pad::FolderPad, entities::folder::FolderDelta};
     use chrono::Utc;
 
     use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};

+ 0 - 33
shared-lib/flowy-sync/src/client_grid/grid_builder.rs

@@ -57,36 +57,3 @@ fn check_rows(fields: &[FieldRevision], rows: &[RowRevision]) -> CollaborateResu
     }
     Ok(())
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBuilder};
-    use flowy_grid_data_model::entities::FieldType;
-    use flowy_grid_data_model::revision::{FieldRevision, GridBlockRevision, GridRevision};
-    use std::sync::Arc;
-
-    #[test]
-    fn create_default_grid_test() {
-        let grid_id = "1".to_owned();
-        let build_context = GridBuilder::default()
-            .add_field(FieldRevision::new("Name", "", FieldType::RichText, true))
-            .add_field(FieldRevision::new("Tags", "", FieldType::SingleSelect, false))
-            .add_empty_row()
-            .add_empty_row()
-            .add_empty_row()
-            .build();
-
-        let grid_rev = GridRevision {
-            grid_id,
-            fields: build_context.field_revs,
-            blocks: build_context.blocks.into_iter().map(Arc::new).collect(),
-            setting: Default::default(),
-        };
-
-        let grid_meta_delta = make_grid_delta(&grid_rev);
-        let _: GridRevision = serde_json::from_str(&grid_meta_delta.to_str().unwrap()).unwrap();
-
-        let grid_block_meta_delta = make_block_meta_delta(build_context.blocks_meta_data.first().unwrap());
-        let _: GridBlockRevision = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap();
-    }
-}

+ 81 - 44
shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs

@@ -1,13 +1,12 @@
+use crate::entities::grid::{FieldChangesetParams, GridSettingChangesetParams};
 use crate::entities::revision::{md5, RepeatedRevision, Revision};
 use crate::errors::{internal_error, CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
 use bytes::Bytes;
-use flowy_grid_data_model::entities::{FieldChangesetParams, FieldOrder};
-use flowy_grid_data_model::entities::{FieldType, GridSettingChangesetParams};
 use flowy_grid_data_model::revision::{
     gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, gen_grid_sort_id, FieldRevision,
-    GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridFilterRevision, GridGroupRevision, GridLayoutRevision,
-    GridRevision, GridSettingRevision, GridSortRevision,
+    FieldTypeRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridFilterRevision, GridGroupRevision,
+    GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision,
 };
 use lib_infra::util::move_vec_element;
 use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
@@ -27,8 +26,16 @@ pub trait JsonDeserializer {
 }
 
 impl GridRevisionPad {
+    pub fn grid_id(&self) -> String {
+        self.grid_rev.grid_id.clone()
+    }
     pub async fn duplicate_grid_block_meta(&self) -> (Vec<FieldRevision>, Vec<GridBlockMetaRevision>) {
-        let fields = self.grid_rev.fields.to_vec();
+        let fields = self
+            .grid_rev
+            .fields
+            .iter()
+            .map(|field_rev| field_rev.as_ref().clone())
+            .collect();
 
         let blocks = self
             .grid_rev
@@ -81,7 +88,7 @@ impl GridRevisionPad {
                 None => None,
                 Some(start_field_id) => grid_meta.fields.iter().position(|field| field.id == start_field_id),
             };
-
+            let new_field_rev = Arc::new(new_field_rev);
             match insert_index {
                 None => grid_meta.fields.push(new_field_rev),
                 Some(index) => grid_meta.fields.insert(index, new_field_rev),
@@ -111,25 +118,27 @@ impl GridRevisionPad {
             |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
                 None => Ok(None),
                 Some(index) => {
-                    let mut duplicate_field_rev = grid_meta.fields[index].clone();
+                    let mut duplicate_field_rev = grid_meta.fields[index].as_ref().clone();
                     duplicate_field_rev.id = duplicated_field_id.to_string();
                     duplicate_field_rev.name = format!("{} (copy)", duplicate_field_rev.name);
-                    grid_meta.fields.insert(index + 1, duplicate_field_rev);
+                    grid_meta.fields.insert(index + 1, Arc::new(duplicate_field_rev));
                     Ok(Some(()))
                 }
             },
         )
     }
 
-    pub fn switch_to_field<B>(
+    pub fn switch_to_field<B, T>(
         &mut self,
         field_id: &str,
-        field_type: FieldType,
+        field_type: T,
         type_option_json_builder: B,
     ) -> CollaborateResult<Option<GridChangeset>>
     where
-        B: FnOnce(&FieldType) -> String,
+        B: FnOnce(&FieldTypeRevision) -> String,
+        T: Into<FieldTypeRevision>,
     {
+        let field_type = field_type.into();
         self.modify_grid(|grid_meta| {
             //
             match grid_meta.fields.iter_mut().find(|field_rev| field_rev.id == field_id) {
@@ -138,12 +147,13 @@ impl GridRevisionPad {
                     Ok(None)
                 }
                 Some(field_rev) => {
-                    if field_rev.get_type_option_str(&field_type).is_none() {
+                    let mut_field_rev = Arc::make_mut(field_rev);
+                    if mut_field_rev.get_type_option_str(field_type).is_none() {
                         let type_option_json = type_option_json_builder(&field_type);
-                        field_rev.insert_type_option_str(&field_type, type_option_json);
+                        mut_field_rev.insert_type_option_str(&field_type, type_option_json);
                     }
 
-                    field_rev.field_type = field_type;
+                    mut_field_rev.field_type_rev = field_type;
                     Ok(Some(()))
                 }
             }
@@ -169,7 +179,7 @@ impl GridRevisionPad {
             }
 
             if let Some(field_type) = changeset.field_type {
-                field.field_type = field_type;
+                field.field_type_rev = field_type;
                 is_changed = Some(())
             }
 
@@ -191,7 +201,7 @@ impl GridRevisionPad {
             if let Some(type_option_data) = changeset.type_option_data {
                 match deserializer.deserialize(type_option_data) {
                     Ok(json_str) => {
-                        let field_type = field.field_type.clone();
+                        let field_type = field.field_type_rev;
                         field.insert_type_option_str(&field_type, json_str);
                         is_changed = Some(())
                     }
@@ -205,7 +215,7 @@ impl GridRevisionPad {
         })
     }
 
-    pub fn get_field_rev(&self, field_id: &str) -> Option<(usize, &FieldRevision)> {
+    pub fn get_field_rev(&self, field_id: &str) -> Option<(usize, &Arc<FieldRevision>)> {
         self.grid_rev
             .fields
             .iter()
@@ -213,7 +223,7 @@ impl GridRevisionPad {
             .find(|(_, field)| field.id == field_id)
     }
 
-    pub fn replace_field_rev(&mut self, field_rev: FieldRevision) -> CollaborateResult<Option<GridChangeset>> {
+    pub fn replace_field_rev(&mut self, field_rev: Arc<FieldRevision>) -> CollaborateResult<Option<GridChangeset>> {
         self.modify_grid(
             |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_rev.id) {
                 None => Ok(None),
@@ -251,31 +261,27 @@ impl GridRevisionPad {
         self.grid_rev.fields.iter().any(|field| field.id == field_id)
     }
 
-    pub fn get_field_orders(&self) -> Vec<FieldOrder> {
-        self.grid_rev.fields.iter().map(FieldOrder::from).collect()
-    }
-
-    pub fn get_field_revs(&self, field_orders: Option<Vec<FieldOrder>>) -> CollaborateResult<Vec<FieldRevision>> {
-        match field_orders {
+    pub fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> CollaborateResult<Vec<Arc<FieldRevision>>> {
+        match field_ids {
             None => Ok(self.grid_rev.fields.clone()),
-            Some(field_orders) => {
+            Some(field_ids) => {
                 let field_by_field_id = self
                     .grid_rev
                     .fields
                     .iter()
                     .map(|field| (&field.id, field))
-                    .collect::<HashMap<&String, &FieldRevision>>();
+                    .collect::<HashMap<&String, &Arc<FieldRevision>>>();
 
-                let fields = field_orders
+                let fields = field_ids
                     .iter()
-                    .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
+                    .flat_map(|field_id| match field_by_field_id.get(&field_id) {
                         None => {
-                            tracing::error!("Can't find the field with id: {}", field_order.field_id);
+                            tracing::error!("Can't find the field with id: {}", field_id);
                             None
                         }
                         Some(field) => Some((*field).clone()),
                     })
-                    .collect::<Vec<FieldRevision>>();
+                    .collect::<Vec<Arc<FieldRevision>>>();
                 Ok(fields)
             }
         }
@@ -334,9 +340,35 @@ impl GridRevisionPad {
         &self.grid_rev.setting
     }
 
-    pub fn get_filters(&self, layout: Option<&GridLayoutRevision>) -> Option<&Vec<GridFilterRevision>> {
+    /// If layout is None, then the default layout will be the read from GridSettingRevision
+    pub fn get_filters(
+        &self,
+        layout: Option<&GridLayoutRevision>,
+        field_ids: Option<Vec<String>>,
+    ) -> Option<Vec<Arc<GridFilterRevision>>> {
+        let mut filter_revs = vec![];
         let layout_ty = layout.unwrap_or(&self.grid_rev.setting.layout);
-        self.grid_rev.setting.filters.get(layout_ty)
+        let field_revs = self.get_field_revs(None).ok()?;
+
+        field_revs.iter().for_each(|field_rev| {
+            let mut is_contain = true;
+            if let Some(field_ids) = &field_ids {
+                is_contain = field_ids.contains(&field_rev.id);
+            }
+
+            if is_contain {
+                // Only return the filters for the current fields' type.
+                if let Some(mut t_filter_revs) =
+                    self.grid_rev
+                        .setting
+                        .get_filters(layout_ty, &field_rev.id, &field_rev.field_type_rev)
+                {
+                    filter_revs.append(&mut t_filter_revs);
+                }
+            }
+        });
+
+        Some(filter_revs)
     }
 
     pub fn update_grid_setting_rev(
@@ -345,28 +377,30 @@ impl GridRevisionPad {
     ) -> CollaborateResult<Option<GridChangeset>> {
         self.modify_grid(|grid_rev| {
             let mut is_changed = None;
-            let layout_rev: GridLayoutRevision = changeset.layout_type.into();
+            let layout_rev = changeset.layout_type;
 
             if let Some(params) = changeset.insert_filter {
-                let rev = GridFilterRevision {
+                let filter_rev = GridFilterRevision {
                     id: gen_grid_filter_id(),
-                    field_id: params.field_id,
+                    field_id: params.field_id.clone(),
                     condition: params.condition,
                     content: params.content,
                 };
 
                 grid_rev
                     .setting
-                    .filters
-                    .entry(layout_rev.clone())
-                    .or_insert_with(std::vec::Vec::new)
-                    .push(rev);
+                    .insert_filter(&layout_rev, &params.field_id, &params.field_type_rev, filter_rev);
 
                 is_changed = Some(())
             }
-            if let Some(delete_filter_id) = changeset.delete_filter {
-                match grid_rev.setting.filters.get_mut(&layout_rev) {
-                    Some(filters) => filters.retain(|filter| filter.id != delete_filter_id),
+            if let Some(params) = changeset.delete_filter {
+                match grid_rev
+                    .setting
+                    .get_mut_filters(&layout_rev, &params.filter_id, &params.field_type_rev)
+                {
+                    Some(filters) => {
+                        filters.retain(|filter| filter.id != params.filter_id);
+                    }
                     None => {
                         tracing::warn!("Can't find the filter with {:?}", layout_rev);
                     }
@@ -435,7 +469,7 @@ impl GridRevisionPad {
         self.delta.to_delta_bytes()
     }
 
-    pub fn fields(&self) -> &[FieldRevision] {
+    pub fn fields(&self) -> &[Arc<FieldRevision>] {
         &self.grid_rev.fields
     }
 
@@ -488,7 +522,10 @@ impl GridRevisionPad {
                     tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
                     Ok(None)
                 }
-                Some(index) => f(&mut grid_rev.fields[index]),
+                Some(index) => {
+                    let mut_field_rev = Arc::make_mut(&mut grid_rev.fields[index]);
+                    f(mut_field_rev)
+                }
             },
         )
     }

+ 0 - 0
shared-lib/flowy-sync/src/entities/folder_info.rs → shared-lib/flowy-sync/src/entities/folder.rs


部分文件因文件數量過多而無法顯示