فهرست منبع

feat: config grid plugin

appflowy 3 سال پیش
والد
کامیت
67e6b091a5
28فایلهای تغییر یافته به همراه952 افزوده شده و 566 حذف شده
  1. 3 0
      frontend/app_flowy/lib/plugin/plugin.dart
  2. 2 0
      frontend/app_flowy/lib/startup/tasks/load_plugin.dart
  3. 2 3
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  4. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart
  5. 5 5
      frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart
  6. 63 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart
  7. 0 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/controller/flowy_table_selection.dart
  8. 0 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/controller/grid_scroll.dart
  9. 6 6
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart
  10. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/layout.dart
  11. 0 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart
  12. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart
  13. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart
  14. 0 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart
  15. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_cell.dart
  16. 3 3
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart
  17. 3 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart
  18. 0 0
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/constants.dart
  19. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart
  20. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart
  21. 0 14
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_error_page.dart
  22. 5 5
      frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart
  23. 310 195
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
  24. 79 46
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
  25. 5 5
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  26. 46 28
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  27. 386 228
      shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
  28. 26 18
      shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

+ 3 - 0
frontend/app_flowy/lib/plugin/plugin.dart

@@ -13,6 +13,7 @@ enum DefaultPlugin {
   quillEditor,
   blank,
   trash,
+  grid,
 }
 
 extension FlowyDefaultPluginExt on DefaultPlugin {
@@ -24,6 +25,8 @@ extension FlowyDefaultPluginExt on DefaultPlugin {
         return 1;
       case DefaultPlugin.trash:
         return 2;
+      case DefaultPlugin.grid:
+        return 3;
     }
   }
 }

+ 2 - 0
frontend/app_flowy/lib/startup/tasks/load_plugin.dart

@@ -2,6 +2,7 @@ import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/presentation/plugins/blank/blank.dart';
 import 'package:app_flowy/workspace/presentation/plugins/doc/document.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/grid.dart';
 import 'package:app_flowy/workspace/presentation/plugins/trash/trash.dart';
 
 class PluginLoadTask extends LaunchTask {
@@ -13,5 +14,6 @@ class PluginLoadTask extends LaunchTask {
     registerPlugin(builder: BlankPluginBuilder(), config: BlankPluginConfig());
     registerPlugin(builder: TrashPluginBuilder(), config: TrashPluginConfig());
     registerPlugin(builder: DocumentPluginBuilder());
+    registerPlugin(builder: GridPluginBuilder(), config: GridPluginConfig());
   }
 }

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

