Sfoglia il codice sorgente

chore: rename trait

appflowy 3 anni fa
parent
commit
50f32521c5
59 ha cambiato i file con 1443 aggiunte e 851 eliminazioni
  1. 0 1
      frontend/app_flowy/lib/startup/home_deps_resolver.dart
  2. 0 1
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart
  3. 0 1
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart
  4. 0 1
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart
  5. 0 1
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart
  6. 0 1
      frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart
  7. 1 1
      frontend/app_flowy/lib/workspace/application/grid/column_bloc.dart
  8. 0 1
      frontend/app_flowy/lib/workspace/application/grid/data.dart
  9. 0 1
      frontend/app_flowy/lib/workspace/application/grid/grid_service.dart
  10. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart
  11. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/layout.dart
  12. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart
  13. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart
  14. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart
  15. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart
  16. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart
  17. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart
  18. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart
  19. 29 43
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart
  20. 7 8
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart
  21. 174 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
  22. 26 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
  23. 16 57
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart
  24. 7 17
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart
  25. 1 1
      frontend/rust-lib/flowy-block/tests/document/script.rs
  26. 0 1
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  27. 1 1
      frontend/rust-lib/flowy-folder/tests/workspace/script.rs
  28. 8 3
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  29. 3 3
      frontend/rust-lib/flowy-grid/src/macros.rs
  30. 30 12
      frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs
  31. 14 14
      frontend/rust-lib/flowy-grid/src/services/cell/description/checkbox_description.rs
  32. 15 15
      frontend/rust-lib/flowy-grid/src/services/cell/description/date_description.rs
  33. 40 22
      frontend/rust-lib/flowy-grid/src/services/cell/description/number_description.rs
  34. 13 13
      frontend/rust-lib/flowy-grid/src/services/cell/description/selection_description.rs
  35. 6 6
      frontend/rust-lib/flowy-grid/src/services/cell/description/text_description.rs
  36. 14 14
      frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs
  37. 22 15
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  38. 32 0
      frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs
  39. 0 33
      frontend/rust-lib/flowy-grid/src/services/row/cell_stringify.rs
  40. 2 2
      frontend/rust-lib/flowy-grid/src/services/row/mod.rs
  41. 3 3
      frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs
  42. 14 11
      frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs
  43. 27 28
      frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs
  44. 32 26
      frontend/rust-lib/flowy-grid/tests/grid/script.rs
  45. 1 1
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  46. 7 9
      frontend/rust-lib/flowy-test/src/helper.rs
  47. 22 21
      shared-lib/flowy-collaboration/src/client_grid/block_pad.rs
  48. 7 7
      shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs
  49. 29 10
      shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs
  50. 5 11
      shared-lib/flowy-folder-data-model/src/entities/view.rs
  51. 76 118
      shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs
  52. 5 6
      shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto
  53. 76 4
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  54. 11 29
      shared-lib/flowy-grid-data-model/src/entities/meta.rs
  55. 574 23
      shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
  56. 72 239
      shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs
  57. 13 0
      shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto
  58. 2 5
      shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto
  59. 2 2
      shared-lib/flowy-grid-data-model/tests/serde_test.rs

+ 0 - 1
frontend/app_flowy/lib/startup/home_deps_resolver.dart

@@ -13,7 +13,6 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
 import 'package:get_it/get_it.dart';
 

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart

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

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

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

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart

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

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart

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

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart

@@ -1,5 +1,4 @@
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.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/column_bloc.dart

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

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

