소스 검색

feat: add grid event

appflowy 3 년 전
부모
커밋
03f34b143d
28개의 변경된 파일1801개의 추가작업 그리고 15개의 파일을 삭제
  1. 37 0
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
  2. 907 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
  3. 34 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbenum.dart
  4. 187 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
  5. 9 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbserver.dart
  6. 2 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart
  7. 11 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pb.dart
  8. 26 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
  9. 21 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
  10. 9 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbserver.dart
  11. 2 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart
  12. 22 0
      frontend/rust-lib/Cargo.lock
  13. 4 4
      frontend/rust-lib/flowy-folder/Cargo.toml
  14. 17 0
      frontend/rust-lib/flowy-grid/Cargo.toml
  15. 3 0
      frontend/rust-lib/flowy-grid/Flowy.toml
  16. 7 0
      frontend/rust-lib/flowy-grid/build.rs
  17. 1 0
      frontend/rust-lib/flowy-grid/src/controller.rs
  18. 23 0
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  19. 26 0
      frontend/rust-lib/flowy-grid/src/event_map.rs
  20. 5 8
      frontend/rust-lib/flowy-grid/src/lib.rs
  21. 4 0
      frontend/rust-lib/flowy-grid/src/protobuf/mod.rs
  22. 91 0
      frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
  23. 5 0
      frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs
  24. 6 0
      frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
  25. 2 1
      frontend/rust-lib/flowy-sdk/Cargo.toml
  26. 12 0
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  27. 322 2
      shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
  28. 6 0
      shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto

+ 37 - 0
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart

@@ -0,0 +1,37 @@
+
+/// Auto generate. Do not edit
+part of '../../dispatch.dart';
+class GridEventCreateGrid {
+     CreateGridPayload request;
+     GridEventCreateGrid(this.request);
+
+    Future<Either<Grid, FlowyError>> send() {
+    final request = FFIRequest.create()
+          ..event = GridEvent.CreateGrid.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+           (okBytes) => left(Grid.fromBuffer(okBytes)),
+           (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+        ));
+    }
+}
+
+class GridEventOpenGrid {
+     GridId request;
+     GridEventOpenGrid(this.request);
+
+    Future<Either<Grid, FlowyError>> send() {
+    final request = FFIRequest.create()
+          ..event = GridEvent.OpenGrid.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+           (okBytes) => left(Grid.fromBuffer(okBytes)),
+           (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+        ));
+    }
+}
+

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