@@ -74,7 +74,6 @@ class GridBloc extends Bloc<GridEvent, GridState> {
       result.fold((repeatedRow) {
         final rows = repeatedRow.items;
         final gridInfo = GridInfo(rows: rows, fields: _fields!);
-
         emit(
           state.copyWith(loadingState: GridLoadingState.finish(left(unit)), gridInfo: some(left(gridInfo))),
         );
@@ -116,7 +115,7 @@ class GridLoadingState with _$GridLoadingState {
 }
 
 class GridInfo {
-  List<GridRow> rows;
+  List<Row> rows;
   List<Field> fields;
 
   GridInfo({
@@ -139,7 +138,7 @@ class GridInfo {
 
 class RowInfo {
   List<Field> fields;
-  Map<String, GridCell> cellMap;
+  Map<String, Cell> cellMap;
   RowInfo({
     required this.fields,
     required this.cellMap,

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart

@@ -170,7 +170,7 @@ class HomeStackManager {
             if (pluginType == notifier.plugin.ty) {
               return notifier.plugin.display.buildWidget();
             } else {
-              return const BlankStackPage();
+              return const BlankPage();
             }
           }).toList(),
         );

+ 5 - 5
frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart

@@ -45,20 +45,20 @@ class BlankPagePluginDisplay extends PluginDisplay {
   Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12);
 
   @override
-  Widget buildWidget() => const BlankStackPage();
+  Widget buildWidget() => const BlankPage();
 
   @override
   List<NavigationItem> get navigationItems => [this];
 }
 
-class BlankStackPage extends StatefulWidget {
-  const BlankStackPage({Key? key}) : super(key: key);
+class BlankPage extends StatefulWidget {
+  const BlankPage({Key? key}) : super(key: key);
 
   @override
-  State<BlankStackPage> createState() => _BlankStackPageState();
+  State<BlankPage> createState() => _BlankPageState();
 }
 
-class _BlankStackPageState extends State<BlankStackPage> {
+class _BlankPageState extends State<BlankPage> {
   @override
   Widget build(BuildContext context) {
     return SizedBox.expand(

+ 63 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart

@@ -0,0 +1,63 @@
+import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
+import 'package:app_flowy/plugin/plugin.dart';
+import 'package:flutter/material.dart';
+
+import 'src/grid_page.dart';
+
+class GridPluginBuilder extends PluginBuilder {
+  @override
+  Plugin build(dynamic data) {
+    if (data is View) {
+      return GridPlugin(pluginType: pluginType, view: data);
+    } else {
+      throw FlowyPluginException.invalidData;
+    }
+  }
+
+  @override
+  String get menuName => "Table";
+
+  @override
+  PluginType get pluginType => DefaultPlugin.grid.type();
+}
+
+class GridPluginConfig implements PluginConfig {
+  @override
+  bool get creatable => true;
+}
+
+class GridPlugin extends Plugin {
+  final View _view;
+  final PluginType _pluginType;
+
+  GridPlugin({
+    required View view,
+    required PluginType pluginType,
+  })  : _pluginType = pluginType,
+        _view = view;
+
+  @override
+  PluginDisplay get display => GridPluginDisplay(view: _view);
+
+  @override
+  PluginId get id => _view.id;
+
+  @override
+  PluginType get ty => _pluginType;
+}
+
+class GridPluginDisplay extends PluginDisplay {
+  final View _view;
+  GridPluginDisplay({required View view, Key? key}) : _view = view;
+
+  @override
+  Widget get leftBarItem => const FlowyText.medium("Grid demo", fontSize: 12);
+
+  @override
+  Widget buildWidget() => GridPage(view: _view);
+
+  @override
+  List<NavigationItem> get navigationItems => [this];
+}

+ 0 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/controller/flowy_table_selection.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/controller/flowy_table_selection.dart


+ 0 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/controller/grid_scroll.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/controller/grid_scroll.dart


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

@@ -8,14 +8,14 @@ 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:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/controller/grid_scroll.dart';
 import 'package:styled_widget/styled_widget.dart';
 
-import 'grid_layout.dart';
-import 'grid_sizes.dart';
-import 'widgets/grid_content/grid_row.dart';
-import 'widgets/grid_footer/grid_footer.dart';
-import 'widgets/grid_header/header.dart';
+import 'controller/grid_scroll.dart';
+import 'layout/layout.dart';
+import 'layout/sizes.dart';
+import 'widgets/content/grid_row.dart';
+import 'widgets/footer/grid_footer.dart';
+import 'widgets/header/header.dart';
 
 class GridPage extends StatefulWidget {
   final View view;

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

@@ -1,6 +1,6 @@
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 
-import 'grid_sizes.dart';
+import 'sizes.dart';
 
 class GridLayout {
   static double headerWidth(List<Field> fields) {

+ 0 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid_sizes.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart


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

@@ -2,7 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'grid_cell.dart';
 
 class GridCellBuilder {
-  static GridCellWidget buildCell(Field? field, GridCell? cell) {
+  static GridCellWidget buildCell(Field? field, Cell? cell) {
     if (field == null || cell == null) {
       return const BlankCell();
     }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_content/cell_container.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart

@@ -1,4 +1,4 @@
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
 import 'package:flutter/material.dart';
 import 'cell_decoration.dart';

+ 0 - 0
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_content/cell_decoration.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart


+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_content/grid_cell.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_cell.dart

@@ -1,4 +1,4 @@
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
 import 'package:flutter/material.dart';
 

+ 3 - 3
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_content/grid_row.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart

@@ -1,6 +1,6 @@
 import 'package:app_flowy/workspace/application/grid/grid_bloc.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
 import 'package:flutter/material.dart';
 import 'cell_builder.dart';
 import 'cell_container.dart';
@@ -9,7 +9,7 @@ import 'grid_cell.dart';
 class GridRowContext {
   final RepeatedFieldOrder fieldOrders;
   final Map<String, Field> fieldById;
-  final Map<String, GridCell> cellByFieldId;
+  final Map<String, Cell> cellByFieldId;
   GridRowContext(this.fieldOrders, this.fieldById, this.cellByFieldId);
 }
 

+ 3 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_footer/grid_footer.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart

@@ -1,8 +1,9 @@
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/widgets/grid_content/cell_decoration.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
 import 'package:flutter/material.dart';
 
+import '../content/cell_decoration.dart';
+
 class GridFooter extends StatelessWidget {
   final VoidCallback? onAddRow;
   const GridFooter({Key? key, required this.onAddRow}) : super(key: key);

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


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

@@ -1,5 +1,5 @@
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
 import 'package:flutter/material.dart';
 
 import 'header_cell.dart';

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

@@ -1,4 +1,4 @@
-import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter/material.dart';
 import 'constants.dart';

+ 0 - 14
frontend/app_flowy/lib/workspace/presentation/plugins/grid/widgets/grid_error_page.dart

@@ -1,14 +0,0 @@
-import 'package:flutter/material.dart';
-
-class GridUnknownError extends StatelessWidget {
-  const GridUnknownError({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Container(
-      child: Center(
-        child: CircularProgressIndicator(),
-      ),
-    );
-  }
-}

+ 5 - 5
frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart

@@ -65,20 +65,20 @@ class TrashPluginDisplay extends PluginDisplay {
   Widget? get rightBarItem => null;
 
   @override
-  Widget buildWidget() => const TrashStackPage(key: ValueKey('TrashStackPage'));
+  Widget buildWidget() => const TrashPage(key: ValueKey('TrashPage'));
 
   @override
   List<NavigationItem> get navigationItems => [this];
 }
 
-class TrashStackPage extends StatefulWidget {
-  const TrashStackPage({Key? key}) : super(key: key);
+class TrashPage extends StatefulWidget {
+  const TrashPage({Key? key}) : super(key: key);
 
   @override
-  State<TrashStackPage> createState() => _TrashStackPageState();
+  State<TrashPage> createState() => _TrashPageState();
 }
 
-class _TrashStackPageState extends State<TrashStackPage> {
+class _TrashPageState extends State<TrashPage> {
   final ScrollController _scrollController = ScrollController();
   @override
   Widget build(BuildContext context) {

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

@@ -7,7 +7,6 @@
 
 import 'dart:core' as $core;
 
-import 'package:fixnum/fixnum.dart' as $fixnum;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 import 'grid.pbenum.dart';
@@ -16,8 +15,8 @@ export 'grid.pbenum.dart';
 
 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') ? '' : 'gridId')
-    ..aOM<RepeatedGridFilter>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'filters', subBuilder: RepeatedGridFilter.create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOM<RepeatedFilter>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'filters', subBuilder: RepeatedFilter.create)
     ..aOM<RepeatedFieldOrder>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldOrders', subBuilder: RepeatedFieldOrder.create)
     ..aOM<RepeatedRowOrder>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowOrders', subBuilder: RepeatedRowOrder.create)
     ..hasRequiredFields = false
@@ -25,14 +24,14 @@ class Grid extends $pb.GeneratedMessage {
 
   Grid._() : super();
   factory Grid({
-    $core.String? gridId,
-    RepeatedGridFilter? filters,
+    $core.String? id,
+    RepeatedFilter? filters,
     RepeatedFieldOrder? fieldOrders,
     RepeatedRowOrder? rowOrders,
   }) {
     final _result = create();
-    if (gridId != null) {
-      _result.gridId = gridId;
+    if (id != null) {
+      _result.id = id;
     }
     if (filters != null) {
       _result.filters = filters;
@@ -67,24 +66,24 @@ class Grid extends $pb.GeneratedMessage {
   static Grid? _defaultInstance;
 
   @$pb.TagNumber(1)
-  $core.String get gridId => $_getSZ(0);
+  $core.String get id => $_getSZ(0);
   @$pb.TagNumber(1)
-  set gridId($core.String v) { $_setString(0, v); }
+  set id($core.String v) { $_setString(0, v); }
   @$pb.TagNumber(1)
-  $core.bool hasGridId() => $_has(0);
+  $core.bool hasId() => $_has(0);
   @$pb.TagNumber(1)
-  void clearGridId() => clearField(1);
+  void clearId() => clearField(1);
 
   @$pb.TagNumber(2)
-  RepeatedGridFilter get filters => $_getN(1);
+  RepeatedFilter get filters => $_getN(1);
   @$pb.TagNumber(2)
-  set filters(RepeatedGridFilter v) { setField(2, v); }
+  set filters(RepeatedFilter v) { setField(2, v); }
   @$pb.TagNumber(2)
   $core.bool hasFilters() => $_has(1);
   @$pb.TagNumber(2)
   void clearFilters() => clearField(2);
   @$pb.TagNumber(2)
-  RepeatedGridFilter ensureFilters() => $_ensure(1);
+  RepeatedFilter ensureFilters() => $_ensure(1);
 
   @$pb.TagNumber(3)
   RepeatedFieldOrder get fieldOrders => $_getN(2);
@@ -109,122 +108,6 @@ class Grid extends $pb.GeneratedMessage {
   RepeatedRowOrder ensureRowOrders() => $_ensure(3);
 }
 
-class GridFilter extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridFilter', 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')
-    ..hasRequiredFields = false
-  ;
-
-  GridFilter._() : super();
-  factory GridFilter({
-    $core.String? id,
-    $core.String? name,
-    $core.String? desc,
-  }) {
-    final _result = create();
-    if (id != null) {
-      _result.id = id;
-    }
-    if (name != null) {
-      _result.name = name;
-    }
-    if (desc != null) {
-      _result.desc = desc;
-    }
-    return _result;
-  }
-  factory GridFilter.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory GridFilter.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')
-  GridFilter clone() => GridFilter()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  GridFilter copyWith(void Function(GridFilter) updates) => super.copyWith((message) => updates(message as GridFilter)) as GridFilter; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static GridFilter create() => GridFilter._();
-  GridFilter createEmptyInstance() => create();
-  static $pb.PbList<GridFilter> createRepeated() => $pb.PbList<GridFilter>();
-  @$core.pragma('dart2js:noInline')
-  static GridFilter getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridFilter>(create);
-  static GridFilter? _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);
-}
-
-class RepeatedGridFilter extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedGridFilter', createEmptyInstance: create)
-    ..pc<GridFilter>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: GridFilter.create)
-    ..hasRequiredFields = false
-  ;
-
-  RepeatedGridFilter._() : super();
-  factory RepeatedGridFilter({
-    $core.Iterable<GridFilter>? items,
-  }) {
-    final _result = create();
-    if (items != null) {
-      _result.items.addAll(items);
-    }
-    return _result;
-  }
-  factory RepeatedGridFilter.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory RepeatedGridFilter.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')
-  RepeatedGridFilter clone() => RepeatedGridFilter()..mergeFromMessage(this);
-  @$core.Deprecated(
-  'Using this can add significant overhead to your binary. '
-  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-  'Will be removed in next major version')
-  RepeatedGridFilter copyWith(void Function(RepeatedGridFilter) updates) => super.copyWith((message) => updates(message as RepeatedGridFilter)) as RepeatedGridFilter; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static RepeatedGridFilter create() => RepeatedGridFilter._();
-  RepeatedGridFilter createEmptyInstance() => create();
-  static $pb.PbList<RepeatedGridFilter> createRepeated() => $pb.PbList<RepeatedGridFilter>();
-  @$core.pragma('dart2js:noInline')
-  static RepeatedGridFilter getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedGridFilter>(create);
-  static RepeatedGridFilter? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.List<GridFilter> get items => $_getList(0);
-}
-
 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')
@@ -678,21 +561,19 @@ class RepeatedRowOrder extends $pb.GeneratedMessage {
   $core.List<RowOrder> get items => $_getList(0);
 }
 
-class GridRow extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridRow', createEmptyInstance: create)
+class RawRow extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RawRow', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
     ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
-    ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'modifiedTime')
-    ..m<$core.String, GridCell>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cellByFieldId', entryClassName: 'GridRow.CellByFieldIdEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OM, valueCreator: GridCell.create)
+    ..m<$core.String, RawCell>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cellByFieldId', entryClassName: 'RawRow.CellByFieldIdEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OM, valueCreator: RawCell.create)
     ..hasRequiredFields = false
   ;
 
-  GridRow._() : super();
-  factory GridRow({
+  RawRow._() : super();
+  factory RawRow({
     $core.String? id,
     $core.String? gridId,
-    $fixnum.Int64? modifiedTime,
-    $core.Map<$core.String, GridCell>? cellByFieldId,
+    $core.Map<$core.String, RawCell>? cellByFieldId,
   }) {
     final _result = create();
     if (id != null) {
@@ -701,34 +582,31 @@ class GridRow extends $pb.GeneratedMessage {
     if (gridId != null) {
       _result.gridId = gridId;
     }
-    if (modifiedTime != null) {
-      _result.modifiedTime = modifiedTime;
-    }
     if (cellByFieldId != null) {
       _result.cellByFieldId.addAll(cellByFieldId);
     }
     return _result;
   }
-  factory GridRow.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory GridRow.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory RawRow.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RawRow.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')
-  GridRow clone() => GridRow()..mergeFromMessage(this);
+  RawRow clone() => RawRow()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  GridRow copyWith(void Function(GridRow) updates) => super.copyWith((message) => updates(message as GridRow)) as GridRow; // ignore: deprecated_member_use
+  RawRow copyWith(void Function(RawRow) updates) => super.copyWith((message) => updates(message as RawRow)) as RawRow; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static GridRow create() => GridRow._();
-  GridRow createEmptyInstance() => create();
-  static $pb.PbList<GridRow> createRepeated() => $pb.PbList<GridRow>();
+  static RawRow create() => RawRow._();
+  RawRow createEmptyInstance() => create();
+  static $pb.PbList<RawRow> createRepeated() => $pb.PbList<RawRow>();
   @$core.pragma('dart2js:noInline')
-  static GridRow getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridRow>(create);
-  static GridRow? _defaultInstance;
+  static RawRow getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RawRow>(create);
+  static RawRow? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get id => $_getSZ(0);
@@ -749,27 +627,107 @@ class GridRow extends $pb.GeneratedMessage {
   void clearGridId() => clearField(2);
 
   @$pb.TagNumber(3)
-  $fixnum.Int64 get modifiedTime => $_getI64(2);
+  $core.Map<$core.String, RawCell> get cellByFieldId => $_getMap(2);
+}
+
+class RawCell extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RawCell', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId')
+    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
+    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
+    ..hasRequiredFields = false
+  ;
+
+  RawCell._() : super();
+  factory RawCell({
+    $core.String? id,
+    $core.String? rowId,
+    $core.String? fieldId,
+    $core.String? data,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (rowId != null) {
+      _result.rowId = rowId;
+    }
+    if (fieldId != null) {
+      _result.fieldId = fieldId;
+    }
+    if (data != null) {
+      _result.data = data;
+    }
+    return _result;
+  }
+  factory RawCell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RawCell.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')
+  RawCell clone() => RawCell()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RawCell copyWith(void Function(RawCell) updates) => super.copyWith((message) => updates(message as RawCell)) as RawCell; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RawCell create() => RawCell._();
+  RawCell createEmptyInstance() => create();
+  static $pb.PbList<RawCell> createRepeated() => $pb.PbList<RawCell>();
+  @$core.pragma('dart2js:noInline')
+  static RawCell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RawCell>(create);
+  static RawCell? _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 rowId => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set rowId($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasRowId() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearRowId() => clearField(2);
+
+  @$pb.TagNumber(3)
+  $core.String get fieldId => $_getSZ(2);
   @$pb.TagNumber(3)
-  set modifiedTime($fixnum.Int64 v) { $_setInt64(2, v); }
+  set fieldId($core.String v) { $_setString(2, v); }
   @$pb.TagNumber(3)
-  $core.bool hasModifiedTime() => $_has(2);
+  $core.bool hasFieldId() => $_has(2);
   @$pb.TagNumber(3)
-  void clearModifiedTime() => clearField(3);
+  void clearFieldId() => clearField(3);
 
   @$pb.TagNumber(4)
-  $core.Map<$core.String, GridCell> get cellByFieldId => $_getMap(3);
+  $core.String get data => $_getSZ(3);
+  @$pb.TagNumber(4)
+  set data($core.String v) { $_setString(3, v); }
+  @$pb.TagNumber(4)
+  $core.bool hasData() => $_has(3);
+  @$pb.TagNumber(4)
+  void clearData() => clearField(4);
 }
 
 class RepeatedRow extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedRow', createEmptyInstance: create)
-    ..pc<GridRow>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: GridRow.create)
+    ..pc<Row>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Row.create)
     ..hasRequiredFields = false
   ;
 
   RepeatedRow._() : super();
   factory RepeatedRow({
-    $core.Iterable<GridRow>? items,
+    $core.Iterable<Row>? items,
   }) {
     final _result = create();
     if (items != null) {
@@ -799,22 +757,75 @@ class RepeatedRow extends $pb.GeneratedMessage {
   static RepeatedRow? _defaultInstance;
 
   @$pb.TagNumber(1)
-  $core.List<GridRow> get items => $_getList(0);
+  $core.List<Row> get items => $_getList(0);
 }
 
-class GridCell extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridCell', createEmptyInstance: create)
+class Row extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Row', createEmptyInstance: create)
     ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
-    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId')
-    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
-    ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')
+    ..m<$core.String, Cell>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cellByFieldId', entryClassName: 'Row.CellByFieldIdEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OM, valueCreator: Cell.create)
     ..hasRequiredFields = false
   ;
 
-  GridCell._() : super();
-  factory GridCell({
+  Row._() : super();
+  factory Row({
+    $core.String? id,
+    $core.Map<$core.String, Cell>? cellByFieldId,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (cellByFieldId != null) {
+      _result.cellByFieldId.addAll(cellByFieldId);
+    }
+    return _result;
+  }
+  factory Row.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Row.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')
+  Row clone() => Row()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  Row copyWith(void Function(Row) updates) => super.copyWith((message) => updates(message as Row)) as Row; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static Row create() => Row._();
+  Row createEmptyInstance() => create();
+  static $pb.PbList<Row> createRepeated() => $pb.PbList<Row>();
+  @$core.pragma('dart2js:noInline')
+  static Row getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Row>(create);
+  static Row? _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.Map<$core.String, Cell> get cellByFieldId => $_getMap(1);
+}
+
+class Cell extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Cell', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
+    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')
+    ..hasRequiredFields = false
+  ;
+
+  Cell._() : super();
+  factory Cell({
     $core.String? id,
-    $core.String? rowId,
     $core.String? fieldId,
     $core.String? content,
   }) {
@@ -822,9 +833,6 @@ class GridCell extends $pb.GeneratedMessage {
     if (id != null) {
       _result.id = id;
     }
-    if (rowId != null) {
-      _result.rowId = rowId;
-    }
     if (fieldId != null) {
       _result.fieldId = fieldId;
     }
@@ -833,26 +841,26 @@ class GridCell extends $pb.GeneratedMessage {
     }
     return _result;
   }
-  factory GridCell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory GridCell.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory Cell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Cell.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')
-  GridCell clone() => GridCell()..mergeFromMessage(this);
+  Cell clone() => Cell()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  GridCell copyWith(void Function(GridCell) updates) => super.copyWith((message) => updates(message as GridCell)) as GridCell; // ignore: deprecated_member_use
+  Cell copyWith(void Function(Cell) updates) => super.copyWith((message) => updates(message as Cell)) as Cell; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static GridCell create() => GridCell._();
-  GridCell createEmptyInstance() => create();
-  static $pb.PbList<GridCell> createRepeated() => $pb.PbList<GridCell>();
+  static Cell create() => Cell._();
+  Cell createEmptyInstance() => create();
+  static $pb.PbList<Cell> createRepeated() => $pb.PbList<Cell>();
   @$core.pragma('dart2js:noInline')
-  static GridCell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridCell>(create);
-  static GridCell? _defaultInstance;
+  static Cell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Cell>(create);
+  static Cell? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get id => $_getSZ(0);
@@ -864,31 +872,22 @@ class GridCell extends $pb.GeneratedMessage {
   void clearId() => clearField(1);
 
   @$pb.TagNumber(2)
-  $core.String get rowId => $_getSZ(1);
+  $core.String get fieldId => $_getSZ(1);
   @$pb.TagNumber(2)
-  set rowId($core.String v) { $_setString(1, v); }
+  set fieldId($core.String v) { $_setString(1, v); }
   @$pb.TagNumber(2)
-  $core.bool hasRowId() => $_has(1);
+  $core.bool hasFieldId() => $_has(1);
   @$pb.TagNumber(2)
-  void clearRowId() => clearField(2);
+  void clearFieldId() => clearField(2);
 
   @$pb.TagNumber(3)
-  $core.String get fieldId => $_getSZ(2);
+  $core.String get content => $_getSZ(2);
   @$pb.TagNumber(3)
-  set fieldId($core.String v) { $_setString(2, v); }
+  set content($core.String v) { $_setString(2, v); }
   @$pb.TagNumber(3)
-  $core.bool hasFieldId() => $_has(2);
+  $core.bool hasContent() => $_has(2);
   @$pb.TagNumber(3)
-  void clearFieldId() => clearField(3);
-
-  @$pb.TagNumber(4)
-  $core.String get content => $_getSZ(3);
-  @$pb.TagNumber(4)
-  set content($core.String v) { $_setString(3, v); }
-  @$pb.TagNumber(4)
-  $core.bool hasContent() => $_has(3);
-  @$pb.TagNumber(4)
-  void clearContent() => clearField(4);
+  void clearContent() => clearField(3);
 }
 
 class CreateGridPayload extends $pb.GeneratedMessage {
@@ -985,3 +984,119 @@ class GridId extends $pb.GeneratedMessage {
   void clearValue() => clearField(1);
 }
 
+class Filter extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Filter', 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')
+    ..hasRequiredFields = false
+  ;
+
+  Filter._() : super();
+  factory Filter({
+    $core.String? id,
+    $core.String? name,
+    $core.String? desc,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (name != null) {
+      _result.name = name;
+    }
+    if (desc != null) {
+      _result.desc = desc;
+    }
+    return _result;
+  }
+  factory Filter.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Filter.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')
+  Filter clone() => Filter()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  Filter copyWith(void Function(Filter) updates) => super.copyWith((message) => updates(message as Filter)) as Filter; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static Filter create() => Filter._();
+  Filter createEmptyInstance() => create();
+  static $pb.PbList<Filter> createRepeated() => $pb.PbList<Filter>();
+  @$core.pragma('dart2js:noInline')
+  static Filter getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Filter>(create);
+  static Filter? _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);
+}
+
+class RepeatedFilter extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedFilter', createEmptyInstance: create)
+    ..pc<Filter>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Filter.create)
+    ..hasRequiredFields = false
+  ;
+
+  RepeatedFilter._() : super();
+  factory RepeatedFilter({
+    $core.Iterable<Filter>? items,
+  }) {
+    final _result = create();
+    if (items != null) {
+      _result.items.addAll(items);
+    }
+    return _result;
+  }
+  factory RepeatedFilter.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RepeatedFilter.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')
+  RepeatedFilter clone() => RepeatedFilter()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RepeatedFilter copyWith(void Function(RepeatedFilter) updates) => super.copyWith((message) => updates(message as RepeatedFilter)) as RepeatedFilter; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RepeatedFilter create() => RepeatedFilter._();
+  RepeatedFilter createEmptyInstance() => create();
+  static $pb.PbList<RepeatedFilter> createRepeated() => $pb.PbList<RepeatedFilter>();
+  @$core.pragma('dart2js:noInline')
+  static RepeatedFilter getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedFilter>(create);
+  static RepeatedFilter? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.List<Filter> get items => $_getList(0);
+}
+

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

@@ -27,37 +27,15 @@ final $typed_data.Uint8List fieldTypeDescriptor = $convert.base64Decode('CglGaWV
 const Grid$json = const {
   '1': 'Grid',
   '2': const [
-    const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
-    const {'1': 'filters', '3': 2, '4': 1, '5': 11, '6': '.RepeatedGridFilter', '10': 'filters'},
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'filters', '3': 2, '4': 1, '5': 11, '6': '.RepeatedFilter', '10': 'filters'},
     const {'1': 'field_orders', '3': 3, '4': 1, '5': 11, '6': '.RepeatedFieldOrder', '10': 'fieldOrders'},
     const {'1': 'row_orders', '3': 4, '4': 1, '5': 11, '6': '.RepeatedRowOrder', '10': 'rowOrders'},
   ],
 };
 
 /// Descriptor for `Grid`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridDescriptor = $convert.base64Decode('CgRHcmlkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBItCgdmaWx0ZXJzGAIgASgLMhMuUmVwZWF0ZWRHcmlkRmlsdGVyUgdmaWx0ZXJzEjYKDGZpZWxkX29yZGVycxgDIAEoCzITLlJlcGVhdGVkRmllbGRPcmRlclILZmllbGRPcmRlcnMSMAoKcm93X29yZGVycxgEIAEoCzIRLlJlcGVhdGVkUm93T3JkZXJSCXJvd09yZGVycw==');
-@$core.Deprecated('Use gridFilterDescriptor instead')
-const GridFilter$json = const {
-  '1': 'GridFilter',
-  '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'},
-  ],
-};
-
-/// Descriptor for `GridFilter`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridFilterDescriptor = $convert.base64Decode('CgpHcmlkRmlsdGVyEg4KAmlkGAEgASgJUgJpZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2M=');
-@$core.Deprecated('Use repeatedGridFilterDescriptor instead')
-const RepeatedGridFilter$json = const {
-  '1': 'RepeatedGridFilter',
-  '2': const [
-    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.GridFilter', '10': 'items'},
-  ],
-};
-
-/// Descriptor for `RepeatedGridFilter`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List repeatedGridFilterDescriptor = $convert.base64Decode('ChJSZXBlYXRlZEdyaWRGaWx0ZXISIQoFaXRlbXMYASADKAsyCy5HcmlkRmlsdGVyUgVpdGVtcw==');
+final $typed_data.Uint8List gridDescriptor = $convert.base64Decode('CgRHcmlkEg4KAmlkGAEgASgJUgJpZBIpCgdmaWx0ZXJzGAIgASgLMg8uUmVwZWF0ZWRGaWx0ZXJSB2ZpbHRlcnMSNgoMZmllbGRfb3JkZXJzGAMgASgLMhMuUmVwZWF0ZWRGaWVsZE9yZGVyUgtmaWVsZE9yZGVycxIwCgpyb3dfb3JkZXJzGAQgASgLMhEuUmVwZWF0ZWRSb3dPcmRlclIJcm93T3JkZXJz');
 @$core.Deprecated('Use fieldOrderDescriptor instead')
 const FieldOrder$json = const {
   '1': 'FieldOrder',
@@ -138,53 +116,86 @@ const RepeatedRowOrder$json = const {
 
 /// Descriptor for `RepeatedRowOrder`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List repeatedRowOrderDescriptor = $convert.base64Decode('ChBSZXBlYXRlZFJvd09yZGVyEh8KBWl0ZW1zGAEgAygLMgkuUm93T3JkZXJSBWl0ZW1z');
-@$core.Deprecated('Use gridRowDescriptor instead')
-const GridRow$json = const {
-  '1': 'GridRow',
+@$core.Deprecated('Use rawRowDescriptor instead')
+const RawRow$json = const {
+  '1': 'RawRow',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
     const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'},
-    const {'1': 'modified_time', '3': 3, '4': 1, '5': 3, '10': 'modifiedTime'},
-    const {'1': 'cell_by_field_id', '3': 4, '4': 3, '5': 11, '6': '.GridRow.CellByFieldIdEntry', '10': 'cellByFieldId'},
+    const {'1': 'cell_by_field_id', '3': 3, '4': 3, '5': 11, '6': '.RawRow.CellByFieldIdEntry', '10': 'cellByFieldId'},
   ],
-  '3': const [GridRow_CellByFieldIdEntry$json],
+  '3': const [RawRow_CellByFieldIdEntry$json],
 };
 
-@$core.Deprecated('Use gridRowDescriptor instead')
-const GridRow_CellByFieldIdEntry$json = const {
+@$core.Deprecated('Use rawRowDescriptor instead')
+const RawRow_CellByFieldIdEntry$json = const {
   '1': 'CellByFieldIdEntry',
   '2': const [
     const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
-    const {'1': 'value', '3': 2, '4': 1, '5': 11, '6': '.GridCell', '10': 'value'},
+    const {'1': 'value', '3': 2, '4': 1, '5': 11, '6': '.RawCell', '10': 'value'},
   ],
   '7': const {'7': true},
 };
 
-/// Descriptor for `GridRow`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridRowDescriptor = $convert.base64Decode('CgdHcmlkUm93Eg4KAmlkGAEgASgJUgJpZBIXCgdncmlkX2lkGAIgASgJUgZncmlkSWQSIwoNbW9kaWZpZWRfdGltZRgDIAEoA1IMbW9kaWZpZWRUaW1lEkQKEGNlbGxfYnlfZmllbGRfaWQYBCADKAsyGy5HcmlkUm93LkNlbGxCeUZpZWxkSWRFbnRyeVINY2VsbEJ5RmllbGRJZBpLChJDZWxsQnlGaWVsZElkRW50cnkSEAoDa2V5GAEgASgJUgNrZXkSHwoFdmFsdWUYAiABKAsyCS5HcmlkQ2VsbFIFdmFsdWU6AjgB');
+/// Descriptor for `RawRow`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List rawRowDescriptor = $convert.base64Decode('CgZSYXdSb3cSDgoCaWQYASABKAlSAmlkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZBJDChBjZWxsX2J5X2ZpZWxkX2lkGAMgAygLMhouUmF3Um93LkNlbGxCeUZpZWxkSWRFbnRyeVINY2VsbEJ5RmllbGRJZBpKChJDZWxsQnlGaWVsZElkRW50cnkSEAoDa2V5GAEgASgJUgNrZXkSHgoFdmFsdWUYAiABKAsyCC5SYXdDZWxsUgV2YWx1ZToCOAE=');
+@$core.Deprecated('Use rawCellDescriptor instead')
+const RawCell$json = const {
+  '1': 'RawCell',
+  '2': const [
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'row_id', '3': 2, '4': 1, '5': 9, '10': 'rowId'},
+    const {'1': 'field_id', '3': 3, '4': 1, '5': 9, '10': 'fieldId'},
+    const {'1': 'data', '3': 4, '4': 1, '5': 9, '10': 'data'},
+  ],
+};
+
+/// Descriptor for `RawCell`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List rawCellDescriptor = $convert.base64Decode('CgdSYXdDZWxsEg4KAmlkGAEgASgJUgJpZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElkEhIKBGRhdGEYBCABKAlSBGRhdGE=');
 @$core.Deprecated('Use repeatedRowDescriptor instead')
 const RepeatedRow$json = const {
   '1': 'RepeatedRow',
   '2': const [
-    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.GridRow', '10': 'items'},
+    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Row', '10': 'items'},
   ],
 };
 
 /// Descriptor for `RepeatedRow`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List repeatedRowDescriptor = $convert.base64Decode('CgtSZXBlYXRlZFJvdxIeCgVpdGVtcxgBIAMoCzIILkdyaWRSb3dSBWl0ZW1z');
-@$core.Deprecated('Use gridCellDescriptor instead')
-const GridCell$json = const {
-  '1': 'GridCell',
+final $typed_data.Uint8List repeatedRowDescriptor = $convert.base64Decode('CgtSZXBlYXRlZFJvdxIaCgVpdGVtcxgBIAMoCzIELlJvd1IFaXRlbXM=');
+@$core.Deprecated('Use rowDescriptor instead')
+const Row$json = const {
+  '1': 'Row',
   '2': const [
     const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
-    const {'1': 'row_id', '3': 2, '4': 1, '5': 9, '10': 'rowId'},
-    const {'1': 'field_id', '3': 3, '4': 1, '5': 9, '10': 'fieldId'},
-    const {'1': 'content', '3': 4, '4': 1, '5': 9, '10': 'content'},
+    const {'1': 'cell_by_field_id', '3': 2, '4': 3, '5': 11, '6': '.Row.CellByFieldIdEntry', '10': 'cellByFieldId'},
   ],
+  '3': const [Row_CellByFieldIdEntry$json],
 };
 
-/// Descriptor for `GridCell`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridCellDescriptor = $convert.base64Decode('CghHcmlkQ2VsbBIOCgJpZBgBIAEoCVICaWQSFQoGcm93X2lkGAIgASgJUgVyb3dJZBIZCghmaWVsZF9pZBgDIAEoCVIHZmllbGRJZBIYCgdjb250ZW50GAQgASgJUgdjb250ZW50');
+@$core.Deprecated('Use rowDescriptor instead')
+const Row_CellByFieldIdEntry$json = const {
+  '1': 'CellByFieldIdEntry',
+  '2': const [
+    const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
+    const {'1': 'value', '3': 2, '4': 1, '5': 11, '6': '.Cell', '10': 'value'},
+  ],
+  '7': const {'7': true},
+};
+
+/// Descriptor for `Row`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List rowDescriptor = $convert.base64Decode('CgNSb3cSDgoCaWQYASABKAlSAmlkEkAKEGNlbGxfYnlfZmllbGRfaWQYAiADKAsyFy5Sb3cuQ2VsbEJ5RmllbGRJZEVudHJ5Ug1jZWxsQnlGaWVsZElkGkcKEkNlbGxCeUZpZWxkSWRFbnRyeRIQCgNrZXkYASABKAlSA2tleRIbCgV2YWx1ZRgCIAEoCzIFLkNlbGxSBXZhbHVlOgI4AQ==');
+@$core.Deprecated('Use cellDescriptor instead')
+const Cell$json = const {
+  '1': 'Cell',
+  '2': const [
+    const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+    const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'},
+    const {'1': 'content', '3': 3, '4': 1, '5': 9, '10': 'content'},
+  ],
+};
+
+/// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEg4KAmlkGAEgASgJUgJpZBIZCghmaWVsZF9pZBgCIAEoCVIHZmllbGRJZBIYCgdjb250ZW50GAMgASgJUgdjb250ZW50');
 @$core.Deprecated('Use createGridPayloadDescriptor instead')
 const CreateGridPayload$json = const {
   '1': 'CreateGridPayload',
@@ -205,3 +216,25 @@ const GridId$json = const {
 
 /// Descriptor for `GridId`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List gridIdDescriptor = $convert.base64Decode('CgZHcmlkSWQSFAoFdmFsdWUYASABKAlSBXZhbHVl');
+@$core.Deprecated('Use filterDescriptor instead')
+const Filter$json = const {
+  '1': 'Filter',
+  '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'},
+  ],
+};
+
+/// Descriptor for `Filter`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List filterDescriptor = $convert.base64Decode('CgZGaWx0ZXISDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYw==');
+@$core.Deprecated('Use repeatedFilterDescriptor instead')
+const RepeatedFilter$json = const {
+  '1': 'RepeatedFilter',
+  '2': const [
+    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Filter', '10': 'items'},
+  ],
+};
+
+/// Descriptor for `RepeatedFilter`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List repeatedFilterDescriptor = $convert.base64Decode('Cg5SZXBlYXRlZEZpbHRlchIdCgVpdGVtcxgBIAMoCzIHLkZpbHRlclIFaXRlbXM=');

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

@@ -1,7 +1,7 @@
 use crate::controller::GridManager;
 use flowy_error::FlowyError;
 use flowy_grid_data_model::entities::{
-    CreateGridPayload, Grid, GridId, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder,
+    CreateGridPayload, Grid, GridId, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder,
 };
 use lib_dispatch::prelude::{AppData, Data, DataResult};
 use std::sync::Arc;
@@ -28,7 +28,7 @@ pub(crate) async fn open_grid_handler(
 pub(crate) async fn get_rows_handler(
     data: Data<RepeatedRowOrder>,
     controller: AppData<Arc<GridManager>>,
-) -> DataResult<Grid, FlowyError> {
+) -> DataResult<RepeatedRow, FlowyError> {
     let row_orders: RepeatedRowOrder = data.into_inner();
 
     todo!()
@@ -38,7 +38,7 @@ pub(crate) async fn get_rows_handler(
 pub(crate) async fn get_fields_handler(
     data: Data<RepeatedFieldOrder>,
     controller: AppData<Arc<GridManager>>,
-) -> DataResult<Grid, FlowyError> {
+) -> DataResult<RepeatedField, FlowyError> {
     let field_orders: RepeatedFieldOrder = data.into_inner();
 
     todo!()
@@ -48,8 +48,8 @@ pub(crate) async fn get_fields_handler(
 pub(crate) async fn create_row_handler(
     data: Data<GridId>,
     controller: AppData<Arc<GridManager>>,
-) -> DataResult<Grid, FlowyError> {
+) -> Result<(), FlowyError> {
     let id: GridId = data.into_inner();
 
-    todo!()
+    Ok(())
 }

+ 46 - 28
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -6,10 +6,10 @@ use strum_macros::{Display, EnumIter, EnumString};
 #[derive(Debug, Default, ProtoBuf)]
 pub struct Grid {
     #[pb(index = 1)]
-    pub grid_id: String,
+    pub id: String,
 
     #[pb(index = 2)]
-    pub filters: RepeatedGridFilter,
+    pub filters: RepeatedFilter,
 
     #[pb(index = 3)]
     pub field_orders: RepeatedFieldOrder,
@@ -18,24 +18,6 @@ pub struct Grid {
     pub row_orders: RepeatedRowOrder,
 }
 
-#[derive(Debug, Default, ProtoBuf)]
-pub struct GridFilter {
-    #[pb(index = 1)]
-    pub id: String,
-
-    #[pb(index = 2)]
-    pub name: String,
-
-    #[pb(index = 3)]
-    pub desc: String,
-}
-
-#[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedGridFilter {
-    #[pb(index = 1)]
-    pub items: Vec<GridFilter>,
-}
-
 #[derive(Debug, Default, ProtoBuf)]
 pub struct FieldOrder {
     #[pb(index = 1)]
@@ -167,7 +149,7 @@ pub struct RepeatedRowOrder {
 }
 
 #[derive(Debug, Default, ProtoBuf)]
-pub struct GridRow {
+pub struct RawRow {
     #[pb(index = 1)]
     pub id: String,
 
@@ -175,30 +157,48 @@ pub struct GridRow {
     pub grid_id: String,
 
     #[pb(index = 3)]
-    pub modified_time: i64,
+    pub cell_by_field_id: HashMap<String, RawCell>,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RawCell {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub row_id: String,
+
+    #[pb(index = 3)]
+    pub field_id: String,
 
     #[pb(index = 4)]
-    pub cell_by_field_id: HashMap<String, GridCell>,
+    pub data: String,
 }
 
 #[derive(Debug, Default, ProtoBuf)]
 pub struct RepeatedRow {
     #[pb(index = 1)]
-    pub items: Vec<GridRow>,
+    pub items: Vec<Row>,
 }
 
 #[derive(Debug, Default, ProtoBuf)]
-pub struct GridCell {
+pub struct Row {
     #[pb(index = 1)]
     pub id: String,
 
     #[pb(index = 2)]
-    pub row_id: String,
+    pub cell_by_field_id: HashMap<String, Cell>,
+}
 
-    #[pb(index = 3)]
+#[derive(Debug, Default, ProtoBuf)]
+pub struct Cell {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
     pub field_id: String,
 
-    #[pb(index = 4)]
+    #[pb(index = 3)]
     pub content: String,
 }
 
@@ -213,3 +213,21 @@ pub struct GridId {
     #[pb(index = 1)]
     pub value: String,
 }
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct Filter {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub name: String,
+
+    #[pb(index = 3)]
+    pub desc: String,
+}
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct RepeatedFilter {
+    #[pb(index = 1)]
+    pub items: Vec<Filter>,
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 386 - 228
shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs


+ 26 - 18
shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

@@ -1,19 +1,11 @@
 syntax = "proto3";
 
 message Grid {
-    string grid_id = 1;
-    RepeatedGridFilter filters = 2;
+    string id = 1;
+    RepeatedFilter filters = 2;
     RepeatedFieldOrder field_orders = 3;
     RepeatedRowOrder row_orders = 4;
 }
-message GridFilter {
-    string id = 1;
-    string name = 2;
-    string desc = 3;
-}
-message RepeatedGridFilter {
-    repeated GridFilter items = 1;
-}
 message FieldOrder {
     string field_id = 1;
     bool visibility = 2;
@@ -45,20 +37,28 @@ message RowOrder {
 message RepeatedRowOrder {
     repeated RowOrder items = 1;
 }
-message GridRow {
+message RawRow {
     string id = 1;
     string grid_id = 2;
-    int64 modified_time = 3;
-    map<string, GridCell> cell_by_field_id = 4;
+    map<string, RawCell> cell_by_field_id = 3;
 }
-message RepeatedRow {
-    repeated GridRow items = 1;
-}
-message GridCell {
+message RawCell {
     string id = 1;
     string row_id = 2;
     string field_id = 3;
-    string content = 4;
+    string data = 4;
+}
+message RepeatedRow {
+    repeated Row items = 1;
+}
+message Row {
+    string id = 1;
+    map<string, Cell> cell_by_field_id = 2;
+}
+message Cell {
+    string id = 1;
+    string field_id = 2;
+    string content = 3;
 }
 message CreateGridPayload {
     string name = 1;
@@ -66,6 +66,14 @@ message CreateGridPayload {
 message GridId {
     string value = 1;
 }
+message Filter {
+    string id = 1;
+    string name = 2;
+    string desc = 3;
+}
+message RepeatedFilter {
+    repeated Filter items = 1;
+}
 enum FieldType {
     RichText = 0;
     Number = 1;

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است