@@ -1,6 +1,5 @@
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:equatable/equatable.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 
 class GridInfo {
   List<Row> rows;

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

@@ -3,7 +3,6 @@ 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/grid.pb.dart';
 import 'package:dartz/dartz.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 
 class GridService {
   Future<Either<Grid, FlowyError>> openGrid({required String gridId}) async {

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

@@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 import 'package:styled_widget/styled_widget.dart';

+ 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/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 
 import 'sizes.dart';
 

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/cell_bloc/date_cell_bloc.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/cell_bloc/number_cell_bloc.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter/material.dart';
 
 class SingleSelectCell extends StatefulWidget {

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/grid/cell_bloc/text_cell_bloc.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/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/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

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

@@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
 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/meta.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 

+ 29 - 43
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart

@@ -275,8 +275,8 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
     ..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
-    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
-    ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
+    ..a<$core.int>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
+    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
     ..hasRequiredFields = false
   ;
 
@@ -287,8 +287,8 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     $core.String? desc,
     $core.String? thumbnail,
     ViewDataType? dataType,
-    $core.String? extData,
     $core.int? pluginType,
+    $core.String? data,
   }) {
     final _result = create();
     if (belongToId != null) {
@@ -306,12 +306,12 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     if (dataType != null) {
       _result.dataType = dataType;
     }
-    if (extData != null) {
-      _result.extData = extData;
-    }
     if (pluginType != null) {
       _result.pluginType = pluginType;
     }
+    if (data != null) {
+      _result.data = data;
+    }
     return _result;
   }
   factory CreateViewPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -384,22 +384,22 @@ class CreateViewPayload extends $pb.GeneratedMessage {
   void clearDataType() => clearField(5);
 
   @$pb.TagNumber(6)
-  $core.String get extData => $_getSZ(5);
+  $core.int get pluginType => $_getIZ(5);
   @$pb.TagNumber(6)
-  set extData($core.String v) { $_setString(5, v); }
+  set pluginType($core.int v) { $_setSignedInt32(5, v); }
   @$pb.TagNumber(6)
-  $core.bool hasExtData() => $_has(5);
+  $core.bool hasPluginType() => $_has(5);
   @$pb.TagNumber(6)
-  void clearExtData() => clearField(6);
+  void clearPluginType() => clearField(6);
 
   @$pb.TagNumber(7)
-  $core.int get pluginType => $_getIZ(6);
+  $core.String get data => $_getSZ(6);
   @$pb.TagNumber(7)
-  set pluginType($core.int v) { $_setSignedInt32(6, v); }
+  set data($core.String v) { $_setString(6, v); }
   @$pb.TagNumber(7)
-  $core.bool hasPluginType() => $_has(6);
+  $core.bool hasData() => $_has(6);
   @$pb.TagNumber(7)
-  void clearPluginType() => clearField(7);
+  void clearData() => clearField(7);
 }
 
 class CreateViewParams extends $pb.GeneratedMessage {
@@ -409,10 +409,9 @@ class CreateViewParams extends $pb.GeneratedMessage {
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
     ..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
-    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
-    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
-    ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
-    ..a<$core.int>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
+    ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
+    ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
+    ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
     ..hasRequiredFields = false
   ;
 
@@ -423,7 +422,6 @@ class CreateViewParams extends $pb.GeneratedMessage {
     $core.String? desc,
     $core.String? thumbnail,
     ViewDataType? dataType,
-    $core.String? extData,
     $core.String? viewId,
     $core.String? data,
     $core.int? pluginType,
@@ -444,9 +442,6 @@ class CreateViewParams extends $pb.GeneratedMessage {
     if (dataType != null) {
       _result.dataType = dataType;
     }
-    if (extData != null) {
-      _result.extData = extData;
-    }
     if (viewId != null) {
       _result.viewId = viewId;
     }
@@ -525,40 +520,31 @@ class CreateViewParams extends $pb.GeneratedMessage {
   void clearDataType() => clearField(5);
 
   @$pb.TagNumber(6)
-  $core.String get extData => $_getSZ(5);
+  $core.String get viewId => $_getSZ(5);
   @$pb.TagNumber(6)
-  set extData($core.String v) { $_setString(5, v); }
+  set viewId($core.String v) { $_setString(5, v); }
   @$pb.TagNumber(6)
-  $core.bool hasExtData() => $_has(5);
+  $core.bool hasViewId() => $_has(5);
   @$pb.TagNumber(6)
-  void clearExtData() => clearField(6);
+  void clearViewId() => clearField(6);
 
   @$pb.TagNumber(7)
-  $core.String get viewId => $_getSZ(6);
+  $core.String get data => $_getSZ(6);
   @$pb.TagNumber(7)
-  set viewId($core.String v) { $_setString(6, v); }
+  set data($core.String v) { $_setString(6, v); }
   @$pb.TagNumber(7)
-  $core.bool hasViewId() => $_has(6);
+  $core.bool hasData() => $_has(6);
   @$pb.TagNumber(7)
-  void clearViewId() => clearField(7);
+  void clearData() => clearField(7);
 
   @$pb.TagNumber(8)
-  $core.String get data => $_getSZ(7);
+  $core.int get pluginType => $_getIZ(7);
   @$pb.TagNumber(8)
-  set data($core.String v) { $_setString(7, v); }
+  set pluginType($core.int v) { $_setSignedInt32(7, v); }
   @$pb.TagNumber(8)
-  $core.bool hasData() => $_has(7);
+  $core.bool hasPluginType() => $_has(7);
   @$pb.TagNumber(8)
-  void clearData() => clearField(8);
-
-  @$pb.TagNumber(9)
-  $core.int get pluginType => $_getIZ(8);
-  @$pb.TagNumber(9)
-  set pluginType($core.int v) { $_setSignedInt32(8, v); }
-  @$pb.TagNumber(9)
-  $core.bool hasPluginType() => $_has(8);
-  @$pb.TagNumber(9)
-  void clearPluginType() => clearField(9);
+  void clearPluginType() => clearField(8);
 }
 
 class ViewId extends $pb.GeneratedMessage {

+ 7 - 8
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart

@@ -59,8 +59,8 @@ const CreateViewPayload$json = const {
     const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
     const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'},
     const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'},
-    const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'},
-    const {'1': 'plugin_type', '3': 7, '4': 1, '5': 5, '10': 'pluginType'},
+    const {'1': 'plugin_type', '3': 6, '4': 1, '5': 5, '10': 'pluginType'},
+    const {'1': 'data', '3': 7, '4': 1, '5': 9, '10': 'data'},
   ],
   '8': const [
     const {'1': 'one_of_thumbnail'},
@@ -68,7 +68,7 @@ const CreateViewPayload$json = const {
 };
 
 /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIfCgtwbHVnaW5fdHlwZRgHIAEoBVIKcGx1Z2luVHlwZUISChBvbmVfb2ZfdGh1bWJuYWls');
+final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIfCgtwbHVnaW5fdHlwZRgGIAEoBVIKcGx1Z2luVHlwZRISCgRkYXRhGAcgASgJUgRkYXRhQhIKEG9uZV9vZl90aHVtYm5haWw=');
 @$core.Deprecated('Use createViewParamsDescriptor instead')
 const CreateViewParams$json = const {
   '1': 'CreateViewParams',
@@ -78,15 +78,14 @@ const CreateViewParams$json = const {
     const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
     const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'},
     const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'},
-    const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'},
-    const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'},
-    const {'1': 'data', '3': 8, '4': 1, '5': 9, '10': 'data'},
-    const {'1': 'plugin_type', '3': 9, '4': 1, '5': 5, '10': 'pluginType'},
+    const {'1': 'view_id', '3': 6, '4': 1, '5': 9, '10': 'viewId'},
+    const {'1': 'data', '3': 7, '4': 1, '5': 9, '10': 'data'},
+    const {'1': 'plugin_type', '3': 8, '4': 1, '5': 5, '10': 'pluginType'},
   ],
 };
 
 /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YRIfCgtwbHVnaW5fdHlwZRgJIAEoBVIKcGx1Z2luVHlwZQ==');
+final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIXCgd2aWV3X2lkGAYgASgJUgZ2aWV3SWQSEgoEZGF0YRgHIAEoCVIEZGF0YRIfCgtwbHVnaW5fdHlwZRgIIAEoBVIKcGx1Z2luVHlwZQ==');
 @$core.Deprecated('Use viewIdDescriptor instead')
 const ViewId$json = const {
   '1': 'ViewId',

+ 174 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart

@@ -9,6 +9,8 @@ import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
+import 'meta.pbenum.dart' as $0;
+
 class Grid extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Grid', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
@@ -72,6 +74,137 @@ class Grid extends $pb.GeneratedMessage {
   $core.List<RowOrder> get rowOrders => $_getList(2);
 }
 
+class Field extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Field', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
+    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
+    ..e<$0.FieldType>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values)
+    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
+    ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
+    ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false
+  ;
+
+  Field._() : super();
+  factory Field({
+    $core.String? id,
+    $core.String? name,
+    $core.String? desc,
+    $0.FieldType? fieldType,
+    $core.bool? frozen,
+    $core.bool? visibility,
+    $core.int? width,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (name != null) {
+      _result.name = name;
+    }
+    if (desc != null) {
+      _result.desc = desc;
+    }
+    if (fieldType != null) {
+      _result.fieldType = fieldType;
+    }
+    if (frozen != null) {
+      _result.frozen = frozen;
+    }
+    if (visibility != null) {
+      _result.visibility = visibility;
+    }
+    if (width != null) {
+      _result.width = width;
+    }
+    return _result;
+  }
+  factory Field.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Field.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  Field clone() => Field()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  Field copyWith(void Function(Field) updates) => super.copyWith((message) => updates(message as Field)) as Field; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static Field create() => Field._();
+  Field createEmptyInstance() => create();
+  static $pb.PbList<Field> createRepeated() => $pb.PbList<Field>();
+  @$core.pragma('dart2js:noInline')
+  static Field getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Field>(create);
+  static Field? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get id => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set id($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.String get name => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set name($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasName() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearName() => clearField(2);
+
+  @$pb.TagNumber(3)
+  $core.String get desc => $_getSZ(2);
+  @$pb.TagNumber(3)
+  set desc($core.String v) { $_setString(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasDesc() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearDesc() => clearField(3);
+
+  @$pb.TagNumber(4)
+  $0.FieldType get fieldType => $_getN(3);
+  @$pb.TagNumber(4)
+  set fieldType($0.FieldType v) { setField(4, v); }
+  @$pb.TagNumber(4)
+  $core.bool hasFieldType() => $_has(3);
+  @$pb.TagNumber(4)
+  void clearFieldType() => clearField(4);
+
+  @$pb.TagNumber(5)
+  $core.bool get frozen => $_getBF(4);
+  @$pb.TagNumber(5)
+  set frozen($core.bool v) { $_setBool(4, v); }
+  @$pb.TagNumber(5)
+  $core.bool hasFrozen() => $_has(4);
+  @$pb.TagNumber(5)
+  void clearFrozen() => clearField(5);
+
+  @$pb.TagNumber(6)
+  $core.bool get visibility => $_getBF(5);
+  @$pb.TagNumber(6)
+  set visibility($core.bool v) { $_setBool(5, v); }
+  @$pb.TagNumber(6)
+  $core.bool hasVisibility() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearVisibility() => clearField(6);
+
+  @$pb.TagNumber(7)
+  $core.int get width => $_getIZ(6);
+  @$pb.TagNumber(7)
+  set width($core.int v) { $_setSignedInt32(6, v); }
+  @$pb.TagNumber(7)
+  $core.bool hasWidth() => $_has(6);
+  @$pb.TagNumber(7)
+  void clearWidth() => clearField(7);
+}
+
 class FieldOrder extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldOrder', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
@@ -119,6 +252,47 @@ class FieldOrder extends $pb.GeneratedMessage {
   void clearFieldId() => clearField(1);
 }
 
+class RepeatedField extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedField', createEmptyInstance: create)
+    ..pc<Field>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Field.create)
+    ..hasRequiredFields = false
+  ;
+
+  RepeatedField._() : super();
+  factory RepeatedField({
+    $core.Iterable<Field>? items,
+  }) {
+    final _result = create();
+    if (items != null) {
+      _result.items.addAll(items);
+    }
+    return _result;
+  }
+  factory RepeatedField.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RepeatedField.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+  'Will be removed in next major version')
+  RepeatedField clone() => RepeatedField()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RepeatedField copyWith(void Function(RepeatedField) updates) => super.copyWith((message) => updates(message as RepeatedField)) as RepeatedField; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RepeatedField create() => RepeatedField._();
+  RepeatedField createEmptyInstance() => create();
+  static $pb.PbList<RepeatedField> createRepeated() => $pb.PbList<RepeatedField>();
+  @$core.pragma('dart2js:noInline')
+  static RepeatedField getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedField>(create);
+  static RepeatedField? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.List<Field> get items => $_getList(0);
+}
+
 class RepeatedFieldOrder extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedFieldOrder', createEmptyInstance: create)
     ..pc<FieldOrder>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: FieldOrder.create)

+ 26 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart

@@ -20,6 +20,22 @@ const Grid$json = const {
 
 /// Descriptor for `Grid`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List gridDescriptor = $convert.base64Decode('CgRHcmlkEg4KAmlkGAEgASgJUgJpZBIuCgxmaWVsZF9vcmRlcnMYAiADKAsyCy5GaWVsZE9yZGVyUgtmaWVsZE9yZGVycxIoCgpyb3dfb3JkZXJzGAMgAygLMgkuUm93T3JkZXJSCXJvd09yZGVycw==');
+@$core.Deprecated('Use fieldDescriptor instead')
+const Field$json = const {
+  '1': 'Field',
+  '2': const [
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
+    const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'},
+    const {'1': 'field_type', '3': 4, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'},
+    const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'},
+    const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'},
+    const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'},
+  ],
+};
+
+/// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aA==');
 @$core.Deprecated('Use fieldOrderDescriptor instead')
 const FieldOrder$json = const {
   '1': 'FieldOrder',
@@ -30,6 +46,16 @@ const FieldOrder$json = const {
 
 /// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElk');
+@$core.Deprecated('Use repeatedFieldDescriptor instead')
+const RepeatedField$json = const {
+  '1': 'RepeatedField',
+  '2': const [
+    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Field', '10': 'items'},
+  ],
+};
+
+/// Descriptor for `RepeatedField`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List repeatedFieldDescriptor = $convert.base64Decode('Cg1SZXBlYXRlZEZpZWxkEhwKBWl0ZW1zGAEgAygLMgYuRmllbGRSBWl0ZW1z');
 @$core.Deprecated('Use repeatedFieldOrderDescriptor instead')
 const RepeatedFieldOrder$json = const {
   '1': 'RepeatedFieldOrder',

+ 16 - 57
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart

@@ -16,7 +16,7 @@ export 'meta.pbenum.dart';
 class GridMeta extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridMeta', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
-    ..pc<Field>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fields', $pb.PbFieldType.PM, subBuilder: Field.create)
+    ..pc<FieldMeta>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fields', $pb.PbFieldType.PM, subBuilder: FieldMeta.create)
     ..pc<GridBlock>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blocks', $pb.PbFieldType.PM, subBuilder: GridBlock.create)
     ..hasRequiredFields = false
   ;
@@ -24,7 +24,7 @@ class GridMeta extends $pb.GeneratedMessage {
   GridMeta._() : super();
   factory GridMeta({
     $core.String? gridId,
-    $core.Iterable<Field>? fields,
+    $core.Iterable<FieldMeta>? fields,
     $core.Iterable<GridBlock>? blocks,
   }) {
     final _result = create();
@@ -70,7 +70,7 @@ class GridMeta extends $pb.GeneratedMessage {
   void clearGridId() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.List<Field> get fields => $_getList(1);
+  $core.List<FieldMeta> get fields => $_getList(1);
 
   @$pb.TagNumber(3)
   $core.List<GridBlock> get blocks => $_getList(2);
@@ -206,8 +206,8 @@ class GridBlockMeta extends $pb.GeneratedMessage {
   $core.List<RowMeta> get rows => $_getList(1);
 }
 
-class Field extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Field', createEmptyInstance: create)
+class FieldMeta extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldMeta', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
@@ -219,8 +219,8 @@ class Field extends $pb.GeneratedMessage {
     ..hasRequiredFields = false
   ;
 
-  Field._() : super();
-  factory Field({
+  FieldMeta._() : super();
+  factory FieldMeta({
     $core.String? id,
     $core.String? name,
     $core.String? desc,
@@ -257,26 +257,26 @@ class Field extends $pb.GeneratedMessage {
     }
     return _result;
   }
-  factory Field.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory Field.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory FieldMeta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory FieldMeta.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
   'Will be removed in next major version')
-  Field clone() => Field()..mergeFromMessage(this);
+  FieldMeta clone() => FieldMeta()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  Field copyWith(void Function(Field) updates) => super.copyWith((message) => updates(message as Field)) as Field; // ignore: deprecated_member_use
+  FieldMeta copyWith(void Function(FieldMeta) updates) => super.copyWith((message) => updates(message as FieldMeta)) as FieldMeta; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static Field create() => Field._();
-  Field createEmptyInstance() => create();
-  static $pb.PbList<Field> createRepeated() => $pb.PbList<Field>();
+  static FieldMeta create() => FieldMeta._();
+  FieldMeta createEmptyInstance() => create();
+  static $pb.PbList<FieldMeta> createRepeated() => $pb.PbList<FieldMeta>();
   @$core.pragma('dart2js:noInline')
-  static Field getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Field>(create);
-  static Field? _defaultInstance;
+  static FieldMeta getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldMeta>(create);
+  static FieldMeta? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get id => $_getSZ(0);
@@ -587,47 +587,6 @@ class FieldChangeset extends $pb.GeneratedMessage {
   void clearTypeOptions() => clearField(8);
 }
 
-class RepeatedField extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedField', createEmptyInstance: create)
-    ..pc<Field>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Field.create)
-    ..hasRequiredFields = false
-  ;
-
-  RepeatedField._() : super();
-  factory RepeatedField({
-    $core.Iterable<Field>? items,
-  }) {
-    final _result = create();
-    if (items != null) {
-      _result.items.addAll(items);
-    }
-    return _result;
-  }
-  factory RepeatedField.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory RepeatedField.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-  'Will be removed in next major version')
-  RepeatedField clone() => RepeatedField()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  RepeatedField copyWith(void Function(RepeatedField) updates) => super.copyWith((message) => updates(message as RepeatedField)) as RepeatedField; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static RepeatedField create() => RepeatedField._();
-  RepeatedField createEmptyInstance() => create();
-  static $pb.PbList<RepeatedField> createRepeated() => $pb.PbList<RepeatedField>();
-  @$core.pragma('dart2js:noInline')
-  static RepeatedField getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedField>(create);
-  static RepeatedField? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.List<Field> get items => $_getList(0);
-}
-
 class AnyData extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AnyData', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeId')

+ 7 - 17
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart

@@ -28,13 +28,13 @@ const GridMeta$json = const {
   '1': 'GridMeta',
   '2': const [
     const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
-    const {'1': 'fields', '3': 2, '4': 3, '5': 11, '6': '.Field', '10': 'fields'},
+    const {'1': 'fields', '3': 2, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fields'},
     const {'1': 'blocks', '3': 3, '4': 3, '5': 11, '6': '.GridBlock', '10': 'blocks'},
   ],
 };
 
 /// Descriptor for `GridMeta`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSHgoGZmllbGRzGAIgAygLMgYuRmllbGRSBmZpZWxkcxIiCgZibG9ja3MYAyADKAsyCi5HcmlkQmxvY2tSBmJsb2Nrcw==');
+final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSIgoGZmllbGRzGAIgAygLMgouRmllbGRNZXRhUgZmaWVsZHMSIgoGYmxvY2tzGAMgAygLMgouR3JpZEJsb2NrUgZibG9ja3M=');
 @$core.Deprecated('Use gridBlockDescriptor instead')
 const GridBlock$json = const {
   '1': 'GridBlock',
@@ -58,9 +58,9 @@ const GridBlockMeta$json = const {
 
 /// Descriptor for `GridBlockMeta`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List gridBlockMetaDescriptor = $convert.base64Decode('Cg1HcmlkQmxvY2tNZXRhEhkKCGJsb2NrX2lkGAEgASgJUgdibG9ja0lkEhwKBHJvd3MYAiADKAsyCC5Sb3dNZXRhUgRyb3dz');
-@$core.Deprecated('Use fieldDescriptor instead')
-const Field$json = const {
-  '1': 'Field',
+@$core.Deprecated('Use fieldMetaDescriptor instead')
+const FieldMeta$json = const {
+  '1': 'FieldMeta',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
     const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
@@ -73,8 +73,8 @@ const Field$json = const {
   ],
 };
 
-/// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aBIhCgx0eXBlX29wdGlvbnMYCCABKAlSC3R5cGVPcHRpb25z');
+/// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSIQoMdHlwZV9vcHRpb25zGAggASgJUgt0eXBlT3B0aW9ucw==');
 @$core.Deprecated('Use fieldChangesetDescriptor instead')
 const FieldChangeset$json = const {
   '1': 'FieldChangeset',
@@ -101,16 +101,6 @@ const FieldChangeset$json = const {
 
 /// Descriptor for `FieldChangeset`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIUCgRuYW1lGAIgASgJSABSBG5hbWUSFAoEZGVzYxgDIAEoCUgBUgRkZXNjEisKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVIAlIJZmllbGRUeXBlEhgKBmZyb3plbhgFIAEoCEgDUgZmcm96ZW4SIAoKdmlzaWJpbGl0eRgGIAEoCEgEUgp2aXNpYmlsaXR5EhYKBXdpZHRoGAcgASgFSAVSBXdpZHRoEiMKDHR5cGVfb3B0aW9ucxgIIAEoCUgGUgt0eXBlT3B0aW9uc0INCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0ITChFvbmVfb2ZfZmllbGRfdHlwZUIPCg1vbmVfb2ZfZnJvemVuQhMKEW9uZV9vZl92aXNpYmlsaXR5Qg4KDG9uZV9vZl93aWR0aEIVChNvbmVfb2ZfdHlwZV9vcHRpb25z');
-@$core.Deprecated('Use repeatedFieldDescriptor instead')
-const RepeatedField$json = const {
-  '1': 'RepeatedField',
-  '2': const [
-    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Field', '10': 'items'},
-  ],
-};
-
-/// Descriptor for `RepeatedField`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List repeatedFieldDescriptor = $convert.base64Decode('Cg1SZXBlYXRlZEZpZWxkEhwKBWl0ZW1zGAEgAygLMgYuRmllbGRSBWl0ZW1z');
 @$core.Deprecated('Use anyDataDescriptor instead')
 const AnyData$json = const {
   '1': 'AnyData',

+ 1 - 1
frontend/rust-lib/flowy-block/tests/document/script.rs

@@ -26,7 +26,7 @@ impl TextBlockEditorTest {
     pub async fn new() -> Self {
         let sdk = FlowySDKTest::default();
         let _ = sdk.init_user().await;
-        let test = ViewTest::new_grid_view(&sdk).await;
+        let test = ViewTest::new_text_block_view(&sdk).await;
         let editor = sdk.text_block_manager.open_block(&test.view.id).await.unwrap();
         Self { sdk, editor }
     }

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

@@ -171,7 +171,6 @@ impl ViewController {
             data_type: view.data_type,
             data: delta_str,
             view_id: uuid(),
-            ext_data: view.ext_data,
             plugin_type: view.plugin_type,
         };
 

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

@@ -350,8 +350,8 @@ pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &st
         desc: desc.to_string(),
         thumbnail: None,
         data_type,
-        ext_data: "".to_string(),
         plugin_type: 0,
+        data: "".to_string(),
     };
     let view = FolderEventBuilder::new(sdk.clone())
         .event(CreateView)

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

@@ -1,7 +1,7 @@
 use crate::manager::GridManager;
 use flowy_error::FlowyError;
 use flowy_grid_data_model::entities::{
-    Cell, Grid, GridId, QueryFieldPayload, QueryRowPayload, RepeatedField, RepeatedRow,
+    Cell, Field, Grid, GridId, QueryFieldPayload, QueryRowPayload, RepeatedField, RepeatedRow,
 };
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::sync::Arc;
@@ -13,7 +13,7 @@ pub(crate) async fn get_grid_data_handler(
 ) -> DataResult<Grid, FlowyError> {
     let grid_id: GridId = data.into_inner();
     let editor = manager.open_grid(grid_id).await?;
-    let grid = editor.grid_data().await;
+    let grid = editor.grid_data().await?;
     data_result(grid)
 }
 
@@ -35,7 +35,12 @@ pub(crate) async fn get_fields_handler(
 ) -> DataResult<RepeatedField, FlowyError> {
     let payload: QueryFieldPayload = data.into_inner();
     let editor = manager.get_grid_editor(&payload.grid_id)?;
-    let repeated_field: RepeatedField = editor.get_fields(Some(payload.field_orders)).await?.into();
+    let field_metas = editor.get_field_metas(Some(payload.field_orders)).await?;
+    let repeated_field: RepeatedField = field_metas
+        .into_iter()
+        .map(|field_meta| Field::from(field_meta))
+        .collect::<Vec<_>>()
+        .into();
     data_result(repeated_field)
 }
 

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

@@ -9,9 +9,9 @@ macro_rules! impl_from_and_to_type_option {
 #[macro_export]
 macro_rules! impl_from_field_type_option {
     ($target: ident) => {
-        impl std::convert::From<&Field> for $target {
-            fn from(field: &Field) -> $target {
-                match serde_json::from_str(&field.type_options) {
+        impl std::convert::From<&FieldMeta> for $target {
+            fn from(field_meta: &FieldMeta) -> $target {
+                match serde_json::from_str(&field_meta.type_options) {
                     Ok(obj) => obj,
                     Err(err) => {
                         tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err);

+ 30 - 12
frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs

@@ -119,11 +119,11 @@ impl GridBlockMetaEditorManager {
         }
     }
 
-    pub(crate) async fn get_all_rows(&self, grid_blocks: Vec<GridBlock>) -> FlowyResult<Vec<RowMeta>> {
+    pub(crate) async fn get_all_rows(&self, grid_blocks: Vec<GridBlock>) -> FlowyResult<Vec<Arc<RowMeta>>> {
         let mut row_metas = vec![];
         for grid_block in grid_blocks {
             let editor = self.get_editor(&grid_block.id).await?;
-            let new_row_metas = editor.get_rows(None).await?;
+            let new_row_metas = editor.get_row_metas(None).await?;
             new_row_metas.iter().for_each(|row_meta| {
                 self.block_id_by_row_id
                     .insert(row_meta.id.clone(), row_meta.block_id.clone());
@@ -134,12 +134,23 @@ impl GridBlockMetaEditorManager {
         Ok(row_metas)
     }
 
-    pub(crate) async fn get_rows(&self, row_orders: &RepeatedRowOrder) -> FlowyResult<Vec<RowMeta>> {
+    pub(crate) async fn get_row_orders(&self, grid_blocks: Vec<GridBlock>) -> FlowyResult<Vec<RowOrder>> {
+        let mut row_orders = vec![];
+        for grid_block in grid_blocks {
+            let editor = self.get_editor(&grid_block.id).await?;
+            let row_metas = editor.get_row_metas(None).await?;
+            let block_row_orders = row_metas.iter().map(|row_meta| RowOrder::from(row_meta));
+            row_orders.extend(block_row_orders);
+        }
+        Ok(row_orders)
+    }
+
+    pub(crate) async fn get_rows(&self, row_orders: &RepeatedRowOrder) -> FlowyResult<Vec<Arc<RowMeta>>> {
         let row_ids_per_blocks = make_row_ids_per_block(row_orders);
         let mut row_metas = vec![];
         for row_ids_per_block in row_ids_per_blocks {
             let editor = self.get_editor(&row_ids_per_block.block_id).await?;
-            let new_row_metas = editor.get_rows(Some(row_ids_per_block.row_ids)).await?;
+            let new_row_metas = editor.get_row_metas(Some(row_ids_per_block.row_ids)).await?;
             new_row_metas.iter().for_each(|row_meta| {
                 self.block_id_by_row_id
                     .insert(row_meta.id.clone(), row_meta.block_id.clone());
@@ -234,14 +245,21 @@ impl ClientGridBlockMetaEditor {
         Ok(())
     }
 
-    pub async fn get_rows(&self, row_ids: Option<Vec<String>>) -> FlowyResult<Vec<RowMeta>> {
-        match row_ids {
-            None => Ok(self.meta_pad.read().await.all_rows()),
-            Some(row_ids) => {
-                let rows = self.meta_pad.read().await.get_rows(row_ids)?;
-                Ok(rows)
-            }
-        }
+    pub async fn get_row_metas(&self, row_ids: Option<Vec<String>>) -> FlowyResult<Vec<Arc<RowMeta>>> {
+        let row_metas = self.meta_pad.read().await.get_rows(row_ids)?;
+        Ok(row_metas)
+    }
+
+    pub async fn get_row_orders(&self) -> FlowyResult<Vec<RowOrder>> {
+        let row_orders = self
+            .meta_pad
+            .read()
+            .await
+            .get_rows(None)?
+            .iter()
+            .map(|row_meta| RowOrder::from(row_meta))
+            .collect::<Vec<RowOrder>>();
+        Ok(row_orders)
     }
 
     async fn modify<F>(&self, f: F) -> FlowyResult<()>

+ 14 - 14
frontend/rust-lib/flowy-grid/src/services/cell/description/checkbox_description.rs

@@ -1,8 +1,8 @@
 use crate::impl_from_and_to_type_option;
-use crate::services::row::StringifyCellData;
+use crate::services::row::CellDataSerde;
 use flowy_derive::ProtoBuf;
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 use serde::{Deserialize, Serialize};
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
@@ -12,13 +12,13 @@ pub struct CheckboxDescription {
 }
 impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox);
 
-impl StringifyCellData for CheckboxDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for CheckboxDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        let s = match string_to_bool(s) {
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        let s = match string_to_bool(data) {
             true => "1",
             false => "0",
         };
@@ -42,19 +42,19 @@ fn string_to_bool(bool_str: &str) -> bool {
 #[cfg(test)]
 mod tests {
     use crate::services::cell::CheckboxDescription;
-    use crate::services::row::StringifyCellData;
+    use crate::services::row::CellDataSerde;
 
     #[test]
     fn checkout_box_description_test() {
         let description = CheckboxDescription::default();
-        assert_eq!(description.str_to_cell_data("true").unwrap(), "1".to_owned());
-        assert_eq!(description.str_to_cell_data("1").unwrap(), "1".to_owned());
-        assert_eq!(description.str_to_cell_data("yes").unwrap(), "1".to_owned());
+        assert_eq!(description.serialize_cell_data("true").unwrap(), "1".to_owned());
+        assert_eq!(description.serialize_cell_data("1").unwrap(), "1".to_owned());
+        assert_eq!(description.serialize_cell_data("yes").unwrap(), "1".to_owned());
 
-        assert_eq!(description.str_to_cell_data("false").unwrap(), "0".to_owned());
-        assert_eq!(description.str_to_cell_data("no").unwrap(), "0".to_owned());
-        assert_eq!(description.str_to_cell_data("123").unwrap(), "0".to_owned());
+        assert_eq!(description.serialize_cell_data("false").unwrap(), "0".to_owned());
+        assert_eq!(description.serialize_cell_data("no").unwrap(), "0".to_owned());
+        assert_eq!(description.serialize_cell_data("123").unwrap(), "0".to_owned());
 
-        assert_eq!(description.str_from_cell_data("1".to_owned()), "1".to_owned());
+        assert_eq!(description.deserialize_cell_data("1".to_owned()), "1".to_owned());
     }
 }

+ 15 - 15
frontend/rust-lib/flowy-grid/src/services/cell/description/date_description.rs

@@ -1,11 +1,11 @@
 use crate::impl_from_and_to_type_option;
-use crate::services::row::StringifyCellData;
+use crate::services::row::CellDataSerde;
 
 use chrono::format::strftime::StrftimeItems;
 use chrono::NaiveDateTime;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 use serde::{Deserialize, Serialize};
 
 use strum_macros::EnumIter;
@@ -38,8 +38,8 @@ impl DateDescription {
     }
 }
 
-impl StringifyCellData for DateDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for DateDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         match data.parse::<i64>() {
             Ok(timestamp) => {
                 let native = NaiveDateTime::from_timestamp(timestamp, 0);
@@ -52,11 +52,11 @@ impl StringifyCellData for DateDescription {
         }
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        let timestamp = match s.parse::<i64>() {
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        let timestamp = match data.parse::<i64>() {
             Ok(timestamp) => timestamp,
             Err(e) => {
-                tracing::error!("Parse {} to i64 failed: {}", s, e);
+                tracing::error!("Parse {} to i64 failed: {}", data, e);
                 chrono::Utc::now().timestamp()
             }
         };
@@ -149,7 +149,7 @@ impl std::default::Default for TimeFormat {
 #[cfg(test)]
 mod tests {
     use crate::services::cell::{DateDescription, DateFormat, TimeFormat};
-    use crate::services::row::StringifyCellData;
+    use crate::services::row::CellDataSerde;
     use strum::IntoEnumIterator;
 
     #[test]
@@ -167,7 +167,7 @@ mod tests {
                     );
                     assert_eq!(
                         "Mar 14,2022 17:56".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
                 DateFormat::US => {
@@ -177,7 +177,7 @@ mod tests {
                     );
                     assert_eq!(
                         "2022/03/14 17:56".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
                 DateFormat::ISO => {
@@ -187,7 +187,7 @@ mod tests {
                     );
                     assert_eq!(
                         "2022-03-14 17:56".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
                 DateFormat::Local => {
@@ -197,7 +197,7 @@ mod tests {
                     );
                     assert_eq!(
                         "2022/03/14 17:56".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
             }
@@ -217,7 +217,7 @@ mod tests {
                     );
                     assert_eq!(
                         "Mar 14,2022 17:56".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
                 TimeFormat::TwelveHour => {
@@ -227,7 +227,7 @@ mod tests {
                     );
                     assert_eq!(
                         "Mar 14,2022 05:56:02 PM".to_owned(),
-                        description.str_from_cell_data("1647251762".to_owned())
+                        description.deserialize_cell_data("1647251762".to_owned())
                     );
                 }
             }
@@ -237,6 +237,6 @@ mod tests {
     #[test]
     fn date_description_invalid_data_test() {
         let description = DateDescription::default();
-        description.str_to_cell_data("he").unwrap();
+        description.serialize_cell_data("he").unwrap();
     }
 }

+ 40 - 22
frontend/rust-lib/flowy-grid/src/services/cell/description/number_description.rs

@@ -1,8 +1,8 @@
 use crate::impl_from_and_to_type_option;
-use crate::services::row::StringifyCellData;
+use crate::services::row::CellDataSerde;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 use lazy_static::lazy_static;
 use rust_decimal::prelude::Zero;
 use rust_decimal::Decimal;
@@ -119,8 +119,8 @@ impl NumberDescription {
     }
 }
 
-impl StringifyCellData for NumberDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for NumberDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         match self.format {
             NumberFormat::Number => data,
             NumberFormat::USD => self.money_from_str(&data, USD),
@@ -129,8 +129,8 @@ impl StringifyCellData for NumberDescription {
         }
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        Ok(self.strip_symbol(s))
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        Ok(self.strip_symbol(data))
     }
 }
 
@@ -145,30 +145,42 @@ fn make_strip_symbol() -> Vec<String> {
 #[cfg(test)]
 mod tests {
     use crate::services::cell::{NumberDescription, NumberFormat};
-    use crate::services::row::StringifyCellData;
+    use crate::services::row::CellDataSerde;
     use strum::IntoEnumIterator;
 
     #[test]
     fn number_description_test() {
         let mut description = NumberDescription::default();
-        assert_eq!(description.str_to_cell_data("¥18,443").unwrap(), "18443".to_owned());
-        assert_eq!(description.str_to_cell_data("$18,443").unwrap(), "18443".to_owned());
-        assert_eq!(description.str_to_cell_data("€18.443").unwrap(), "18443".to_owned());
+        assert_eq!(description.serialize_cell_data("¥18,443").unwrap(), "18443".to_owned());
+        assert_eq!(description.serialize_cell_data("$18,443").unwrap(), "18443".to_owned());
+        assert_eq!(description.serialize_cell_data("€18.443").unwrap(), "18443".to_owned());
 
         for format in NumberFormat::iter() {
             description.format = format;
             match format {
                 NumberFormat::Number => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "18443".to_owned()
+                    );
                 }
                 NumberFormat::USD => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "$18,443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "$18,443".to_owned()
+                    );
                 }
                 NumberFormat::CNY => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "¥18,443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "¥18,443".to_owned()
+                    );
                 }
                 NumberFormat::EUR => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "€18.443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "€18.443".to_owned()
+                    );
                 }
             }
         }
@@ -183,23 +195,26 @@ mod tests {
             description.format = format;
             match format {
                 NumberFormat::Number => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "18443".to_owned()
+                    );
                 }
                 NumberFormat::USD => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "$1,844.3".to_owned()
                     );
                 }
                 NumberFormat::CNY => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "¥1,844.3".to_owned()
                     );
                 }
                 NumberFormat::EUR => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "€1.844,3".to_owned()
                     );
                 }
@@ -216,23 +231,26 @@ mod tests {
             description.format = format;
             match format {
                 NumberFormat::Number => {
-                    assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
+                    assert_eq!(
+                        description.deserialize_cell_data("18443".to_owned()),
+                        "18443".to_owned()
+                    );
                 }
                 NumberFormat::USD => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "-$18,443".to_owned()
                     );
                 }
                 NumberFormat::CNY => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "-¥18,443".to_owned()
                     );
                 }
                 NumberFormat::EUR => {
                     assert_eq!(
-                        description.str_from_cell_data("18443".to_owned()),
+                        description.deserialize_cell_data("18443".to_owned()),
                         "-€18.443".to_owned()
                     );
                 }

+ 13 - 13
frontend/rust-lib/flowy-grid/src/services/cell/description/selection_description.rs

@@ -1,9 +1,9 @@
 use crate::impl_from_and_to_type_option;
-use crate::services::row::StringifyCellData;
+use crate::services::row::CellDataSerde;
 use crate::services::util::*;
 use flowy_derive::ProtoBuf;
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 use serde::{Deserialize, Serialize};
 
 // Single select
@@ -17,13 +17,13 @@ pub struct SingleSelectDescription {
 }
 impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect);
 
-impl StringifyCellData for SingleSelectDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for SingleSelectDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        Ok(select_option_id_from_data(s.to_owned(), true))
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        Ok(select_option_id_from_data(data.to_owned(), true))
     }
 }
 
@@ -37,13 +37,13 @@ pub struct MultiSelectDescription {
     pub disable_color: bool,
 }
 impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect);
-impl StringifyCellData for MultiSelectDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for MultiSelectDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        Ok(select_option_id_from_data(s.to_owned(), false))
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        Ok(select_option_id_from_data(data.to_owned(), false))
     }
 }
 
@@ -84,14 +84,14 @@ impl SelectOption {
 #[cfg(test)]
 mod tests {
     use crate::services::cell::{MultiSelectDescription, SingleSelectDescription};
-    use crate::services::row::StringifyCellData;
+    use crate::services::row::CellDataSerde;
 
     #[test]
     fn selection_description_test() {
         let description = SingleSelectDescription::default();
-        assert_eq!(description.str_to_cell_data("1,2,3").unwrap(), "1".to_owned());
+        assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1".to_owned());
 
         let description = MultiSelectDescription::default();
-        assert_eq!(description.str_to_cell_data("1,2,3").unwrap(), "1,2,3".to_owned());
+        assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1,2,3".to_owned());
     }
 }

+ 6 - 6
frontend/rust-lib/flowy-grid/src/services/cell/description/text_description.rs

@@ -1,9 +1,9 @@
 use crate::impl_from_and_to_type_option;
-use crate::services::row::StringifyCellData;
+use crate::services::row::CellDataSerde;
 
 use flowy_derive::ProtoBuf;
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 use serde::{Deserialize, Serialize};
 
 #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
@@ -13,12 +13,12 @@ pub struct RichTextDescription {
 }
 impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText);
 
-impl StringifyCellData for RichTextDescription {
-    fn str_from_cell_data(&self, data: String) -> String {
+impl CellDataSerde for RichTextDescription {
+    fn deserialize_cell_data(&self, data: String) -> String {
         data
     }
 
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
-        Ok(s.to_owned())
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
+        Ok(data.to_owned())
     }
 }

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

@@ -1,55 +1,55 @@
-use flowy_grid_data_model::entities::{Field, FieldType};
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
 
 pub struct FieldBuilder {
-    field: Field,
+    field_meta: FieldMeta,
     type_options_builder: Box<dyn TypeOptionsBuilder>,
 }
 
 impl FieldBuilder {
     pub fn new<T: TypeOptionsBuilder + 'static>(type_options_builder: T) -> Self {
-        let field = Field::new("Name", "", FieldType::RichText);
+        let field_meta = FieldMeta::new("Name", "", FieldType::RichText);
         Self {
-            field,
+            field_meta,
             type_options_builder: Box::new(type_options_builder),
         }
     }
 
     pub fn name(mut self, name: &str) -> Self {
-        self.field.name = name.to_owned();
+        self.field_meta.name = name.to_owned();
         self
     }
 
     pub fn desc(mut self, desc: &str) -> Self {
-        self.field.desc = desc.to_owned();
+        self.field_meta.desc = desc.to_owned();
         self
     }
 
     pub fn field_type(mut self, field_type: FieldType) -> Self {
-        self.field.field_type = field_type;
+        self.field_meta.field_type = field_type;
         self
     }
 
     pub fn visibility(mut self, visibility: bool) -> Self {
-        self.field.visibility = visibility;
+        self.field_meta.visibility = visibility;
         self
     }
 
     pub fn width(mut self, width: i32) -> Self {
-        self.field.width = width;
+        self.field_meta.width = width;
         self
     }
 
     pub fn frozen(mut self, frozen: bool) -> Self {
-        self.field.frozen = frozen;
+        self.field_meta.frozen = frozen;
         self
     }
 
-    pub fn build(mut self) -> Field {
-        assert_eq!(self.field.field_type, self.type_options_builder.field_type());
+    pub fn build(mut self) -> FieldMeta {
+        assert_eq!(self.field_meta.field_type, self.type_options_builder.field_type());
 
         let type_options = self.type_options_builder.build();
-        self.field.type_options = type_options;
-        self.field
+        self.field_meta.type_options = type_options;
+        self.field_meta
     }
 }
 

+ 22 - 15
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -7,7 +7,7 @@ use flowy_collaboration::entities::revision::Revision;
 use flowy_collaboration::util::make_delta_from_revisions;
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::entities::{
-    CellMetaChangeset, Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder,
+    CellMetaChangeset, Field, FieldChangeset, FieldMeta, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder,
     RepeatedRowOrder, Row, RowMeta, RowMetaChangeset,
 };
 use std::collections::HashMap;
@@ -56,8 +56,8 @@ impl ClientGridEditor {
         }))
     }
 
-    pub async fn create_field(&self, field: Field) -> FlowyResult<()> {
-        let _ = self.modify(|grid| Ok(grid.create_field(field)?)).await?;
+    pub async fn create_field(&self, field_meta: FieldMeta) -> FlowyResult<()> {
+        let _ = self.modify(|grid| Ok(grid.create_field(field_meta)?)).await?;
         Ok(())
     }
 
@@ -82,9 +82,9 @@ impl ClientGridEditor {
     }
 
     pub async fn create_row(&self) -> FlowyResult<()> {
-        let fields = self.grid_meta_pad.read().await.get_fields(None)?;
+        let field_metas = self.grid_meta_pad.read().await.get_field_metas(None)?;
         let block_id = self.last_block_id().await?;
-        let row = row_meta_from_context(&block_id, CreateRowContextBuilder::new(&fields).build());
+        let row = row_meta_from_context(&block_id, CreateRowContextBuilder::new(&field_metas).build());
         let row_count = self.block_meta_manager.create_row(row).await?;
         let changeset = GridBlockChangeset::from_row_count(&block_id, row_count);
         let _ = self.update_block(changeset).await?;
@@ -119,12 +119,12 @@ impl ClientGridEditor {
     }
 
     pub async fn get_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<Row>> {
-        let row_metas = self.get_row_metas(&row_orders).await?;
-        let fields = self.grid_meta_pad.read().await.get_fields(None)?;
+        let row_metas = self.get_row_metas(row_orders.as_ref()).await?;
+        let field_meta = self.grid_meta_pad.read().await.get_field_metas(None)?;
         match row_orders {
-            None => Ok(make_rows(&fields, row_metas)),
+            None => Ok(make_rows(&field_meta, row_metas)),
             Some(row_orders) => {
-                let mut row_map: HashMap<String, Row> = make_row_by_row_id(&fields, row_metas);
+                let mut row_map: HashMap<String, Row> = make_row_by_row_id(&field_meta, row_metas);
                 let rows = row_orders
                     .iter()
                     .flat_map(|row_order| row_map.remove(&row_order.row_id))
@@ -134,7 +134,7 @@ impl ClientGridEditor {
         }
     }
 
-    pub async fn get_row_metas(&self, row_orders: &Option<RepeatedRowOrder>) -> FlowyResult<Vec<RowMeta>> {
+    pub async fn get_row_metas(&self, row_orders: Option<&RepeatedRowOrder>) -> FlowyResult<Vec<Arc<RowMeta>>> {
         match row_orders {
             None => {
                 let grid_blocks = self.grid_meta_pad.read().await.get_blocks();
@@ -156,13 +156,20 @@ impl ClientGridEditor {
         Ok(())
     }
 
-    pub async fn grid_data(&self) -> Grid {
-        todo!()
+    pub async fn grid_data(&self) -> FlowyResult<Grid> {
+        let field_orders = self.grid_meta_pad.read().await.get_field_orders();
+        let grid_blocks = self.grid_meta_pad.read().await.get_blocks();
+        let row_orders = self.block_meta_manager.get_row_orders(grid_blocks).await?;
+        Ok(Grid {
+            id: self.grid_id.clone(),
+            field_orders,
+            row_orders,
+        })
     }
 
-    pub async fn get_fields(&self, field_orders: Option<RepeatedFieldOrder>) -> FlowyResult<Vec<Field>> {
-        let fields = self.grid_meta_pad.read().await.get_fields(field_orders)?;
-        Ok(fields)
+    pub async fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> FlowyResult<Vec<FieldMeta>> {
+        let field_meta = self.grid_meta_pad.read().await.get_field_metas(field_orders)?;
+        Ok(field_meta)
     }
 
     pub async fn get_blocks(&self) -> FlowyResult<Vec<GridBlock>> {

+ 32 - 0
frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs

@@ -0,0 +1,32 @@
+use crate::services::cell::*;
+use flowy_error::FlowyError;
+use flowy_grid_data_model::entities::{FieldMeta, FieldType};
+
+pub trait CellDataSerde {
+    fn deserialize_cell_data(&self, data: String) -> String;
+    fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError>;
+}
+
+#[allow(dead_code)]
+pub fn serialize_cell_data(data: &str, field: &FieldMeta) -> Result<String, FlowyError> {
+    match field.field_type {
+        FieldType::RichText => RichTextDescription::from(field).serialize_cell_data(data),
+        FieldType::Number => NumberDescription::from(field).serialize_cell_data(data),
+        FieldType::DateTime => DateDescription::from(field).serialize_cell_data(data),
+        FieldType::SingleSelect => SingleSelectDescription::from(field).serialize_cell_data(data),
+        FieldType::MultiSelect => MultiSelectDescription::from(field).serialize_cell_data(data),
+        FieldType::Checkbox => CheckboxDescription::from(field).serialize_cell_data(data),
+    }
+}
+
+pub fn deserialize_cell_data(data: String, field: &FieldMeta) -> Result<String, FlowyError> {
+    let s = match field.field_type {
+        FieldType::RichText => RichTextDescription::from(field).deserialize_cell_data(data),
+        FieldType::Number => NumberDescription::from(field).deserialize_cell_data(data),
+        FieldType::DateTime => DateDescription::from(field).deserialize_cell_data(data),
+        FieldType::SingleSelect => SingleSelectDescription::from(field).deserialize_cell_data(data),
+        FieldType::MultiSelect => MultiSelectDescription::from(field).deserialize_cell_data(data),
+        FieldType::Checkbox => CheckboxDescription::from(field).deserialize_cell_data(data),
+    };
+    Ok(s)
+}

+ 0 - 33
frontend/rust-lib/flowy-grid/src/services/row/cell_stringify.rs

@@ -1,33 +0,0 @@
-use crate::services::cell::*;
-use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{Field, FieldType};
-
-pub trait StringifyCellData {
-    fn str_from_cell_data(&self, data: String) -> String;
-    fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError>;
-}
-
-#[allow(dead_code)]
-pub fn stringify_serialize(field: &Field, s: &str) -> Result<String, FlowyError> {
-    match field.field_type {
-        FieldType::RichText => RichTextDescription::from(field).str_to_cell_data(s),
-        FieldType::Number => NumberDescription::from(field).str_to_cell_data(s),
-        FieldType::DateTime => DateDescription::from(field).str_to_cell_data(s),
-        FieldType::SingleSelect => SingleSelectDescription::from(field).str_to_cell_data(s),
-        FieldType::MultiSelect => MultiSelectDescription::from(field).str_to_cell_data(s),
-        FieldType::Checkbox => CheckboxDescription::from(field).str_to_cell_data(s),
-    }
-}
-
-pub(crate) fn stringify_deserialize(data: String, field: &Field) -> Result<String, FlowyError> {
-    // let _ = check_type_id(&data, field)?;
-    let s = match field.field_type {
-        FieldType::RichText => RichTextDescription::from(field).str_from_cell_data(data),
-        FieldType::Number => NumberDescription::from(field).str_from_cell_data(data),
-        FieldType::DateTime => DateDescription::from(field).str_from_cell_data(data),
-        FieldType::SingleSelect => SingleSelectDescription::from(field).str_from_cell_data(data),
-        FieldType::MultiSelect => MultiSelectDescription::from(field).str_from_cell_data(data),
-        FieldType::Checkbox => CheckboxDescription::from(field).str_from_cell_data(data),
-    };
-    Ok(s)
-}

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

@@ -1,7 +1,7 @@
-mod cell_stringify;
+mod cell_data_serde;
 mod row_builder;
 mod row_loader;
 
-pub use cell_stringify::*;
+pub use cell_data_serde::*;
 pub use row_builder::*;
 pub(crate) use row_loader::*;

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

@@ -1,14 +1,14 @@
-use flowy_grid_data_model::entities::{CellMeta, Field, RowMeta, DEFAULT_ROW_HEIGHT};
+use flowy_grid_data_model::entities::{CellMeta, FieldMeta, RowMeta, DEFAULT_ROW_HEIGHT};
 use std::collections::HashMap;
 
 pub struct CreateRowContextBuilder<'a> {
     #[allow(dead_code)]
-    fields: &'a [Field],
+    fields: &'a [FieldMeta],
     ctx: CreateRowContext,
 }
 
 impl<'a> CreateRowContextBuilder<'a> {
-    pub fn new(fields: &'a [Field]) -> Self {
+    pub fn new(fields: &'a [FieldMeta]) -> Self {
         let ctx = CreateRowContext {
             row_id: uuid::Uuid::new_v4().to_string(),
             cell_by_field_id: Default::default(),

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

@@ -1,7 +1,8 @@
-use crate::services::row::stringify_deserialize;
-use flowy_grid_data_model::entities::{Cell, CellMeta, Field, Row, RowMeta, RowOrder};
+use crate::services::row::deserialize_cell_data;
+use flowy_grid_data_model::entities::{Cell, CellMeta, FieldMeta, Row, RowMeta, RowOrder};
 use rayon::iter::{IntoParallelIterator, ParallelIterator};
 use std::collections::HashMap;
+use std::sync::Arc;
 
 pub(crate) struct RowIdsPerBlock {
     pub(crate) block_id: String,
@@ -21,15 +22,16 @@ pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec<RowIdsPerBl
     map.into_values().collect::<Vec<_>>()
 }
 
-pub(crate) fn make_rows(fields: &[Field], row_metas: Vec<RowMeta>) -> Vec<Row> {
+pub(crate) fn make_rows(fields: &[FieldMeta], row_metas: Vec<Arc<RowMeta>>) -> Vec<Row> {
     let field_map = fields
         .iter()
         .map(|field| (&field.id, field))
-        .collect::<HashMap<&String, &Field>>();
+        .collect::<HashMap<&String, &FieldMeta>>();
 
-    let make_row = |row_meta: RowMeta| {
+    let make_row = |row_meta: Arc<RowMeta>| {
         let cell_by_field_id = row_meta
             .cell_by_field_id
+            .clone()
             .into_par_iter()
             .flat_map(|(field_id, raw_cell)| make_cell(&field_map, field_id, raw_cell))
             .collect::<HashMap<String, Cell>>();
@@ -45,9 +47,9 @@ pub(crate) fn make_rows(fields: &[Field], row_metas: Vec<RowMeta>) -> Vec<Row> {
 }
 
 #[inline(always)]
-fn make_cell(field_map: &HashMap<&String, &Field>, field_id: String, raw_cell: CellMeta) -> Option<(String, Cell)> {
-    let field = field_map.get(&field_id)?;
-    match stringify_deserialize(raw_cell.data, field) {
+fn make_cell(field_map: &HashMap<&String, &FieldMeta>, field_id: String, raw_cell: CellMeta) -> Option<(String, Cell)> {
+    let field_meta = field_map.get(&field_id)?;
+    match deserialize_cell_data(raw_cell.data, field_meta) {
         Ok(content) => {
             let cell = Cell::new(&field_id, content);
             Some((field_id, cell))
@@ -59,15 +61,16 @@ fn make_cell(field_map: &HashMap<&String, &Field>, field_id: String, raw_cell: C
     }
 }
 
-pub(crate) fn make_row_by_row_id(fields: &[Field], row_metas: Vec<RowMeta>) -> HashMap<String, Row> {
+pub(crate) fn make_row_by_row_id(fields: &[FieldMeta], row_metas: Vec<Arc<RowMeta>>) -> HashMap<String, Row> {
     let field_map = fields
         .iter()
         .map(|field| (&field.id, field))
-        .collect::<HashMap<&String, &Field>>();
+        .collect::<HashMap<&String, &FieldMeta>>();
 
-    let make_row = |row_meta: RowMeta| {
+    let make_row = |row_meta: Arc<RowMeta>| {
         let cell_by_field_id = row_meta
             .cell_by_field_id
+            .clone()
             .into_par_iter()
             .flat_map(|(field_id, raw_cell)| make_cell(&field_map, field_id, raw_cell))
             .collect::<HashMap<String, Cell>>();

+ 27 - 28
frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs

@@ -1,7 +1,7 @@
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use flowy_grid::services::cell::*;
-use flowy_grid::services::row::{CreateRowContextBuilder, StringifyCellData};
+use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataSerde, CreateRowContextBuilder};
 use flowy_grid_data_model::entities::{FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMetaChangeset};
 
 #[tokio::test]
@@ -17,19 +17,19 @@ async fn grid_create_field() {
     let scripts = vec![
         AssertFieldCount(2),
         CreateField {
-            field: text_field.clone(),
+            field_meta: text_field.clone(),
         },
         AssertFieldEqual {
             field_index: 2,
-            field: text_field,
+            field_meta: text_field,
         },
         AssertFieldCount(3),
         CreateField {
-            field: single_select_field.clone(),
+            field_meta: single_select_field.clone(),
         },
         AssertFieldEqual {
             field_index: 3,
-            field: single_select_field,
+            field_meta: single_select_field,
         },
         AssertFieldCount(4),
     ];
@@ -42,11 +42,11 @@ async fn grid_create_duplicate_field() {
     let scripts = vec![
         AssertFieldCount(2),
         CreateField {
-            field: text_field.clone(),
+            field_meta: text_field.clone(),
         },
         AssertFieldCount(3),
         CreateField {
-            field: text_field.clone(),
+            field_meta: text_field.clone(),
         },
         AssertFieldCount(3),
     ];
@@ -69,12 +69,12 @@ async fn grid_update_field_with_empty_change() {
 
     let scripts = vec![
         CreateField {
-            field: single_select_field.clone(),
+            field_meta: single_select_field.clone(),
         },
         UpdateField { changeset },
         AssertFieldEqual {
             field_index: 2,
-            field: single_select_field,
+            field_meta: single_select_field,
         },
     ];
     GridEditorTest::new().await.run_scripts(scripts).await;
@@ -105,12 +105,12 @@ async fn grid_update_field() {
 
     let scripts = vec![
         CreateField {
-            field: single_select_field.clone(),
+            field_meta: single_select_field.clone(),
         },
         UpdateField { changeset },
         AssertFieldEqual {
             field_index: 2,
-            field: cloned_field,
+            field_meta: cloned_field,
         },
         AssertGridMetaPad,
     ];
@@ -122,10 +122,10 @@ async fn grid_delete_field() {
     let text_field = create_text_field();
     let scripts = vec![
         CreateField {
-            field: text_field.clone(),
+            field_meta: text_field.clone(),
         },
         AssertFieldCount(3),
-        DeleteField { field: text_field },
+        DeleteField { field_meta: text_field },
         AssertFieldCount(2),
     ];
     GridEditorTest::new().await.run_scripts(scripts).await;
@@ -177,7 +177,7 @@ async fn grid_create_row() {
 #[tokio::test]
 async fn grid_create_row2() {
     let mut test = GridEditorTest::new().await;
-    let create_row_context = CreateRowContextBuilder::new(&test.fields).build();
+    let create_row_context = CreateRowContextBuilder::new(&test.field_metas).build();
     let scripts = vec![
         AssertRowCount(3),
         CreateRow {
@@ -191,7 +191,7 @@ async fn grid_create_row2() {
 #[tokio::test]
 async fn grid_update_row() {
     let mut test = GridEditorTest::new().await;
-    let context = CreateRowContextBuilder::new(&test.fields).build();
+    let context = CreateRowContextBuilder::new(&test.field_metas).build();
     let changeset = RowMetaChangeset {
         row_id: context.row_id.clone(),
         height: None,
@@ -214,8 +214,8 @@ async fn grid_update_row() {
 #[tokio::test]
 async fn grid_delete_row() {
     let mut test = GridEditorTest::new().await;
-    let context_1 = CreateRowContextBuilder::new(&test.fields).build();
-    let context_2 = CreateRowContextBuilder::new(&test.fields).build();
+    let context_1 = CreateRowContextBuilder::new(&test.field_metas).build();
+    let context_2 = CreateRowContextBuilder::new(&test.field_metas).build();
     let row_ids = vec![context_1.row_id.clone(), context_2.row_id.clone()];
     let scripts = vec![
         AssertRowCount(3),
@@ -240,26 +240,26 @@ async fn grid_delete_row() {
 #[tokio::test]
 async fn grid_update_cell() {
     let mut test = GridEditorTest::new().await;
-    let mut builder = CreateRowContextBuilder::new(&test.fields);
-    for field in &test.fields {
+    let mut builder = CreateRowContextBuilder::new(&test.field_metas);
+    for field in &test.field_metas {
         match field.field_type {
             FieldType::RichText => {
-                builder = builder.add_cell(&field.id, "hello world".to_owned());
+                let data = serialize_cell_data("hello world", field).unwrap();
+                builder = builder.add_cell(&field.id, data);
             }
             FieldType::Number => {
-                let description = NumberDescription::from(field);
-                let data = description.str_to_cell_data("¥18,443").unwrap();
+                let data = serialize_cell_data("¥18,443", field).unwrap();
                 builder = builder.add_cell(&field.id, data);
             }
             FieldType::DateTime => {
-                let description = DateDescription::from(field);
-                let data = description.str_to_cell_data("1647251762").unwrap();
+                let data = serialize_cell_data("1647251762", field).unwrap();
                 builder = builder.add_cell(&field.id, data);
             }
             FieldType::SingleSelect => {
                 let description = SingleSelectDescription::from(field);
                 let options = description.options.first().unwrap();
-                let data = description.str_to_cell_data(&options.id).unwrap();
+
+                let data = description.serialize_cell_data(&options.id).unwrap();
                 builder = builder.add_cell(&field.id, data);
             }
             FieldType::MultiSelect => {
@@ -270,12 +270,11 @@ async fn grid_update_cell() {
                     .map(|option| option.id.clone())
                     .collect::<Vec<_>>()
                     .join(",");
-                let data = description.str_to_cell_data(&options).unwrap();
+                let data = description.serialize_cell_data(&options).unwrap();
                 builder = builder.add_cell(&field.id, data);
             }
             FieldType::Checkbox => {
-                let description = CheckboxDescription::from(field);
-                let data = description.str_to_cell_data("false").unwrap();
+                let data = serialize_cell_data("false", field).unwrap();
                 builder = builder.add_cell(&field.id, data);
             }
         }

+ 32 - 26
frontend/rust-lib/flowy-grid/tests/grid/script.rs

@@ -3,7 +3,7 @@ use flowy_grid::services::field::*;
 use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
 use flowy_grid::services::row::CreateRowContext;
 use flowy_grid_data_model::entities::{
-    CellMetaChangeset, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMeta, RowMetaChangeset,
+    CellMetaChangeset, FieldChangeset, FieldMeta, FieldType, GridBlock, GridBlockChangeset, RowMeta, RowMetaChangeset,
 };
 use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
 use flowy_test::helper::ViewTest;
@@ -14,18 +14,18 @@ use tokio::time::sleep;
 
 pub enum EditorScript {
     CreateField {
-        field: Field,
+        field_meta: FieldMeta,
     },
     UpdateField {
         changeset: FieldChangeset,
     },
     DeleteField {
-        field: Field,
+        field_meta: FieldMeta,
     },
     AssertFieldCount(usize),
     AssertFieldEqual {
         field_index: usize,
-        field: Field,
+        field_meta: FieldMeta,
     },
     CreateBlock {
         block: GridBlock,
@@ -68,27 +68,31 @@ pub struct GridEditorTest {
     pub sdk: FlowySDKTest,
     pub grid_id: String,
     pub editor: Arc<ClientGridEditor>,
-    pub fields: Vec<Field>,
+    pub field_metas: Vec<FieldMeta>,
     pub grid_blocks: Vec<GridBlock>,
-    pub row_metas: Vec<RowMeta>,
+    pub row_metas: Vec<Arc<RowMeta>>,
 }
 
 impl GridEditorTest {
     pub async fn new() -> Self {
+        Self::with_data("".to_owned()).await
+    }
+
+    pub async fn with_data(data: String) -> Self {
         let sdk = FlowySDKTest::default();
         let _ = sdk.init_user().await;
-        let test = ViewTest::new_grid_view(&sdk).await;
+        let test = ViewTest::new_grid_view(&sdk, data).await;
         let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
-        let fields = editor.get_fields(None).await.unwrap();
+        let fields = editor.get_field_metas(None).await.unwrap();
         let grid_blocks = editor.get_blocks().await.unwrap();
-        let row_metas = editor.get_row_metas(&None).await.unwrap();
+        let row_metas = editor.get_row_metas(None).await.unwrap();
 
         let grid_id = test.view.id;
         Self {
             sdk,
             grid_id,
             editor,
-            fields,
+            field_metas: fields,
             grid_blocks,
             row_metas,
         }
@@ -107,26 +111,28 @@ impl GridEditorTest {
         let _cache = rev_manager.revision_cache().await;
 
         match script {
-            EditorScript::CreateField { field } => {
+            EditorScript::CreateField { field_meta: field } => {
                 self.editor.create_field(field).await.unwrap();
-                self.fields = self.editor.get_fields(None).await.unwrap();
+                self.field_metas = self.editor.get_field_metas(None).await.unwrap();
             }
             EditorScript::UpdateField { changeset: change } => {
                 self.editor.update_field(change).await.unwrap();
-                self.fields = self.editor.get_fields(None).await.unwrap();
+                self.field_metas = self.editor.get_field_metas(None).await.unwrap();
             }
-            EditorScript::DeleteField { field } => {
+            EditorScript::DeleteField { field_meta: field } => {
                 self.editor.delete_field(&field.id).await.unwrap();
-                self.fields = self.editor.get_fields(None).await.unwrap();
+                self.field_metas = self.editor.get_field_metas(None).await.unwrap();
             }
             EditorScript::AssertFieldCount(count) => {
-                assert_eq!(self.editor.get_fields(None).await.unwrap().len(), count);
+                assert_eq!(self.editor.get_field_metas(None).await.unwrap().len(), count);
             }
 
-            EditorScript::AssertFieldEqual { field_index, field } => {
-                let repeated_fields = self.editor.get_fields(None).await.unwrap();
-                let compared_field = repeated_fields[field_index].clone();
-                assert_eq!(compared_field, field);
+            EditorScript::AssertFieldEqual {
+                field_index,
+                field_meta,
+            } => {
+                let field_metas = self.editor.get_field_metas(None).await.unwrap();
+                assert_eq!(field_metas[field_index].clone(), field_meta);
             }
             EditorScript::CreateBlock { block } => {
                 self.editor.create_block(block).await.unwrap();
@@ -153,18 +159,18 @@ impl GridEditorTest {
             }
             EditorScript::CreateEmptyRow => {
                 self.editor.create_row().await.unwrap();
-                self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
+                self.row_metas = self.editor.get_row_metas(None).await.unwrap();
                 self.grid_blocks = self.editor.get_blocks().await.unwrap();
             }
             EditorScript::CreateRow { context } => {
                 self.editor.insert_rows(vec![context]).await.unwrap();
-                self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
+                self.row_metas = self.editor.get_row_metas(None).await.unwrap();
                 self.grid_blocks = self.editor.get_blocks().await.unwrap();
             }
             EditorScript::UpdateRow { changeset: change } => self.editor.update_row(change).await.unwrap(),
             EditorScript::DeleteRow { row_ids } => {
                 self.editor.delete_rows(row_ids).await.unwrap();
-                self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
+                self.row_metas = self.editor.get_row_metas(None).await.unwrap();
                 self.grid_blocks = self.editor.get_blocks().await.unwrap();
             }
             EditorScript::AssertRow { changeset } => {
@@ -180,7 +186,7 @@ impl GridEditorTest {
             }
             EditorScript::UpdateCell { changeset } => {
                 self.editor.update_cell(changeset).await.unwrap();
-                self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
+                self.row_metas = self.editor.get_row_metas(None).await.unwrap();
             }
             EditorScript::AssertRowCount(count) => {
                 assert_eq!(self.editor.get_rows(None).await.unwrap().len(), count);
@@ -195,7 +201,7 @@ impl GridEditorTest {
     }
 }
 
-pub fn create_text_field() -> Field {
+pub fn create_text_field() -> FieldMeta {
     FieldBuilder::new(RichTextTypeOptionsBuilder::default())
         .name("Name")
         .visibility(true)
@@ -203,7 +209,7 @@ pub fn create_text_field() -> Field {
         .build()
 }
 
-pub fn create_single_select_field() -> Field {
+pub fn create_single_select_field() -> FieldMeta {
     let single_select = SingleSelectTypeOptionsBuilder::default()
         .option(SelectOption::new("Done"))
         .option(SelectOption::new("Progress"));

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

@@ -308,7 +308,7 @@ impl FolderCouldServiceV1 for LocalServer {
             belongings: RepeatedView::default(),
             modified_time: time,
             create_time: time,
-            ext_data: params.ext_data,
+            ext_data: "".to_string(),
             thumbnail: params.thumbnail,
             plugin_type: params.plugin_type,
         };

+ 7 - 9
frontend/rust-lib/flowy-test/src/helper.rs

@@ -26,11 +26,11 @@ pub struct ViewTest {
 
 impl ViewTest {
     #[allow(dead_code)]
-    pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType) -> Self {
+    pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType, data: String) -> Self {
         let workspace = create_workspace(sdk, "Workspace", "").await;
         open_workspace(sdk, &workspace.id).await;
         let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
-        let view = create_view(sdk, &app.id, data_type).await;
+        let view = create_view(sdk, &app.id, data_type, data).await;
         Self {
             sdk: sdk.clone(),
             workspace,
@@ -39,14 +39,12 @@ impl ViewTest {
         }
     }
 
-    #[allow(dead_code)]
-    pub async fn new_grid_view(sdk: &FlowySDKTest) -> Self {
-        Self::new(sdk, ViewDataType::Grid).await
+    pub async fn new_grid_view(sdk: &FlowySDKTest, data: String) -> Self {
+        Self::new(sdk, ViewDataType::Grid, data).await
     }
 
-    #[allow(dead_code)]
     pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self {
-        Self::new(sdk, ViewDataType::TextBlock).await
+        Self::new(sdk, ViewDataType::TextBlock, "".to_owned()).await
     }
 }
 
@@ -93,15 +91,15 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s
     app
 }
 
-async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType) -> View {
+async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType, data: String) -> View {
     let request = CreateViewPayload {
         belong_to_id: app_id.to_string(),
         name: "View A".to_string(),
         desc: "".to_string(),
         thumbnail: Some("http://1.png".to_string()),
         data_type,
-        ext_data: "".to_string(),
         plugin_type: 0,
+        data,
     };
 
     let view = FolderEventBuilder::new(sdk.clone())

+ 22 - 21
shared-lib/flowy-collaboration/src/client_grid/block_pad.rs

@@ -50,27 +50,28 @@ impl GridBlockMetaPad {
         })
     }
 
-    pub fn get_rows(&self, row_ids: Vec<String>) -> CollaborateResult<Vec<RowMeta>> {
-        let row_map = self
-            .rows
-            .iter()
-            .map(|row| (&row.id, row.clone()))
-            .collect::<HashMap<&String, Arc<RowMeta>>>();
-
-        Ok(row_ids
-            .iter()
-            .flat_map(|row_id| match row_map.get(row_id) {
-                None => {
-                    tracing::error!("Can't find the row with id: {}", row_id);
-                    None
-                }
-                Some(row) => Some((**row).clone()),
-            })
-            .collect::<Vec<RowMeta>>())
-    }
-
-    pub fn all_rows(&self) -> Vec<RowMeta> {
-        self.rows.iter().map(|row| (**row).clone()).collect::<Vec<_>>()
+    pub fn get_rows(&self, row_ids: Option<Vec<String>>) -> CollaborateResult<Vec<Arc<RowMeta>>> {
+        match row_ids {
+            None => Ok(self.rows.iter().map(|row| row.clone()).collect::<Vec<_>>()),
+            Some(row_ids) => {
+                let row_map = self
+                    .rows
+                    .iter()
+                    .map(|row| (&row.id, row.clone()))
+                    .collect::<HashMap<&String, Arc<RowMeta>>>();
+
+                Ok(row_ids
+                    .iter()
+                    .flat_map(|row_id| match row_map.get(row_id) {
+                        None => {
+                            tracing::error!("Can't find the row with id: {}", row_id);
+                            None
+                        }
+                        Some(row) => Some(row.clone()),
+                    })
+                    .collect::<Vec<_>>())
+            }
+        }
     }
 
     pub fn number_of_rows(&self) -> i32 {

+ 7 - 7
shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs

@@ -1,10 +1,10 @@
 use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBlockMetaDelta, GridMetaDelta};
 use crate::errors::{CollaborateError, CollaborateResult};
-use flowy_grid_data_model::entities::{Field, GridBlock, GridBlockMeta, GridMeta, RowMeta};
+use flowy_grid_data_model::entities::{FieldMeta, GridBlock, GridBlockMeta, GridMeta, RowMeta};
 
 pub struct GridBuilder {
     grid_id: String,
-    fields: Vec<Field>,
+    fields: Vec<FieldMeta>,
     grid_block: GridBlock,
     grid_block_meta: GridBlockMeta,
 }
@@ -25,7 +25,7 @@ impl GridBuilder {
         }
     }
 
-    pub fn add_field(mut self, field: Field) -> Self {
+    pub fn add_field(mut self, field: FieldMeta) -> Self {
         self.fields.push(field);
         self
     }
@@ -62,7 +62,7 @@ pub struct BuildGridInfo {
 }
 
 #[allow(dead_code)]
-fn check_rows(fields: &[Field], rows: &[RowMeta]) -> CollaborateResult<()> {
+fn check_rows(fields: &[FieldMeta], rows: &[RowMeta]) -> CollaborateResult<()> {
     let field_ids = fields.iter().map(|field| &field.id).collect::<Vec<&String>>();
     for row in rows {
         let cell_field_ids = row.cell_by_field_id.keys().into_iter().collect::<Vec<&String>>();
@@ -77,13 +77,13 @@ fn check_rows(fields: &[Field], rows: &[RowMeta]) -> CollaborateResult<()> {
 #[cfg(test)]
 mod tests {
     use crate::client_grid::GridBuilder;
-    use flowy_grid_data_model::entities::{Field, FieldType, GridBlockMeta, GridMeta};
+    use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMeta, GridMeta};
 
     #[test]
     fn create_default_grid_test() {
         let info = GridBuilder::new("1")
-            .add_field(Field::new("Name", "", FieldType::RichText))
-            .add_field(Field::new("Tags", "", FieldType::SingleSelect))
+            .add_field(FieldMeta::new("Name", "", FieldType::RichText))
+            .add_field(FieldMeta::new("Tags", "", FieldType::SingleSelect))
             .add_empty_row()
             .add_empty_row()
             .add_empty_row()

+ 29 - 10
shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs

@@ -2,7 +2,7 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision};
 use crate::errors::{internal_error, CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
 use flowy_grid_data_model::entities::{
-    Field, FieldChangeset, GridBlock, GridBlockChangeset, GridMeta, RepeatedFieldOrder,
+    FieldChangeset, FieldMeta, FieldOrder, GridBlock, GridBlockChangeset, GridMeta, RepeatedFieldOrder,
 };
 use lib_infra::uuid;
 use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
@@ -34,13 +34,13 @@ impl GridMetaPad {
         Self::from_delta(grid_delta)
     }
 
-    pub fn create_field(&mut self, field: Field) -> CollaborateResult<Option<GridChange>> {
+    pub fn create_field(&mut self, field_meta: FieldMeta) -> CollaborateResult<Option<GridChange>> {
         self.modify_grid(|grid| {
-            if grid.fields.contains(&field) {
+            if grid.fields.contains(&field_meta) {
                 tracing::warn!("Duplicate grid field");
                 Ok(None)
             } else {
-                grid.fields.push(field);
+                grid.fields.push(field_meta);
                 Ok(Some(()))
             }
         })
@@ -56,7 +56,15 @@ impl GridMetaPad {
         })
     }
 
-    pub fn get_fields(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<Field>> {
+    pub fn get_field_orders(&self) -> Vec<FieldOrder> {
+        self.grid_meta
+            .fields
+            .iter()
+            .map(|field_meta| FieldOrder::from(field_meta))
+            .collect()
+    }
+
+    pub fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<FieldMeta>> {
         match field_orders {
             None => Ok(self.grid_meta.fields.clone()),
             Some(field_orders) => {
@@ -65,7 +73,7 @@ impl GridMetaPad {
                     .fields
                     .iter()
                     .map(|field| (&field.id, field))
-                    .collect::<HashMap<&String, &Field>>();
+                    .collect::<HashMap<&String, &FieldMeta>>();
 
                 let fields = field_orders
                     .iter()
@@ -76,7 +84,7 @@ impl GridMetaPad {
                         }
                         Some(field) => Some((*field).clone()),
                     })
-                    .collect::<Vec<Field>>();
+                    .collect::<Vec<FieldMeta>>();
                 Ok(fields)
             }
         }
@@ -131,7 +139,18 @@ impl GridMetaPad {
                 tracing::warn!("Duplicate grid block");
                 Ok(None)
             } else {
-                grid.blocks.push(block);
+                match grid.blocks.last() {
+                    None => grid.blocks.push(block),
+                    Some(last_block) => {
+                        if last_block.start_row_index > block.start_row_index
+                            && last_block.len() > block.start_row_index
+                        {
+                            let msg = format!("GridBlock's start_row_index should be greater than the last_block's start_row_index and its len");
+                            return Err(CollaborateError::internal().context(msg))
+                        }
+                        grid.blocks.push(block);
+                    }
+                }
                 Ok(Some(()))
             }
         })
@@ -168,7 +187,7 @@ impl GridMetaPad {
         self.delta.to_delta_str()
     }
 
-    pub fn fields(&self) -> &[Field] {
+    pub fn fields(&self) -> &[FieldMeta] {
         &self.grid_meta.fields
     }
 
@@ -208,7 +227,7 @@ impl GridMetaPad {
 
     pub fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridChange>>
     where
-        F: FnOnce(&mut Field) -> CollaborateResult<Option<()>>,
+        F: FnOnce(&mut FieldMeta) -> CollaborateResult<Option<()>>,
     {
         self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
             None => {

+ 5 - 11
shared-lib/flowy-folder-data-model/src/entities/view.rs

@@ -124,10 +124,10 @@ pub struct CreateViewPayload {
     pub data_type: ViewDataType,
 
     #[pb(index = 6)]
-    pub ext_data: String,
+    pub plugin_type: i32,
 
     #[pb(index = 7)]
-    pub plugin_type: i32,
+    pub data: String,
 }
 
 #[derive(Default, ProtoBuf, Debug, Clone)]
@@ -148,15 +148,12 @@ pub struct CreateViewParams {
     pub data_type: ViewDataType,
 
     #[pb(index = 6)]
-    pub ext_data: String,
-
-    #[pb(index = 7)]
     pub view_id: String,
 
-    #[pb(index = 8)]
+    #[pb(index = 7)]
     pub data: String,
 
-    #[pb(index = 9)]
+    #[pb(index = 8)]
     pub plugin_type: i32,
 }
 
@@ -167,12 +164,10 @@ impl TryInto<CreateViewParams> for CreateViewPayload {
         let name = ViewName::parse(self.name)?.0;
         let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0;
         let view_id = uuid::Uuid::new_v4().to_string();
-        let ext_data = ViewExtensionData::parse(self.ext_data)?.0;
         let thumbnail = match self.thumbnail {
             None => "".to_string(),
             Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0,
         };
-        let data = "".to_string();
 
         Ok(CreateViewParams {
             belong_to_id,
@@ -180,9 +175,8 @@ impl TryInto<CreateViewParams> for CreateViewPayload {
             desc: self.desc,
             data_type: self.data_type,
             thumbnail,
-            ext_data,
             view_id,
-            data,
+            data: self.data,
             plugin_type: self.plugin_type,
         })
     }

+ 76 - 118
shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs

@@ -793,8 +793,8 @@ pub struct CreateViewPayload {
     pub name: ::std::string::String,
     pub desc: ::std::string::String,
     pub data_type: ViewDataType,
-    pub ext_data: ::std::string::String,
     pub plugin_type: i32,
+    pub data: ::std::string::String,
     // message oneof groups
     pub one_of_thumbnail: ::std::option::Option<CreateViewPayload_oneof_one_of_thumbnail>,
     // special fields
@@ -960,45 +960,45 @@ impl CreateViewPayload {
         self.data_type = v;
     }
 
-    // string ext_data = 6;
+    // int32 plugin_type = 6;
 
 
-    pub fn get_ext_data(&self) -> &str {
-        &self.ext_data
+    pub fn get_plugin_type(&self) -> i32 {
+        self.plugin_type
     }
-    pub fn clear_ext_data(&mut self) {
-        self.ext_data.clear();
+    pub fn clear_plugin_type(&mut self) {
+        self.plugin_type = 0;
     }
 
     // Param is passed by value, moved
-    pub fn set_ext_data(&mut self, v: ::std::string::String) {
-        self.ext_data = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_ext_data(&mut self) -> &mut ::std::string::String {
-        &mut self.ext_data
-    }
-
-    // Take field
-    pub fn take_ext_data(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.ext_data, ::std::string::String::new())
+    pub fn set_plugin_type(&mut self, v: i32) {
+        self.plugin_type = v;
     }
 
-    // int32 plugin_type = 7;
+    // string data = 7;
 
 
-    pub fn get_plugin_type(&self) -> i32 {
-        self.plugin_type
+    pub fn get_data(&self) -> &str {
+        &self.data
     }
-    pub fn clear_plugin_type(&mut self) {
-        self.plugin_type = 0;
+    pub fn clear_data(&mut self) {
+        self.data.clear();
     }
 
     // Param is passed by value, moved
-    pub fn set_plugin_type(&mut self, v: i32) {
-        self.plugin_type = v;
+    pub fn set_data(&mut self, v: ::std::string::String) {
+        self.data = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_data(&mut self) -> &mut ::std::string::String {
+        &mut self.data
+    }
+
+    // Take field
+    pub fn take_data(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
 }
 
@@ -1030,15 +1030,15 @@ impl ::protobuf::Message for CreateViewPayload {
                     ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.data_type, 5, &mut self.unknown_fields)?
                 },
                 6 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?;
-                },
-                7 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
                     let tmp = is.read_int32()?;
                     self.plugin_type = tmp;
                 },
+                7 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -1063,11 +1063,11 @@ impl ::protobuf::Message for CreateViewPayload {
         if self.data_type != ViewDataType::TextBlock {
             my_size += ::protobuf::rt::enum_size(5, self.data_type);
         }
-        if !self.ext_data.is_empty() {
-            my_size += ::protobuf::rt::string_size(6, &self.ext_data);
-        }
         if self.plugin_type != 0 {
-            my_size += ::protobuf::rt::value_size(7, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+            my_size += ::protobuf::rt::value_size(6, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+        }
+        if !self.data.is_empty() {
+            my_size += ::protobuf::rt::string_size(7, &self.data);
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail {
             match v {
@@ -1094,11 +1094,11 @@ impl ::protobuf::Message for CreateViewPayload {
         if self.data_type != ViewDataType::TextBlock {
             os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?;
         }
-        if !self.ext_data.is_empty() {
-            os.write_string(6, &self.ext_data)?;
-        }
         if self.plugin_type != 0 {
-            os.write_int32(7, self.plugin_type)?;
+            os.write_int32(6, self.plugin_type)?;
+        }
+        if !self.data.is_empty() {
+            os.write_string(7, &self.data)?;
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail {
             match v {
@@ -1170,16 +1170,16 @@ impl ::protobuf::Message for CreateViewPayload {
                 |m: &CreateViewPayload| { &m.data_type },
                 |m: &mut CreateViewPayload| { &mut m.data_type },
             ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "ext_data",
-                |m: &CreateViewPayload| { &m.ext_data },
-                |m: &mut CreateViewPayload| { &mut m.ext_data },
-            ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
                 "plugin_type",
                 |m: &CreateViewPayload| { &m.plugin_type },
                 |m: &mut CreateViewPayload| { &mut m.plugin_type },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "data",
+                |m: &CreateViewPayload| { &m.data },
+                |m: &mut CreateViewPayload| { &mut m.data },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateViewPayload>(
                 "CreateViewPayload",
                 fields,
@@ -1201,8 +1201,8 @@ impl ::protobuf::Clear for CreateViewPayload {
         self.desc.clear();
         self.one_of_thumbnail = ::std::option::Option::None;
         self.data_type = ViewDataType::TextBlock;
-        self.ext_data.clear();
         self.plugin_type = 0;
+        self.data.clear();
         self.unknown_fields.clear();
     }
 }
@@ -1227,7 +1227,6 @@ pub struct CreateViewParams {
     pub desc: ::std::string::String,
     pub thumbnail: ::std::string::String,
     pub data_type: ViewDataType,
-    pub ext_data: ::std::string::String,
     pub view_id: ::std::string::String,
     pub data: ::std::string::String,
     pub plugin_type: i32,
@@ -1366,33 +1365,7 @@ impl CreateViewParams {
         self.data_type = v;
     }
 
-    // string ext_data = 6;
-
-
-    pub fn get_ext_data(&self) -> &str {
-        &self.ext_data
-    }
-    pub fn clear_ext_data(&mut self) {
-        self.ext_data.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_ext_data(&mut self, v: ::std::string::String) {
-        self.ext_data = v;
-    }
-
-    // Mutable pointer to the field.
-    // If field is not initialized, it is initialized with default value first.
-    pub fn mut_ext_data(&mut self) -> &mut ::std::string::String {
-        &mut self.ext_data
-    }
-
-    // Take field
-    pub fn take_ext_data(&mut self) -> ::std::string::String {
-        ::std::mem::replace(&mut self.ext_data, ::std::string::String::new())
-    }
-
-    // string view_id = 7;
+    // string view_id = 6;
 
 
     pub fn get_view_id(&self) -> &str {
@@ -1418,7 +1391,7 @@ impl CreateViewParams {
         ::std::mem::replace(&mut self.view_id, ::std::string::String::new())
     }
 
-    // string data = 8;
+    // string data = 7;
 
 
     pub fn get_data(&self) -> &str {
@@ -1444,7 +1417,7 @@ impl CreateViewParams {
         ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
 
-    // int32 plugin_type = 9;
+    // int32 plugin_type = 8;
 
 
     pub fn get_plugin_type(&self) -> i32 {
@@ -1485,15 +1458,12 @@ impl ::protobuf::Message for CreateViewParams {
                     ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.data_type, 5, &mut self.unknown_fields)?
                 },
                 6 => {
-                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?;
-                },
-                7 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?;
                 },
-                8 => {
+                7 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
                 },
-                9 => {
+                8 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
@@ -1527,17 +1497,14 @@ impl ::protobuf::Message for CreateViewParams {
         if self.data_type != ViewDataType::TextBlock {
             my_size += ::protobuf::rt::enum_size(5, self.data_type);
         }
-        if !self.ext_data.is_empty() {
-            my_size += ::protobuf::rt::string_size(6, &self.ext_data);
-        }
         if !self.view_id.is_empty() {
-            my_size += ::protobuf::rt::string_size(7, &self.view_id);
+            my_size += ::protobuf::rt::string_size(6, &self.view_id);
         }
         if !self.data.is_empty() {
-            my_size += ::protobuf::rt::string_size(8, &self.data);
+            my_size += ::protobuf::rt::string_size(7, &self.data);
         }
         if self.plugin_type != 0 {
-            my_size += ::protobuf::rt::value_size(9, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+            my_size += ::protobuf::rt::value_size(8, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
         }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
@@ -1560,17 +1527,14 @@ impl ::protobuf::Message for CreateViewParams {
         if self.data_type != ViewDataType::TextBlock {
             os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.data_type))?;
         }
-        if !self.ext_data.is_empty() {
-            os.write_string(6, &self.ext_data)?;
-        }
         if !self.view_id.is_empty() {
-            os.write_string(7, &self.view_id)?;
+            os.write_string(6, &self.view_id)?;
         }
         if !self.data.is_empty() {
-            os.write_string(8, &self.data)?;
+            os.write_string(7, &self.data)?;
         }
         if self.plugin_type != 0 {
-            os.write_int32(9, self.plugin_type)?;
+            os.write_int32(8, self.plugin_type)?;
         }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
@@ -1635,11 +1599,6 @@ impl ::protobuf::Message for CreateViewParams {
                 |m: &CreateViewParams| { &m.data_type },
                 |m: &mut CreateViewParams| { &mut m.data_type },
             ));
-            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
-                "ext_data",
-                |m: &CreateViewParams| { &m.ext_data },
-                |m: &mut CreateViewParams| { &mut m.ext_data },
-            ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "view_id",
                 |m: &CreateViewParams| { &m.view_id },
@@ -1676,7 +1635,6 @@ impl ::protobuf::Clear for CreateViewParams {
         self.desc.clear();
         self.thumbnail.clear();
         self.data_type = ViewDataType::TextBlock;
-        self.ext_data.clear();
         self.view_id.clear();
         self.data.clear();
         self.plugin_type = 0;
@@ -2880,32 +2838,32 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x18\t\x20\x01(\x03R\ncreateTime\x12\x19\n\x08ext_data\x18\n\x20\x01(\tR\
     \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\x12\x1f\
     \n\x0bplugin_type\x18\x0c\x20\x01(\x05R\npluginType\"+\n\x0cRepeatedView\
-    \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xf9\x01\n\
+    \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xf2\x01\n\
     \x11CreateViewPayload\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbel\
     ongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\
     \x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\0R\
     \tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08d\
-    ataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extData\x12\x1f\n\
-    \x0bplugin_type\x18\x07\x20\x01(\x05R\npluginTypeB\x12\n\x10one_of_thumb\
-    nail\"\x8f\x02\n\x10CreateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\
-    \x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\
-    \x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\
-    \x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.Vi\
-    ewDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07ext\
-    Data\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\x06viewId\x12\x12\n\x04dat\
-    a\x18\x08\x20\x01(\tR\x04data\x12\x1f\n\x0bplugin_type\x18\t\x20\x01(\
-    \x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\x01\x20\x01(\
-    \tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\x01\x20\x03(\
-    \tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07view_id\x18\
-    \x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\
-    ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbn\
-    ail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_\
-    of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateViewParams\x12\
-    \x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\
-    \x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\
-    \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\
-    \x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*'\n\x0cVi\
-    ewDataType\x12\r\n\tTextBlock\x10\0\x12\x08\n\x04Grid\x10\x01b\x06proto3\
+    ataType\x12\x1f\n\x0bplugin_type\x18\x06\x20\x01(\x05R\npluginType\x12\
+    \x12\n\x04data\x18\x07\x20\x01(\tR\x04dataB\x12\n\x10one_of_thumbnail\"\
+    \xf4\x01\n\x10CreateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01\
+    (\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\
+    \x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\
+    \x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTy\
+    peR\x08dataType\x12\x17\n\x07view_id\x18\x06\x20\x01(\tR\x06viewId\x12\
+    \x12\n\x04data\x18\x07\x20\x01(\tR\x04data\x12\x1f\n\x0bplugin_type\x18\
+    \x08\x20\x01(\x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\
+    \x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\
+    \x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07\
+    view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\
+    \tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\
+    \x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nam\
+    eB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateVi\
+    ewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\
+    \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\
+    \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\
+    mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\
+    l*'\n\x0cViewDataType\x12\r\n\tTextBlock\x10\0\x12\x08\n\x04Grid\x10\x01\
+    b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 5 - 6
shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto

@@ -23,8 +23,8 @@ message CreateViewPayload {
     string desc = 3;
     oneof one_of_thumbnail { string thumbnail = 4; };
     ViewDataType data_type = 5;
-    string ext_data = 6;
-    int32 plugin_type = 7;
+    int32 plugin_type = 6;
+    string data = 7;
 }
 message CreateViewParams {
     string belong_to_id = 1;
@@ -32,10 +32,9 @@ message CreateViewParams {
     string desc = 3;
     string thumbnail = 4;
     ViewDataType data_type = 5;
-    string ext_data = 6;
-    string view_id = 7;
-    string data = 8;
-    int32 plugin_type = 9;
+    string view_id = 6;
+    string data = 7;
+    int32 plugin_type = 8;
 }
 message ViewId {
     string value = 1;

+ 76 - 4
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -1,6 +1,7 @@
-use crate::entities::{Field, RowMeta};
+use crate::entities::{FieldMeta, FieldType, RowMeta};
 use flowy_derive::ProtoBuf;
 use std::collections::HashMap;
+use std::sync::Arc;
 
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct Grid {
@@ -14,20 +15,82 @@ pub struct Grid {
     pub row_orders: Vec<RowOrder>,
 }
 
+#[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,
+}
+
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct FieldOrder {
     #[pb(index = 1)]
     pub field_id: String,
 }
 
-impl std::convert::From<&Field> for FieldOrder {
-    fn from(field: &Field) -> Self {
+impl std::convert::From<&FieldMeta> for FieldOrder {
+    fn from(field_meta: &FieldMeta) -> Self {
         Self {
-            field_id: field.id.clone(),
+            field_id: field_meta.id.clone(),
         }
     }
 }
 
+impl std::convert::From<FieldMeta> for Field {
+    fn from(field_meta: FieldMeta) -> Self {
+        Self {
+            id: field_meta.id,
+            name: field_meta.name,
+            desc: field_meta.desc,
+            field_type: field_meta.field_type,
+            frozen: field_meta.frozen,
+            visibility: field_meta.visibility,
+            width: field_meta.width,
+        }
+    }
+}
+
+#[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)]
@@ -59,6 +122,15 @@ impl std::convert::From<&RowMeta> for RowOrder {
     }
 }
 
+impl std::convert::From<&Arc<RowMeta>> for RowOrder {
+    fn from(row: &Arc<RowMeta>) -> Self {
+        Self {
+            row_id: row.id.clone(),
+            block_id: row.block_id.clone(),
+        }
+    }
+}
+
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct RepeatedRowOrder {
     #[pb(index = 1)]

+ 11 - 29
shared-lib/flowy-grid-data-model/src/entities/meta.rs

@@ -12,7 +12,7 @@ pub struct GridMeta {
     pub grid_id: String,
 
     #[pb(index = 2)]
-    pub fields: Vec<Field>,
+    pub fields: Vec<FieldMeta>,
 
     #[pb(index = 3)]
     pub blocks: Vec<GridBlock>,
@@ -30,6 +30,12 @@ pub struct GridBlock {
     pub row_count: i32,
 }
 
+impl GridBlock {
+    pub fn len(&self) -> i32 {
+        self.start_row_index + self.row_count
+    }
+}
+
 impl GridBlock {
     pub fn new() -> Self {
         GridBlock {
@@ -65,7 +71,7 @@ pub struct GridBlockMeta {
 }
 
 #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, PartialEq, Eq)]
-pub struct Field {
+pub struct FieldMeta {
     #[pb(index = 1)]
     pub id: String,
 
@@ -91,7 +97,7 @@ pub struct Field {
     pub type_options: String,
 }
 
-impl Field {
+impl FieldMeta {
     pub fn new(name: &str, desc: &str, field_type: FieldType) -> Self {
         Self {
             id: uuid::Uuid::new_v4().to_string(),
@@ -133,30 +139,6 @@ pub struct FieldChangeset {
     pub type_options: Option<String>,
 }
 
-#[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, PartialEq, Eq, ProtoBuf_Enum, EnumString, EnumIter, Display, Serialize, Deserialize)]
 pub enum FieldType {
     RichText = 0,
@@ -180,8 +162,8 @@ impl AsRef<FieldType> for FieldType {
 }
 
 impl From<&FieldType> for FieldType {
-    fn from(field: &FieldType) -> Self {
-        field.clone()
+    fn from(field_type: &FieldType) -> Self {
+        field_type.clone()
     }
 }
 

+ 574 - 23
shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs

@@ -280,6 +280,385 @@ impl ::protobuf::reflect::ProtobufValue for Grid {
     }
 }
 
+#[derive(PartialEq,Clone,Default)]
+pub struct Field {
+    // message fields
+    pub id: ::std::string::String,
+    pub name: ::std::string::String,
+    pub desc: ::std::string::String,
+    pub field_type: super::meta::FieldType,
+    pub frozen: bool,
+    pub visibility: bool,
+    pub width: i32,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a Field {
+    fn default() -> &'a Field {
+        <Field as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl Field {
+    pub fn new() -> Field {
+        ::std::default::Default::default()
+    }
+
+    // string id = 1;
+
+
+    pub fn get_id(&self) -> &str {
+        &self.id
+    }
+    pub fn clear_id(&mut self) {
+        self.id.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_id(&mut self, v: ::std::string::String) {
+        self.id = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_id(&mut self) -> &mut ::std::string::String {
+        &mut self.id
+    }
+
+    // Take field
+    pub fn take_id(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.id, ::std::string::String::new())
+    }
+
+    // string name = 2;
+
+
+    pub fn get_name(&self) -> &str {
+        &self.name
+    }
+    pub fn clear_name(&mut self) {
+        self.name.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_name(&mut self, v: ::std::string::String) {
+        self.name = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_name(&mut self) -> &mut ::std::string::String {
+        &mut self.name
+    }
+
+    // Take field
+    pub fn take_name(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.name, ::std::string::String::new())
+    }
+
+    // string desc = 3;
+
+
+    pub fn get_desc(&self) -> &str {
+        &self.desc
+    }
+    pub fn clear_desc(&mut self) {
+        self.desc.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_desc(&mut self, v: ::std::string::String) {
+        self.desc = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_desc(&mut self) -> &mut ::std::string::String {
+        &mut self.desc
+    }
+
+    // Take field
+    pub fn take_desc(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.desc, ::std::string::String::new())
+    }
+
+    // .FieldType field_type = 4;
+
+
+    pub fn get_field_type(&self) -> super::meta::FieldType {
+        self.field_type
+    }
+    pub fn clear_field_type(&mut self) {
+        self.field_type = super::meta::FieldType::RichText;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_field_type(&mut self, v: super::meta::FieldType) {
+        self.field_type = v;
+    }
+
+    // bool frozen = 5;
+
+
+    pub fn get_frozen(&self) -> bool {
+        self.frozen
+    }
+    pub fn clear_frozen(&mut self) {
+        self.frozen = false;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_frozen(&mut self, v: bool) {
+        self.frozen = v;
+    }
+
+    // bool visibility = 6;
+
+
+    pub fn get_visibility(&self) -> bool {
+        self.visibility
+    }
+    pub fn clear_visibility(&mut self) {
+        self.visibility = false;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_visibility(&mut self, v: bool) {
+        self.visibility = v;
+    }
+
+    // int32 width = 7;
+
+
+    pub fn get_width(&self) -> i32 {
+        self.width
+    }
+    pub fn clear_width(&mut self) {
+        self.width = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_width(&mut self, v: i32) {
+        self.width = v;
+    }
+}
+
+impl ::protobuf::Message for Field {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
+                },
+                3 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?;
+                },
+                4 => {
+                    ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 4, &mut self.unknown_fields)?
+                },
+                5 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_bool()?;
+                    self.frozen = tmp;
+                },
+                6 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_bool()?;
+                    self.visibility = tmp;
+                },
+                7 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int32()?;
+                    self.width = tmp;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.id.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.id);
+        }
+        if !self.name.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.name);
+        }
+        if !self.desc.is_empty() {
+            my_size += ::protobuf::rt::string_size(3, &self.desc);
+        }
+        if self.field_type != super::meta::FieldType::RichText {
+            my_size += ::protobuf::rt::enum_size(4, self.field_type);
+        }
+        if self.frozen != false {
+            my_size += 2;
+        }
+        if self.visibility != false {
+            my_size += 2;
+        }
+        if self.width != 0 {
+            my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.id.is_empty() {
+            os.write_string(1, &self.id)?;
+        }
+        if !self.name.is_empty() {
+            os.write_string(2, &self.name)?;
+        }
+        if !self.desc.is_empty() {
+            os.write_string(3, &self.desc)?;
+        }
+        if self.field_type != super::meta::FieldType::RichText {
+            os.write_enum(4, ::protobuf::ProtobufEnum::value(&self.field_type))?;
+        }
+        if self.frozen != false {
+            os.write_bool(5, self.frozen)?;
+        }
+        if self.visibility != false {
+            os.write_bool(6, self.visibility)?;
+        }
+        if self.width != 0 {
+            os.write_int32(7, self.width)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> Field {
+        Field::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "id",
+                |m: &Field| { &m.id },
+                |m: &mut Field| { &mut m.id },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "name",
+                |m: &Field| { &m.name },
+                |m: &mut Field| { &mut m.name },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "desc",
+                |m: &Field| { &m.desc },
+                |m: &mut Field| { &mut m.desc },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::meta::FieldType>>(
+                "field_type",
+                |m: &Field| { &m.field_type },
+                |m: &mut Field| { &mut m.field_type },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
+                "frozen",
+                |m: &Field| { &m.frozen },
+                |m: &mut Field| { &mut m.frozen },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
+                "visibility",
+                |m: &Field| { &m.visibility },
+                |m: &mut Field| { &mut m.visibility },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
+                "width",
+                |m: &Field| { &m.width },
+                |m: &mut Field| { &mut m.width },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<Field>(
+                "Field",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static Field {
+        static instance: ::protobuf::rt::LazyV2<Field> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(Field::new)
+    }
+}
+
+impl ::protobuf::Clear for Field {
+    fn clear(&mut self) {
+        self.id.clear();
+        self.name.clear();
+        self.desc.clear();
+        self.field_type = super::meta::FieldType::RichText;
+        self.frozen = false;
+        self.visibility = false;
+        self.width = 0;
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for Field {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for Field {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
 #[derive(PartialEq,Clone,Default)]
 pub struct FieldOrder {
     // message fields
@@ -439,6 +818,172 @@ impl ::protobuf::reflect::ProtobufValue for FieldOrder {
     }
 }
 
+#[derive(PartialEq,Clone,Default)]
+pub struct RepeatedField {
+    // message fields
+    pub items: ::protobuf::RepeatedField<Field>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a RepeatedField {
+    fn default() -> &'a RepeatedField {
+        <RepeatedField as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl RepeatedField {
+    pub fn new() -> RepeatedField {
+        ::std::default::Default::default()
+    }
+
+    // repeated .Field items = 1;
+
+
+    pub fn get_items(&self) -> &[Field] {
+        &self.items
+    }
+    pub fn clear_items(&mut self) {
+        self.items.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_items(&mut self, v: ::protobuf::RepeatedField<Field>) {
+        self.items = v;
+    }
+
+    // Mutable pointer to the field.
+    pub fn mut_items(&mut self) -> &mut ::protobuf::RepeatedField<Field> {
+        &mut self.items
+    }
+
+    // Take field
+    pub fn take_items(&mut self) -> ::protobuf::RepeatedField<Field> {
+        ::std::mem::replace(&mut self.items, ::protobuf::RepeatedField::new())
+    }
+}
+
+impl ::protobuf::Message for RepeatedField {
+    fn is_initialized(&self) -> bool {
+        for v in &self.items {
+            if !v.is_initialized() {
+                return false;
+            }
+        };
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.items)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        for value in &self.items {
+            let len = value.compute_size();
+            my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
+        };
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        for v in &self.items {
+            os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
+            os.write_raw_varint32(v.get_cached_size())?;
+            v.write_to_with_cached_sizes(os)?;
+        };
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> RepeatedField {
+        RepeatedField::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Field>>(
+                "items",
+                |m: &RepeatedField| { &m.items },
+                |m: &mut RepeatedField| { &mut m.items },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<RepeatedField>(
+                "RepeatedField",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static RepeatedField {
+        static instance: ::protobuf::rt::LazyV2<RepeatedField> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(RepeatedField::new)
+    }
+}
+
+impl ::protobuf::Clear for RepeatedField {
+    fn clear(&mut self) {
+        self.items.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for RepeatedField {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for RepeatedField {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
 #[derive(PartialEq,Clone,Default)]
 pub struct RepeatedFieldOrder {
     // message fields
@@ -2321,29 +2866,35 @@ impl ::protobuf::reflect::ProtobufValue for QueryRowPayload {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\ngrid.proto\"p\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\
-    \x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrderR\x0bfieldOr\
-    ders\x12(\n\nrow_orders\x18\x03\x20\x03(\x0b2\t.RowOrderR\trowOrders\"'\
-    \n\nFieldOrder\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"7\n\
-    \x12RepeatedFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOr\
-    derR\x05items\"<\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\
-    \x05rowId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\"3\n\x10R\
-    epeatedRowOrder\x12\x1f\n\x05items\x18\x01\x20\x03(\x0b2\t.RowOrderR\x05\
-    items\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12@\
-    \n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\
-    \rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\
-    \n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\
-    \x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\
-    \x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05ite\
-    ms\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\
-    \x18\n\x07content\x18\x02\x20\x01(\tR\x07content\"'\n\x11CreateGridPaylo\
-    ad\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\
-    \x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"d\n\x11QueryFieldPayload\
-    \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orde\
-    rs\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"\\\n\
-    \x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\
-    \x120\n\nrow_orders\x18\x02\x20\x01(\x0b2\x11.RepeatedRowOrderR\trowOrde\
-    rsb\x06proto3\
+    \n\ngrid.proto\x1a\nmeta.proto\"p\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\
+    \x01(\tR\x02id\x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrd\
+    erR\x0bfieldOrders\x12(\n\nrow_orders\x18\x03\x20\x03(\x0b2\t.RowOrderR\
+    \trowOrders\"\xb8\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02\
+    id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\
+    \x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\x01(\x0e2\n.Fiel\
+    dTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\x08R\x06frozen\
+    \x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\x12\x14\n\x05wi\
+    dth\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\x19\n\x08field_i\
+    d\x18\x01\x20\x01(\tR\x07fieldId\"-\n\rRepeatedField\x12\x1c\n\x05items\
+    \x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\
+    \x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"<\n\x08\
+    RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\
+    lock_id\x18\x02\x20\x01(\tR\x07blockId\"3\n\x10RepeatedRowOrder\x12\x1f\
+    \n\x05items\x18\x01\x20\x03(\x0b2\t.RowOrderR\x05items\"\xb8\x01\n\x03Ro\
+    w\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\
+    \x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\
+    \x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldId\
+    Entry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\
+    \x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\
+    \x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\";\n\x04Cell\x12\
+    \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\
+    \x18\x02\x20\x01(\tR\x07content\"'\n\x11CreateGridPayload\x12\x12\n\x04n\
+    ame\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\
+    \x01\x20\x01(\tR\x05value\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\
+    \x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\
+    \x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"\\\n\x0fQueryRowPayload\
+    \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x120\n\nrow_orders\
+    \x18\x02\x20\x01(\x0b2\x11.RepeatedRowOrderR\trowOrdersb\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 72 - 239
shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs

@@ -27,7 +27,7 @@
 pub struct GridMeta {
     // message fields
     pub grid_id: ::std::string::String,
-    pub fields: ::protobuf::RepeatedField<Field>,
+    pub fields: ::protobuf::RepeatedField<FieldMeta>,
     pub blocks: ::protobuf::RepeatedField<GridBlock>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
@@ -71,10 +71,10 @@ impl GridMeta {
         ::std::mem::replace(&mut self.grid_id, ::std::string::String::new())
     }
 
-    // repeated .Field fields = 2;
+    // repeated .FieldMeta fields = 2;
 
 
-    pub fn get_fields(&self) -> &[Field] {
+    pub fn get_fields(&self) -> &[FieldMeta] {
         &self.fields
     }
     pub fn clear_fields(&mut self) {
@@ -82,17 +82,17 @@ impl GridMeta {
     }
 
     // Param is passed by value, moved
-    pub fn set_fields(&mut self, v: ::protobuf::RepeatedField<Field>) {
+    pub fn set_fields(&mut self, v: ::protobuf::RepeatedField<FieldMeta>) {
         self.fields = v;
     }
 
     // Mutable pointer to the field.
-    pub fn mut_fields(&mut self) -> &mut ::protobuf::RepeatedField<Field> {
+    pub fn mut_fields(&mut self) -> &mut ::protobuf::RepeatedField<FieldMeta> {
         &mut self.fields
     }
 
     // Take field
-    pub fn take_fields(&mut self) -> ::protobuf::RepeatedField<Field> {
+    pub fn take_fields(&mut self) -> ::protobuf::RepeatedField<FieldMeta> {
         ::std::mem::replace(&mut self.fields, ::protobuf::RepeatedField::new())
     }
 
@@ -235,7 +235,7 @@ impl ::protobuf::Message for GridMeta {
                 |m: &GridMeta| { &m.grid_id },
                 |m: &mut GridMeta| { &mut m.grid_id },
             ));
-            fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Field>>(
+            fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<FieldMeta>>(
                 "fields",
                 |m: &GridMeta| { &m.fields },
                 |m: &mut GridMeta| { &mut m.fields },
@@ -718,7 +718,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockMeta {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct Field {
+pub struct FieldMeta {
     // message fields
     pub id: ::std::string::String,
     pub name: ::std::string::String,
@@ -733,14 +733,14 @@ pub struct Field {
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a Field {
-    fn default() -> &'a Field {
-        <Field as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a FieldMeta {
+    fn default() -> &'a FieldMeta {
+        <FieldMeta as ::protobuf::Message>::default_instance()
     }
 }
 
-impl Field {
-    pub fn new() -> Field {
+impl FieldMeta {
+    pub fn new() -> FieldMeta {
         ::std::default::Default::default()
     }
 
@@ -909,7 +909,7 @@ impl Field {
     }
 }
 
-impl ::protobuf::Message for Field {
+impl ::protobuf::Message for FieldMeta {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -1050,8 +1050,8 @@ impl ::protobuf::Message for Field {
         Self::descriptor_static()
     }
 
-    fn new() -> Field {
-        Field::new()
+    fn new() -> FieldMeta {
+        FieldMeta::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -1060,59 +1060,59 @@ impl ::protobuf::Message for Field {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "id",
-                |m: &Field| { &m.id },
-                |m: &mut Field| { &mut m.id },
+                |m: &FieldMeta| { &m.id },
+                |m: &mut FieldMeta| { &mut m.id },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "name",
-                |m: &Field| { &m.name },
-                |m: &mut Field| { &mut m.name },
+                |m: &FieldMeta| { &m.name },
+                |m: &mut FieldMeta| { &mut m.name },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "desc",
-                |m: &Field| { &m.desc },
-                |m: &mut Field| { &mut m.desc },
+                |m: &FieldMeta| { &m.desc },
+                |m: &mut FieldMeta| { &mut m.desc },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<FieldType>>(
                 "field_type",
-                |m: &Field| { &m.field_type },
-                |m: &mut Field| { &mut m.field_type },
+                |m: &FieldMeta| { &m.field_type },
+                |m: &mut FieldMeta| { &mut m.field_type },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
                 "frozen",
-                |m: &Field| { &m.frozen },
-                |m: &mut Field| { &mut m.frozen },
+                |m: &FieldMeta| { &m.frozen },
+                |m: &mut FieldMeta| { &mut m.frozen },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
                 "visibility",
-                |m: &Field| { &m.visibility },
-                |m: &mut Field| { &mut m.visibility },
+                |m: &FieldMeta| { &m.visibility },
+                |m: &mut FieldMeta| { &mut m.visibility },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
                 "width",
-                |m: &Field| { &m.width },
-                |m: &mut Field| { &mut m.width },
+                |m: &FieldMeta| { &m.width },
+                |m: &mut FieldMeta| { &mut m.width },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "type_options",
-                |m: &Field| { &m.type_options },
-                |m: &mut Field| { &mut m.type_options },
+                |m: &FieldMeta| { &m.type_options },
+                |m: &mut FieldMeta| { &mut m.type_options },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<Field>(
-                "Field",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldMeta>(
+                "FieldMeta",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static Field {
-        static instance: ::protobuf::rt::LazyV2<Field> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(Field::new)
+    fn default_instance() -> &'static FieldMeta {
+        static instance: ::protobuf::rt::LazyV2<FieldMeta> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(FieldMeta::new)
     }
 }
 
-impl ::protobuf::Clear for Field {
+impl ::protobuf::Clear for FieldMeta {
     fn clear(&mut self) {
         self.id.clear();
         self.name.clear();
@@ -1126,13 +1126,13 @@ impl ::protobuf::Clear for Field {
     }
 }
 
-impl ::std::fmt::Debug for Field {
+impl ::std::fmt::Debug for FieldMeta {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for Field {
+impl ::protobuf::reflect::ProtobufValue for FieldMeta {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -1769,172 +1769,6 @@ impl ::protobuf::reflect::ProtobufValue for FieldChangeset {
     }
 }
 
-#[derive(PartialEq,Clone,Default)]
-pub struct RepeatedField {
-    // message fields
-    pub items: ::protobuf::RepeatedField<Field>,
-    // special fields
-    pub unknown_fields: ::protobuf::UnknownFields,
-    pub cached_size: ::protobuf::CachedSize,
-}
-
-impl<'a> ::std::default::Default for &'a RepeatedField {
-    fn default() -> &'a RepeatedField {
-        <RepeatedField as ::protobuf::Message>::default_instance()
-    }
-}
-
-impl RepeatedField {
-    pub fn new() -> RepeatedField {
-        ::std::default::Default::default()
-    }
-
-    // repeated .Field items = 1;
-
-
-    pub fn get_items(&self) -> &[Field] {
-        &self.items
-    }
-    pub fn clear_items(&mut self) {
-        self.items.clear();
-    }
-
-    // Param is passed by value, moved
-    pub fn set_items(&mut self, v: ::protobuf::RepeatedField<Field>) {
-        self.items = v;
-    }
-
-    // Mutable pointer to the field.
-    pub fn mut_items(&mut self) -> &mut ::protobuf::RepeatedField<Field> {
-        &mut self.items
-    }
-
-    // Take field
-    pub fn take_items(&mut self) -> ::protobuf::RepeatedField<Field> {
-        ::std::mem::replace(&mut self.items, ::protobuf::RepeatedField::new())
-    }
-}
-
-impl ::protobuf::Message for RepeatedField {
-    fn is_initialized(&self) -> bool {
-        for v in &self.items {
-            if !v.is_initialized() {
-                return false;
-            }
-        };
-        true
-    }
-
-    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        while !is.eof()? {
-            let (field_number, wire_type) = is.read_tag_unpack()?;
-            match field_number {
-                1 => {
-                    ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.items)?;
-                },
-                _ => {
-                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
-                },
-            };
-        }
-        ::std::result::Result::Ok(())
-    }
-
-    // Compute sizes of nested messages
-    #[allow(unused_variables)]
-    fn compute_size(&self) -> u32 {
-        let mut my_size = 0;
-        for value in &self.items {
-            let len = value.compute_size();
-            my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
-        };
-        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
-        self.cached_size.set(my_size);
-        my_size
-    }
-
-    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        for v in &self.items {
-            os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
-            os.write_raw_varint32(v.get_cached_size())?;
-            v.write_to_with_cached_sizes(os)?;
-        };
-        os.write_unknown_fields(self.get_unknown_fields())?;
-        ::std::result::Result::Ok(())
-    }
-
-    fn get_cached_size(&self) -> u32 {
-        self.cached_size.get()
-    }
-
-    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
-        &self.unknown_fields
-    }
-
-    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
-        &mut self.unknown_fields
-    }
-
-    fn as_any(&self) -> &dyn (::std::any::Any) {
-        self as &dyn (::std::any::Any)
-    }
-    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
-        self as &mut dyn (::std::any::Any)
-    }
-    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
-        self
-    }
-
-    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
-        Self::descriptor_static()
-    }
-
-    fn new() -> RepeatedField {
-        RepeatedField::new()
-    }
-
-    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
-        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
-        descriptor.get(|| {
-            let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Field>>(
-                "items",
-                |m: &RepeatedField| { &m.items },
-                |m: &mut RepeatedField| { &mut m.items },
-            ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<RepeatedField>(
-                "RepeatedField",
-                fields,
-                file_descriptor_proto()
-            )
-        })
-    }
-
-    fn default_instance() -> &'static RepeatedField {
-        static instance: ::protobuf::rt::LazyV2<RepeatedField> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(RepeatedField::new)
-    }
-}
-
-impl ::protobuf::Clear for RepeatedField {
-    fn clear(&mut self) {
-        self.items.clear();
-        self.unknown_fields.clear();
-    }
-}
-
-impl ::std::fmt::Debug for RepeatedField {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        ::protobuf::text_format::fmt(self, f)
-    }
-}
-
-impl ::protobuf::reflect::ProtobufValue for RepeatedField {
-    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
-        ::protobuf::reflect::ReflectValueRef::Message(self)
-    }
-}
-
 #[derive(PartialEq,Clone,Default)]
 pub struct AnyData {
     // message fields
@@ -3302,19 +3136,19 @@ impl ::protobuf::reflect::ProtobufValue for FieldType {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\nmeta.proto\"g\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
-    \x06gridId\x12\x1e\n\x06fields\x18\x02\x20\x03(\x0b2\x06.FieldR\x06field\
+    \n\nmeta.proto\"k\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
+    \x06gridId\x12\"\n\x06fields\x18\x02\x20\x03(\x0b2\n.FieldMetaR\x06field\
     s\x12\"\n\x06blocks\x18\x03\x20\x03(\x0b2\n.GridBlockR\x06blocks\"`\n\tG\
     ridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12&\n\x0fstart_row_i\
     ndex\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\x1b\n\trow_count\x18\x03\
     \x20\x01(\x05R\x08rowCount\"H\n\rGridBlockMeta\x12\x19\n\x08block_id\x18\
     \x01\x20\x01(\tR\x07blockId\x12\x1c\n\x04rows\x18\x02\x20\x03(\x0b2\x08.\
-    RowMetaR\x04rows\"\xdb\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
-    R\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\
-    \x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\x01(\x0e2\n.\
-    FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\x08R\x06froze\
-    n\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\x12\x14\n\x05w\
-    idth\x18\x07\x20\x01(\x05R\x05width\x12!\n\x0ctype_options\x18\x08\x20\
+    RowMetaR\x04rows\"\xdf\x01\n\tFieldMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\
+    \tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04des\
+    c\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\x01(\x0e2\n\
+    .FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\x08R\x06froz\
+    en\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\x12\x14\n\x05\
+    width\x18\x07\x20\x01(\x05R\x05width\x12!\n\x0ctype_options\x18\x08\x20\
     \x01(\tR\x0btypeOptions\"\xfd\x02\n\x0eFieldChangeset\x12\x19\n\x08field\
     _id\x18\x01\x20\x01(\tR\x07fieldId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\
     \0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12+\n\nf\
@@ -3324,31 +3158,30 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x01(\x05H\x05R\x05width\x12#\n\x0ctype_options\x18\x08\x20\x01(\tH\x06R\
     \x0btypeOptionsB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\x11one_of\
     _field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visibilityB\x0e\n\x0c\
-    one_of_widthB\x15\n\x13one_of_type_options\"-\n\rRepeatedField\x12\x1c\n\
-    \x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"8\n\x07AnyData\x12\
-    \x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\
-    \x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\
-    \x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\
-    kId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByF\
-    ieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\
-    \x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\
-    \n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\
-    \x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\
-    \xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\
-    \x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\
-    \n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_\
-    field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rce\
-    llByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\
-    \x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05\
-    value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\
-    \x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\
-    \x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"j\n\x11CellMetaChangeset\x12\
-    \x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\
-    \x02\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x03\x20\x01(\tH\0R\x04\
-    dataB\r\n\x0bone_of_data*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\
-    \n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingle\
-    Select\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\
-    \x10\x05b\x06proto3\
+    one_of_widthB\x15\n\x13one_of_type_options\"8\n\x07AnyData\x12\x17\n\x07\
+    type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01\
+    (\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\
+    \tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\
+    \x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntr\
+    yR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\x06height\
+    \x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\n\x12CellB\
+    yFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05v\
+    alue\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\xa7\x02\n\
+    \x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\
+    \x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\n\nvisib\
+    ility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_field_id\
+    \x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rcellByFiel\
+    dId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\
+    \x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\
+    \x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\x08Cell\
+    Meta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x12\n\x04d\
+    ata\x18\x02\x20\x01(\tR\x04data\"j\n\x11CellMetaChangeset\x12\x15\n\x06r\
+    ow_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x02\x20\x01\
+    (\tR\x07fieldId\x12\x14\n\x04data\x18\x03\x20\x01(\tH\0R\x04dataB\r\n\
+    \x0bone_of_data*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Nu\
+    mber\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\
+    \x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06\
+    proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 13 - 0
shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

@@ -1,13 +1,26 @@
 syntax = "proto3";
+import "meta.proto";
 
 message Grid {
     string id = 1;
     repeated FieldOrder field_orders = 2;
     repeated RowOrder row_orders = 3;
 }
+message Field {
+    string id = 1;
+    string name = 2;
+    string desc = 3;
+    FieldType field_type = 4;
+    bool frozen = 5;
+    bool visibility = 6;
+    int32 width = 7;
+}
 message FieldOrder {
     string field_id = 1;
 }
+message RepeatedField {
+    repeated Field items = 1;
+}
 message RepeatedFieldOrder {
     repeated FieldOrder items = 1;
 }

+ 2 - 5
shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto

@@ -2,7 +2,7 @@ syntax = "proto3";
 
 message GridMeta {
     string grid_id = 1;
-    repeated Field fields = 2;
+    repeated FieldMeta fields = 2;
     repeated GridBlock blocks = 3;
 }
 message GridBlock {
@@ -14,7 +14,7 @@ message GridBlockMeta {
     string block_id = 1;
     repeated RowMeta rows = 2;
 }
-message Field {
+message FieldMeta {
     string id = 1;
     string name = 2;
     string desc = 3;
@@ -34,9 +34,6 @@ message FieldChangeset {
     oneof one_of_width { int32 width = 7; };
     oneof one_of_type_options { string type_options = 8; };
 }
-message RepeatedField {
-    repeated Field items = 1;
-}
 message AnyData {
     string type_id = 1;
     bytes value = 2;

+ 2 - 2
shared-lib/flowy-grid-data-model/tests/serde_test.rs

@@ -31,8 +31,8 @@ fn grid_default_serde_test() {
     assert_eq!(json, r#"{"id":"1","fields":[],"blocks":[]}"#)
 }
 
-fn create_field(field_id: &str) -> Field {
-    let mut field = Field::new("Text Field", "", FieldType::RichText);
+fn create_field(field_id: &str) -> FieldMeta {
+    let mut field = FieldMeta::new("Text Field", "", FieldType::RichText);
     field.id = field_id.to_string();
     field
 }