@@ -0,0 +1,907 @@
+///
+//  Generated code. Do not modify.
+//  source: grid.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+import 'dart:core' as $core;
+
+import 'package:fixnum/fixnum.dart' as $fixnum;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+import 'grid.pbenum.dart';
+
+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)
+    ..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
+  ;
+
+  Grid._() : super();
+  factory Grid({
+    $core.String? gridId,
+    RepeatedGridFilter? filters,
+    RepeatedFieldOrder? fieldOrders,
+    RepeatedRowOrder? rowOrders,
+  }) {
+    final _result = create();
+    if (gridId != null) {
+      _result.gridId = gridId;
+    }
+    if (filters != null) {
+      _result.filters = filters;
+    }
+    if (fieldOrders != null) {
+      _result.fieldOrders = fieldOrders;
+    }
+    if (rowOrders != null) {
+      _result.rowOrders = rowOrders;
+    }
+    return _result;
+  }
+  factory Grid.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory Grid.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')
+  Grid clone() => Grid()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  Grid copyWith(void Function(Grid) updates) => super.copyWith((message) => updates(message as Grid)) as Grid; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static Grid create() => Grid._();
+  Grid createEmptyInstance() => create();
+  static $pb.PbList<Grid> createRepeated() => $pb.PbList<Grid>();
+  @$core.pragma('dart2js:noInline')
+  static Grid getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Grid>(create);
+  static Grid? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get gridId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set gridId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasGridId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearGridId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  RepeatedGridFilter get filters => $_getN(1);
+  @$pb.TagNumber(2)
+  set filters(RepeatedGridFilter 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);
+
+  @$pb.TagNumber(3)
+  RepeatedFieldOrder get fieldOrders => $_getN(2);
+  @$pb.TagNumber(3)
+  set fieldOrders(RepeatedFieldOrder v) { setField(3, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasFieldOrders() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearFieldOrders() => clearField(3);
+  @$pb.TagNumber(3)
+  RepeatedFieldOrder ensureFieldOrders() => $_ensure(2);
+
+  @$pb.TagNumber(4)
+  RepeatedRowOrder get rowOrders => $_getN(3);
+  @$pb.TagNumber(4)
+  set rowOrders(RepeatedRowOrder v) { setField(4, v); }
+  @$pb.TagNumber(4)
+  $core.bool hasRowOrders() => $_has(3);
+  @$pb.TagNumber(4)
+  void clearRowOrders() => clearField(4);
+  @$pb.TagNumber(4)
+  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')
+    ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
+    ..a<$core.int>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3)
+    ..hasRequiredFields = false
+  ;
+
+  FieldOrder._() : super();
+  factory FieldOrder({
+    $core.String? fieldId,
+    $core.bool? visibility,
+    $core.int? width,
+  }) {
+    final _result = create();
+    if (fieldId != null) {
+      _result.fieldId = fieldId;
+    }
+    if (visibility != null) {
+      _result.visibility = visibility;
+    }
+    if (width != null) {
+      _result.width = width;
+    }
+    return _result;
+  }
+  factory FieldOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory FieldOrder.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')
+  FieldOrder clone() => FieldOrder()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  FieldOrder copyWith(void Function(FieldOrder) updates) => super.copyWith((message) => updates(message as FieldOrder)) as FieldOrder; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static FieldOrder create() => FieldOrder._();
+  FieldOrder createEmptyInstance() => create();
+  static $pb.PbList<FieldOrder> createRepeated() => $pb.PbList<FieldOrder>();
+  @$core.pragma('dart2js:noInline')
+  static FieldOrder getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldOrder>(create);
+  static FieldOrder? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get fieldId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set fieldId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasFieldId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearFieldId() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.bool get visibility => $_getBF(1);
+  @$pb.TagNumber(2)
+  set visibility($core.bool v) { $_setBool(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasVisibility() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearVisibility() => clearField(2);
+
+  @$pb.TagNumber(3)
+  $core.int get width => $_getIZ(2);
+  @$pb.TagNumber(3)
+  set width($core.int v) { $_setSignedInt32(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasWidth() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearWidth() => clearField(3);
+}
+
+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)
+    ..hasRequiredFields = false
+  ;
+
+  RepeatedFieldOrder._() : super();
+  factory RepeatedFieldOrder({
+    $core.Iterable<FieldOrder>? items,
+  }) {
+    final _result = create();
+    if (items != null) {
+      _result.items.addAll(items);
+    }
+    return _result;
+  }
+  factory RepeatedFieldOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RepeatedFieldOrder.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')
+  RepeatedFieldOrder clone() => RepeatedFieldOrder()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RepeatedFieldOrder copyWith(void Function(RepeatedFieldOrder) updates) => super.copyWith((message) => updates(message as RepeatedFieldOrder)) as RepeatedFieldOrder; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RepeatedFieldOrder create() => RepeatedFieldOrder._();
+  RepeatedFieldOrder createEmptyInstance() => create();
+  static $pb.PbList<RepeatedFieldOrder> createRepeated() => $pb.PbList<RepeatedFieldOrder>();
+  @$core.pragma('dart2js:noInline')
+  static RepeatedFieldOrder getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedFieldOrder>(create);
+  static RepeatedFieldOrder? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.List<FieldOrder> get items => $_getList(0);
+}
+
+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<FieldType>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: FieldType.RichText, valueOf: FieldType.valueOf, enumValues: FieldType.values)
+    ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
+    ..aOM<AnyData>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions', subBuilder: AnyData.create)
+    ..hasRequiredFields = false
+  ;
+
+  Field._() : super();
+  factory Field({
+    $core.String? id,
+    $core.String? name,
+    $core.String? desc,
+    FieldType? fieldType,
+    $core.bool? frozen,
+    AnyData? typeOptions,
+  }) {
+    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 (typeOptions != null) {
+      _result.typeOptions = typeOptions;
+    }
+    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)
+  FieldType get fieldType => $_getN(3);
+  @$pb.TagNumber(4)
+  set fieldType(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)
+  AnyData get typeOptions => $_getN(5);
+  @$pb.TagNumber(6)
+  set typeOptions(AnyData v) { setField(6, v); }
+  @$pb.TagNumber(6)
+  $core.bool hasTypeOptions() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearTypeOptions() => clearField(6);
+  @$pb.TagNumber(6)
+  AnyData ensureTypeOptions() => $_ensure(5);
+}
+
+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') ? '' : 'typeUrl')
+    ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value', $pb.PbFieldType.OY)
+    ..hasRequiredFields = false
+  ;
+
+  AnyData._() : super();
+  factory AnyData({
+    $core.String? typeUrl,
+    $core.List<$core.int>? value,
+  }) {
+    final _result = create();
+    if (typeUrl != null) {
+      _result.typeUrl = typeUrl;
+    }
+    if (value != null) {
+      _result.value = value;
+    }
+    return _result;
+  }
+  factory AnyData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory AnyData.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')
+  AnyData clone() => AnyData()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  AnyData copyWith(void Function(AnyData) updates) => super.copyWith((message) => updates(message as AnyData)) as AnyData; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static AnyData create() => AnyData._();
+  AnyData createEmptyInstance() => create();
+  static $pb.PbList<AnyData> createRepeated() => $pb.PbList<AnyData>();
+  @$core.pragma('dart2js:noInline')
+  static AnyData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AnyData>(create);
+  static AnyData? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get typeUrl => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set typeUrl($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasTypeUrl() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearTypeUrl() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.List<$core.int> get value => $_getN(1);
+  @$pb.TagNumber(2)
+  set value($core.List<$core.int> v) { $_setBytes(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasValue() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearValue() => clearField(2);
+}
+
+class RowOrder extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RowOrder', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId')
+    ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
+    ..hasRequiredFields = false
+  ;
+
+  RowOrder._() : super();
+  factory RowOrder({
+    $core.String? gridId,
+    $core.String? rowId,
+    $core.bool? visibility,
+  }) {
+    final _result = create();
+    if (gridId != null) {
+      _result.gridId = gridId;
+    }
+    if (rowId != null) {
+      _result.rowId = rowId;
+    }
+    if (visibility != null) {
+      _result.visibility = visibility;
+    }
+    return _result;
+  }
+  factory RowOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RowOrder.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')
+  RowOrder clone() => RowOrder()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RowOrder copyWith(void Function(RowOrder) updates) => super.copyWith((message) => updates(message as RowOrder)) as RowOrder; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RowOrder create() => RowOrder._();
+  RowOrder createEmptyInstance() => create();
+  static $pb.PbList<RowOrder> createRepeated() => $pb.PbList<RowOrder>();
+  @$core.pragma('dart2js:noInline')
+  static RowOrder getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RowOrder>(create);
+  static RowOrder? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get gridId => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set gridId($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasGridId() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearGridId() => 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.bool get visibility => $_getBF(2);
+  @$pb.TagNumber(3)
+  set visibility($core.bool v) { $_setBool(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasVisibility() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearVisibility() => clearField(3);
+}
+
+class RepeatedRowOrder extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedRowOrder', createEmptyInstance: create)
+    ..pc<RowOrder>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: RowOrder.create)
+    ..hasRequiredFields = false
+  ;
+
+  RepeatedRowOrder._() : super();
+  factory RepeatedRowOrder({
+    $core.Iterable<RowOrder>? items,
+  }) {
+    final _result = create();
+    if (items != null) {
+      _result.items.addAll(items);
+    }
+    return _result;
+  }
+  factory RepeatedRowOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory RepeatedRowOrder.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')
+  RepeatedRowOrder clone() => RepeatedRowOrder()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  RepeatedRowOrder copyWith(void Function(RepeatedRowOrder) updates) => super.copyWith((message) => updates(message as RepeatedRowOrder)) as RepeatedRowOrder; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static RepeatedRowOrder create() => RepeatedRowOrder._();
+  RepeatedRowOrder createEmptyInstance() => create();
+  static $pb.PbList<RepeatedRowOrder> createRepeated() => $pb.PbList<RepeatedRowOrder>();
+  @$core.pragma('dart2js:noInline')
+  static RepeatedRowOrder getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RepeatedRowOrder>(create);
+  static RepeatedRowOrder? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.List<RowOrder> get items => $_getList(0);
+}
+
+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') ? '' : 'gridId')
+    ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'modifiedTime')
+    ..m<$core.String, Cell>(4, 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
+  ;
+
+  Row._() : super();
+  factory Row({
+    $core.String? id,
+    $core.String? gridId,
+    $fixnum.Int64? modifiedTime,
+    $core.Map<$core.String, Cell>? cellByFieldId,
+  }) {
+    final _result = create();
+    if (id != null) {
+      _result.id = id;
+    }
+    if (gridId != null) {
+      _result.gridId = gridId;
+    }
+    if (modifiedTime != null) {
+      _result.modifiedTime = modifiedTime;
+    }
+    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.String get gridId => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set gridId($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasGridId() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearGridId() => clearField(2);
+
+  @$pb.TagNumber(3)
+  $fixnum.Int64 get modifiedTime => $_getI64(2);
+  @$pb.TagNumber(3)
+  set modifiedTime($fixnum.Int64 v) { $_setInt64(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasModifiedTime() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearModifiedTime() => clearField(3);
+
+  @$pb.TagNumber(4)
+  $core.Map<$core.String, Cell> get cellByFieldId => $_getMap(3);
+}
+
+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') ? '' : 'rowId')
+    ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
+    ..aOM<AnyData>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', subBuilder: AnyData.create)
+    ..hasRequiredFields = false
+  ;
+
+  Cell._() : super();
+  factory Cell({
+    $core.String? id,
+    $core.String? rowId,
+    $core.String? fieldId,
+    AnyData? 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 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')
+  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')
+  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 Cell create() => Cell._();
+  Cell createEmptyInstance() => create();
+  static $pb.PbList<Cell> createRepeated() => $pb.PbList<Cell>();
+  @$core.pragma('dart2js:noInline')
+  static Cell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Cell>(create);
+  static Cell? _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 fieldId($core.String v) { $_setString(2, v); }
+  @$pb.TagNumber(3)
+  $core.bool hasFieldId() => $_has(2);
+  @$pb.TagNumber(3)
+  void clearFieldId() => clearField(3);
+
+  @$pb.TagNumber(4)
+  AnyData get data => $_getN(3);
+  @$pb.TagNumber(4)
+  set data(AnyData v) { setField(4, v); }
+  @$pb.TagNumber(4)
+  $core.bool hasData() => $_has(3);
+  @$pb.TagNumber(4)
+  void clearData() => clearField(4);
+  @$pb.TagNumber(4)
+  AnyData ensureData() => $_ensure(3);
+}
+
+class CreateGridPayload extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateGridPayload', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
+    ..hasRequiredFields = false
+  ;
+
+  CreateGridPayload._() : super();
+  factory CreateGridPayload({
+    $core.String? name,
+  }) {
+    final _result = create();
+    if (name != null) {
+      _result.name = name;
+    }
+    return _result;
+  }
+  factory CreateGridPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory CreateGridPayload.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')
+  CreateGridPayload clone() => CreateGridPayload()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  CreateGridPayload copyWith(void Function(CreateGridPayload) updates) => super.copyWith((message) => updates(message as CreateGridPayload)) as CreateGridPayload; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static CreateGridPayload create() => CreateGridPayload._();
+  CreateGridPayload createEmptyInstance() => create();
+  static $pb.PbList<CreateGridPayload> createRepeated() => $pb.PbList<CreateGridPayload>();
+  @$core.pragma('dart2js:noInline')
+  static CreateGridPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateGridPayload>(create);
+  static CreateGridPayload? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get name => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set name($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasName() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearName() => clearField(1);
+}
+
+class GridId extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridId', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value')
+    ..hasRequiredFields = false
+  ;
+
+  GridId._() : super();
+  factory GridId({
+    $core.String? value,
+  }) {
+    final _result = create();
+    if (value != null) {
+      _result.value = value;
+    }
+    return _result;
+  }
+  factory GridId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory GridId.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')
+  GridId clone() => GridId()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  GridId copyWith(void Function(GridId) updates) => super.copyWith((message) => updates(message as GridId)) as GridId; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static GridId create() => GridId._();
+  GridId createEmptyInstance() => create();
+  static $pb.PbList<GridId> createRepeated() => $pb.PbList<GridId>();
+  @$core.pragma('dart2js:noInline')
+  static GridId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridId>(create);
+  static GridId? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get value => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set value($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasValue() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearValue() => clearField(1);
+}
+

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

@@ -0,0 +1,34 @@
+///
+//  Generated code. Do not modify.
+//  source: grid.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+// ignore_for_file: UNDEFINED_SHOWN_NAME
+import 'dart:core' as $core;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class FieldType extends $pb.ProtobufEnum {
+  static const FieldType RichText = FieldType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RichText');
+  static const FieldType Number = FieldType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number');
+  static const FieldType DateTime = FieldType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DateTime');
+  static const FieldType SingleSelect = FieldType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SingleSelect');
+  static const FieldType MultiSelect = FieldType._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MultiSelect');
+  static const FieldType Checkbox = FieldType._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Checkbox');
+
+  static const $core.List<FieldType> values = <FieldType> [
+    RichText,
+    Number,
+    DateTime,
+    SingleSelect,
+    MultiSelect,
+    Checkbox,
+  ];
+
+  static final $core.Map<$core.int, FieldType> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static FieldType? valueOf($core.int value) => _byValue[value];
+
+  const FieldType._($core.int v, $core.String n) : super(v, n);
+}
+

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

@@ -0,0 +1,187 @@
+///
+//  Generated code. Do not modify.
+//  source: grid.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use fieldTypeDescriptor instead')
+const FieldType$json = const {
+  '1': 'FieldType',
+  '2': const [
+    const {'1': 'RichText', '2': 0},
+    const {'1': 'Number', '2': 1},
+    const {'1': 'DateTime', '2': 2},
+    const {'1': 'SingleSelect', '2': 3},
+    const {'1': 'MultiSelect', '2': 4},
+    const {'1': 'Checkbox', '2': 5},
+  ],
+};
+
+/// Descriptor for `FieldType`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List fieldTypeDescriptor = $convert.base64Decode('CglGaWVsZFR5cGUSDAoIUmljaFRleHQQABIKCgZOdW1iZXIQARIMCghEYXRlVGltZRACEhAKDFNpbmdsZVNlbGVjdBADEg8KC011bHRpU2VsZWN0EAQSDAoIQ2hlY2tib3gQBQ==');
+@$core.Deprecated('Use gridDescriptor instead')
+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': '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==');
+@$core.Deprecated('Use fieldOrderDescriptor instead')
+const FieldOrder$json = const {
+  '1': 'FieldOrder',
+  '2': const [
+    const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'},
+    const {'1': 'visibility', '3': 2, '4': 1, '5': 8, '10': 'visibility'},
+    const {'1': 'width', '3': 3, '4': 1, '5': 5, '10': 'width'},
+  ],
+};
+
+/// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEh4KCnZpc2liaWxpdHkYAiABKAhSCnZpc2liaWxpdHkSFAoFd2lkdGgYAyABKAVSBXdpZHRo');
+@$core.Deprecated('Use repeatedFieldOrderDescriptor instead')
+const RepeatedFieldOrder$json = const {
+  '1': 'RepeatedFieldOrder',
+  '2': const [
+    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.FieldOrder', '10': 'items'},
+  ],
+};
+
+/// Descriptor for `RepeatedFieldOrder`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List repeatedFieldOrderDescriptor = $convert.base64Decode('ChJSZXBlYXRlZEZpZWxkT3JkZXISIQoFaXRlbXMYASADKAsyCy5GaWVsZE9yZGVyUgVpdGVtcw==');
+@$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': 'type_options', '3': 6, '4': 1, '5': 11, '6': '.AnyData', '10': 'typeOptions'},
+  ],
+};
+
+/// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIrCgx0eXBlX29wdGlvbnMYBiABKAsyCC5BbnlEYXRhUgt0eXBlT3B0aW9ucw==');
+@$core.Deprecated('Use anyDataDescriptor instead')
+const AnyData$json = const {
+  '1': 'AnyData',
+  '2': const [
+    const {'1': 'type_url', '3': 1, '4': 1, '5': 9, '10': 'typeUrl'},
+    const {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'},
+  ],
+};
+
+/// Descriptor for `AnyData`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List anyDataDescriptor = $convert.base64Decode('CgdBbnlEYXRhEhkKCHR5cGVfdXJsGAEgASgJUgd0eXBlVXJsEhQKBXZhbHVlGAIgASgMUgV2YWx1ZQ==');
+@$core.Deprecated('Use rowOrderDescriptor instead')
+const RowOrder$json = const {
+  '1': 'RowOrder',
+  '2': const [
+    const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
+    const {'1': 'row_id', '3': 2, '4': 1, '5': 9, '10': 'rowId'},
+    const {'1': 'visibility', '3': 3, '4': 1, '5': 8, '10': 'visibility'},
+  ],
+};
+
+/// Descriptor for `RowOrder`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List rowOrderDescriptor = $convert.base64Decode('CghSb3dPcmRlchIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSFQoGcm93X2lkGAIgASgJUgVyb3dJZBIeCgp2aXNpYmlsaXR5GAMgASgIUgp2aXNpYmlsaXR5');
+@$core.Deprecated('Use repeatedRowOrderDescriptor instead')
+const RepeatedRowOrder$json = const {
+  '1': 'RepeatedRowOrder',
+  '2': const [
+    const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.RowOrder', '10': 'items'},
+  ],
+};
+
+/// Descriptor for `RepeatedRowOrder`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List repeatedRowOrderDescriptor = $convert.base64Decode('ChBSZXBlYXRlZFJvd09yZGVyEh8KBWl0ZW1zGAEgAygLMgkuUm93T3JkZXJSBWl0ZW1z');
+@$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': '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': '.Row.CellByFieldIdEntry', '10': 'cellByFieldId'},
+  ],
+  '3': const [Row_CellByFieldIdEntry$json],
+};
+
+@$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('CgNSb3cSDgoCaWQYASABKAlSAmlkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZBIjCg1tb2RpZmllZF90aW1lGAMgASgDUgxtb2RpZmllZFRpbWUSQAoQY2VsbF9ieV9maWVsZF9pZBgEIAMoCzIXLlJvdy5DZWxsQnlGaWVsZElkRW50cnlSDWNlbGxCeUZpZWxkSWQaRwoSQ2VsbEJ5RmllbGRJZEVudHJ5EhAKA2tleRgBIAEoCVIDa2V5EhsKBXZhbHVlGAIgASgLMgUuQ2VsbFIFdmFsdWU6AjgB');
+@$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': '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': 11, '6': '.AnyData', '10': 'data'},
+  ],
+};
+
+/// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEg4KAmlkGAEgASgJUgJpZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElkEhwKBGRhdGEYBCABKAsyCC5BbnlEYXRhUgRkYXRh');
+@$core.Deprecated('Use createGridPayloadDescriptor instead')
+const CreateGridPayload$json = const {
+  '1': 'CreateGridPayload',
+  '2': const [
+    const {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
+  ],
+};
+
+/// Descriptor for `CreateGridPayload`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List createGridPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVHcmlkUGF5bG9hZBISCgRuYW1lGAEgASgJUgRuYW1l');
+@$core.Deprecated('Use gridIdDescriptor instead')
+const GridId$json = const {
+  '1': 'GridId',
+  '2': const [
+    const {'1': 'value', '3': 1, '4': 1, '5': 9, '10': 'value'},
+  ],
+};
+
+/// Descriptor for `GridId`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List gridIdDescriptor = $convert.base64Decode('CgZHcmlkSWQSFAoFdmFsdWUYASABKAlSBXZhbHVl');

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

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: grid.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+export 'grid.pb.dart';
+

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

@@ -0,0 +1,2 @@
+// Auto-generated, do not edit 
+export './grid.pb.dart';

+ 11 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pb.dart

@@ -0,0 +1,11 @@
+///
+//  Generated code. Do not modify.
+//  source: event_map.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+import 'dart:core' as $core;
+
+export 'event_map.pbenum.dart';
+

+ 26 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart

@@ -0,0 +1,26 @@
+///
+//  Generated code. Do not modify.
+//  source: event_map.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+// ignore_for_file: UNDEFINED_SHOWN_NAME
+import 'dart:core' as $core;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class GridEvent extends $pb.ProtobufEnum {
+  static const GridEvent CreateGrid = GridEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateGrid');
+  static const GridEvent OpenGrid = GridEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'OpenGrid');
+
+  static const $core.List<GridEvent> values = <GridEvent> [
+    CreateGrid,
+    OpenGrid,
+  ];
+
+  static final $core.Map<$core.int, GridEvent> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static GridEvent? valueOf($core.int value) => _byValue[value];
+
+  const GridEvent._($core.int v, $core.String n) : super(v, n);
+}
+

+ 21 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart

@@ -0,0 +1,21 @@
+///
+//  Generated code. Do not modify.
+//  source: event_map.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use gridEventDescriptor instead')
+const GridEvent$json = const {
+  '1': 'GridEvent',
+  '2': const [
+    const {'1': 'CreateGrid', '2': 0},
+    const {'1': 'OpenGrid', '2': 1},
+  ],
+};
+
+/// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDgoKQ3JlYXRlR3JpZBAAEgwKCE9wZW5HcmlkEAE=');

+ 9 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbserver.dart

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: event_map.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+export 'event_map.pb.dart';
+

+ 2 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart

@@ -0,0 +1,2 @@
+// Auto-generated, do not edit 
+export './event_map.pb.dart';

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

@@ -1041,6 +1041,27 @@ dependencies = [
 [[package]]
 name = "flowy-grid"
 version = "0.1.0"
+dependencies = [
+ "flowy-derive",
+ "flowy-error",
+ "flowy-grid-data-model",
+ "lib-dispatch",
+ "lib-infra",
+ "protobuf",
+ "strum",
+ "strum_macros",
+ "tracing",
+]
+
+[[package]]
+name = "flowy-grid-data-model"
+version = "0.1.0"
+dependencies = [
+ "bytes",
+ "flowy-derive",
+ "lib-infra",
+ "protobuf",
+]
 
 [[package]]
 name = "flowy-net"
@@ -1091,6 +1112,7 @@ dependencies = [
  "flowy-collaboration",
  "flowy-database",
  "flowy-folder",
+ "flowy-grid",
  "flowy-net",
  "flowy-sync",
  "flowy-user",

+ 4 - 4
frontend/rust-lib/flowy-folder/Cargo.toml

@@ -49,11 +49,11 @@ serde_json = "1.0"
 flowy-folder = { path = "../flowy-folder", features = ["flowy_unit_test"]}
 flowy-test = { path = "../flowy-test" }
 
+[build-dependencies]
+lib-infra = { path = "../../../shared-lib/lib-infra", features = ["protobuf_file_gen", "proto_gen"] }
+
 [features]
 default = []
 http_server = []
 flowy_unit_test = ["lib-ot/flowy_unit_test", "flowy-sync/flowy_unit_test"]
-dart = ["lib-infra/dart", "flowy-folder/dart", "flowy-folder/dart",]
-
-[build-dependencies]
-lib-infra = { path = "../../../shared-lib/lib-infra", features = ["protobuf_file_gen", "proto_gen"] }
+dart = ["lib-infra/dart", "flowy-folder/dart"]

+ 17 - 0
frontend/rust-lib/flowy-grid/Cargo.toml

@@ -6,3 +6,20 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+flowy-grid-data-model = { path = "../../../shared-lib/flowy-grid-data-model" }
+lib-dispatch = { path = "../lib-dispatch" }
+lib-infra = { path = "../../../shared-lib/lib-infra" }
+flowy-error = { path = "../flowy-error"}
+strum = "0.21"
+strum_macros = "0.21"
+flowy-derive = { path = "../../../shared-lib/flowy-derive" }
+tracing = { version = "0.1", features = ["log"] }
+protobuf = {version = "2.18.0"}
+
+[build-dependencies]
+lib-infra = { path = "../../../shared-lib/lib-infra", features = ["protobuf_file_gen", "proto_gen"] }
+
+
+[features]
+default = []
+dart = ["lib-infra/dart"]

+ 3 - 0
frontend/rust-lib/flowy-grid/Flowy.toml

@@ -0,0 +1,3 @@
+
+proto_crates = ["src/event_map.rs"]
+event_files = ["src/event_map.rs"]

+ 7 - 0
frontend/rust-lib/flowy-grid/build.rs

@@ -0,0 +1,7 @@
+use lib_infra::code_gen;
+
+fn main() {
+    let crate_name = env!("CARGO_PKG_NAME");
+    code_gen::protobuf_file::gen(crate_name, "./src/protobuf/proto");
+    code_gen::dart_event::gen(crate_name);
+}

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

@@ -0,0 +1 @@
+pub struct GridManager {}

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

@@ -0,0 +1,23 @@
+use crate::controller::GridManager;
+use flowy_error::FlowyError;
+use flowy_grid_data_model::entities::{CreateGridPayload, Grid, GridId};
+use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
+use std::sync::Arc;
+
+#[tracing::instrument(skip(data, controller), err)]
+pub(crate) async fn create_grid_handler(
+    data: Data<CreateGridPayload>,
+    controller: AppData<Arc<GridManager>>,
+) -> DataResult<Grid, FlowyError> {
+    todo!()
+}
+
+#[tracing::instrument(skip(data, controller), err)]
+pub(crate) async fn open_grid_handler(
+    data: Data<GridId>,
+    controller: AppData<Arc<GridManager>>,
+) -> DataResult<Grid, FlowyError> {
+    let params: GridId = data.into_inner();
+
+    todo!()
+}

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

@@ -0,0 +1,26 @@
+use crate::controller::GridManager;
+use crate::event_handler::*;
+use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
+use lib_dispatch::prelude::*;
+use std::sync::Arc;
+use strum_macros::Display;
+
+pub fn create(grid_manager: Arc<GridManager>) -> Module {
+    let mut module = Module::new().name(env!("CARGO_PKG_NAME")).data(grid_manager);
+
+    module = module
+        .event(GridEvent::CreateGrid, create_grid_handler)
+        .event(GridEvent::OpenGrid, open_grid_handler);
+
+    module
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
+#[event_err = "FlowyError"]
+pub enum GridEvent {
+    #[event(input = "CreateGridPayload", output = "Grid")]
+    CreateGrid = 0,
+
+    #[event(input = "GridId", output = "Grid")]
+    OpenGrid = 1,
+}

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

@@ -1,8 +1,5 @@
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn it_works() {
-        let result = 2 + 2;
-        assert_eq!(result, 4);
-    }
-}
+mod controller;
+mod event_handler;
+mod event_map;
+
+mod protobuf;

+ 4 - 0
frontend/rust-lib/flowy-grid/src/protobuf/mod.rs

@@ -0,0 +1,4 @@
+#![cfg_attr(rustfmt, rustfmt::skip)]
+// Auto-generated, do not edit
+mod model;
+pub use model::*;

+ 91 - 0
frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs

@@ -0,0 +1,91 @@
+// This file is generated by rust-protobuf 2.25.2. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `event_map.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
+
+#[derive(Clone,PartialEq,Eq,Debug,Hash)]
+pub enum GridEvent {
+    CreateGrid = 0,
+    OpenGrid = 1,
+}
+
+impl ::protobuf::ProtobufEnum for GridEvent {
+    fn value(&self) -> i32 {
+        *self as i32
+    }
+
+    fn from_i32(value: i32) -> ::std::option::Option<GridEvent> {
+        match value {
+            0 => ::std::option::Option::Some(GridEvent::CreateGrid),
+            1 => ::std::option::Option::Some(GridEvent::OpenGrid),
+            _ => ::std::option::Option::None
+        }
+    }
+
+    fn values() -> &'static [Self] {
+        static values: &'static [GridEvent] = &[
+            GridEvent::CreateGrid,
+            GridEvent::OpenGrid,
+        ];
+        values
+    }
+
+    fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            ::protobuf::reflect::EnumDescriptor::new_pb_name::<GridEvent>("GridEvent", file_descriptor_proto())
+        })
+    }
+}
+
+impl ::std::marker::Copy for GridEvent {
+}
+
+impl ::std::default::Default for GridEvent {
+    fn default() -> Self {
+        GridEvent::CreateGrid
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for GridEvent {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x0fevent_map.proto*)\n\tGridEvent\x12\x0e\n\nCreateGrid\x10\0\x12\x0c\
+    \n\x08OpenGrid\x10\x01b\x06proto3\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}

+ 5 - 0
frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs

@@ -0,0 +1,5 @@
+#![cfg_attr(rustfmt, rustfmt::skip)]
+// Auto-generated, do not edit
+
+mod event_map;
+pub use event_map::*;

+ 6 - 0
frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto

@@ -0,0 +1,6 @@
+syntax = "proto3";
+
+enum GridEvent {
+    CreateGrid = 0;
+    OpenGrid = 1;
+}

+ 2 - 1
frontend/rust-lib/flowy-sdk/Cargo.toml

@@ -11,6 +11,7 @@ lib-log = { path = "../lib-log" }
 flowy-user = { path = "../flowy-user" }
 flowy-net = { path = "../flowy-net" }
 flowy-folder = { path = "../flowy-folder", default-features = false }
+flowy-grid = { path = "../flowy-grid", default-features = false }
 flowy-database = { path = "../flowy-database" }
 flowy-block = { path = "../flowy-block" }
 flowy-sync = { path = "../flowy-sync" }
@@ -39,4 +40,4 @@ futures-util = "0.3.15"
 [features]
 http_server = ["flowy-user/http_server", "flowy-folder/http_server", "flowy-block/http_server"]
 use_bunyan = ["lib-log/use_bunyan"]
-dart = ["flowy-user/dart", "flowy-net/dart", "flowy-folder/dart", "flowy-collaboration/dart"]
+dart = ["flowy-user/dart", "flowy-net/dart", "flowy-folder/dart", "flowy-collaboration/dart", "flowy-grid/dart"]

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

@@ -146,3 +146,15 @@ pub struct Cell {
     #[pb(index = 4)]
     pub data: AnyData,
 }
+
+#[derive(ProtoBuf, Default)]
+pub struct CreateGridPayload {
+    #[pb(index = 1)]
+    pub name: String,
+}
+
+#[derive(Clone, ProtoBuf, Default, Debug)]
+pub struct GridId {
+    #[pb(index = 1)]
+    pub value: String,
+}

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

@@ -2699,6 +2699,324 @@ impl ::protobuf::reflect::ProtobufValue for Cell {
     }
 }
 
+#[derive(PartialEq,Clone,Default)]
+pub struct CreateGridPayload {
+    // message fields
+    pub name: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a CreateGridPayload {
+    fn default() -> &'a CreateGridPayload {
+        <CreateGridPayload as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl CreateGridPayload {
+    pub fn new() -> CreateGridPayload {
+        ::std::default::Default::default()
+    }
+
+    // string name = 1;
+
+
+    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())
+    }
+}
+
+impl ::protobuf::Message for CreateGridPayload {
+    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.name)?;
+                },
+                _ => {
+                    ::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.name.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.name);
+        }
+        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.name.is_empty() {
+            os.write_string(1, &self.name)?;
+        }
+        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() -> CreateGridPayload {
+        CreateGridPayload::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>(
+                "name",
+                |m: &CreateGridPayload| { &m.name },
+                |m: &mut CreateGridPayload| { &mut m.name },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateGridPayload>(
+                "CreateGridPayload",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static CreateGridPayload {
+        static instance: ::protobuf::rt::LazyV2<CreateGridPayload> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(CreateGridPayload::new)
+    }
+}
+
+impl ::protobuf::Clear for CreateGridPayload {
+    fn clear(&mut self) {
+        self.name.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for CreateGridPayload {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for CreateGridPayload {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct GridId {
+    // message fields
+    pub value: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a GridId {
+    fn default() -> &'a GridId {
+        <GridId as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl GridId {
+    pub fn new() -> GridId {
+        ::std::default::Default::default()
+    }
+
+    // string value = 1;
+
+
+    pub fn get_value(&self) -> &str {
+        &self.value
+    }
+    pub fn clear_value(&mut self) {
+        self.value.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_value(&mut self, v: ::std::string::String) {
+        self.value = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_value(&mut self) -> &mut ::std::string::String {
+        &mut self.value
+    }
+
+    // Take field
+    pub fn take_value(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.value, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for GridId {
+    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.value)?;
+                },
+                _ => {
+                    ::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.value.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.value);
+        }
+        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.value.is_empty() {
+            os.write_string(1, &self.value)?;
+        }
+        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() -> GridId {
+        GridId::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>(
+                "value",
+                |m: &GridId| { &m.value },
+                |m: &mut GridId| { &mut m.value },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<GridId>(
+                "GridId",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static GridId {
+        static instance: ::protobuf::rt::LazyV2<GridId> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(GridId::new)
+    }
+}
+
+impl ::protobuf::Clear for GridId {
+    fn clear(&mut self) {
+        self.value.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for GridId {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for GridId {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
 #[derive(Clone,PartialEq,Eq,Debug,Hash)]
 pub enum FieldType {
     RichText = 0,
@@ -2792,8 +3110,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x0b2\x05.CellR\x05value:\x028\x01\"f\n\x04Cell\x12\x0e\n\x02id\x18\x01\
     \x20\x01(\tR\x02id\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\
     \x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x1c\n\x04data\x18\
-    \x04\x20\x01(\x0b2\x08.AnyDataR\x04data*d\n\tFieldType\x12\x0c\n\x08Rich\
-    Text\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\
+    \x04\x20\x01(\x0b2\x08.AnyDataR\x04data\"'\n\x11CreateGridPayload\x12\
+    \x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\
+    \x05value\x18\x01\x20\x01(\tR\x05value*d\n\tFieldType\x12\x0c\n\x08RichT\
+    ext\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\
     \x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\
     \n\x08Checkbox\x10\x05b\x06proto3\
 ";

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

@@ -54,6 +54,12 @@ message Cell {
     string field_id = 3;
     AnyData data = 4;
 }
+message CreateGridPayload {
+    string name = 1;
+}
+message GridId {
+    string value = 1;
+}
 enum FieldType {
     RichText = 0;
     Number = 1;