diff --git a/frontend/app_flowy/lib/core/notification_helper.dart b/frontend/app_flowy/lib/core/notification_helper.dart index 88b299aa3a..d815bf92bb 100644 --- a/frontend/app_flowy/lib/core/notification_helper.dart +++ b/frontend/app_flowy/lib/core/notification_helper.dart @@ -4,7 +4,9 @@ import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +// User typedef UserNotificationCallback = void Function(UserNotification, Either); class UserNotificationParser extends NotificationParser { @@ -17,10 +19,11 @@ class UserNotificationParser extends NotificationParser); +// Folder +typedef FolderNotificationCallback = void Function(FolderNotification, Either); class FolderNotificationParser extends NotificationParser { - FolderNotificationParser({String? id, required NotificationCallback callback}) + FolderNotificationParser({String? id, required FolderNotificationCallback callback}) : super( id: id, callback: callback, @@ -29,6 +32,19 @@ class FolderNotificationParser extends NotificationParser); + +class GridNotificationParser extends NotificationParser { + GridNotificationParser({String? id, required GridNotificationCallback callback}) + : super( + id: id, + callback: callback, + tyParser: (ty) => GridNotification.valueOf(ty), + errorParser: (bytes) => FlowyError.fromBuffer(bytes), + ); +} + class NotificationParser { String? id; void Function(T, Either) callback; diff --git a/frontend/app_flowy/lib/startup/home_deps_resolver.dart b/frontend/app_flowy/lib/startup/home_deps_resolver.dart index cbb359f09d..d66fe7cc01 100644 --- a/frontend/app_flowy/lib/startup/home_deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/home_deps_resolver.dart @@ -16,6 +16,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:get_it/get_it.dart'; +import '../workspace/application/grid/grid_listener.dart'; + class HomeDepsResolver { static Future resolve(GetIt getIt) async { getIt.registerFactoryParam( @@ -90,10 +92,7 @@ class HomeDepsResolver { // Grid getIt.registerFactoryParam( - (view, _) => GridBloc( - view: view, - service: GridService(), - ), + (view, _) => GridBloc(view: view, service: GridService(), listener: GridListener(gridId: view.id)), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index b67f119fe3..09e4428a83 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -1,13 +1,14 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; - import 'data.dart'; +import 'grid_listener.dart'; import 'grid_service.dart'; part 'grid_bloc.freezed.dart'; @@ -15,14 +16,16 @@ part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final GridService service; final View view; + final GridListener listener; Grid? _grid; List? _fields; - GridBloc({required this.view, required this.service}) : super(GridState.initial()) { + GridBloc({required this.view, required this.service, required this.listener}) : super(GridState.initial()) { on( (event, emit) async { await event.map( initial: (InitialGrid value) async { + await _startGridListening(); await _loadGrid(emit); await _loadFields(emit); await _loadGridInfo(emit); @@ -40,9 +43,25 @@ class GridBloc extends Bloc { @override Future close() async { + await listener.close(); return super.close(); } + Future _startGridListening() async { + listener.createRowNotifier.addPublishListener((result) { + result.fold((row) { + // + Log.info("$row"); + }, (err) => null); + }); + + listener.deleteRowNotifier.addPublishListener((result) { + result.fold((l) => null, (r) => null); + }); + + listener.start(); + } + Future _loadGrid(Emitter emit) async { final result = await service.openGrid(gridId: view.id); result.fold( diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart index e69de29bb2..b17544edf9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart @@ -0,0 +1,60 @@ +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_sdk/rust_stream.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'dart:async'; +import 'dart:typed_data'; +import 'package:app_flowy/core/notification_helper.dart'; +import 'package:dartz/dartz.dart'; + +typedef CreateRowNotifiedValue = Either; +typedef DeleteRowNotifierValue = Either; + +class GridListener { + final String gridId; + PublishNotifier createRowNotifier = PublishNotifier(); + PublishNotifier deleteRowNotifier = PublishNotifier(); + StreamSubscription? _subscription; + late GridNotificationParser _parser; + + GridListener({required this.gridId}); + + void start() { + _parser = GridNotificationParser( + id: gridId, + callback: (ty, result) { + _handleObservableType(ty, result); + }, + ); + + _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + } + + void _handleObservableType(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.GridDidCreateRows: + result.fold( + (payload) => createRowNotifier.value = left(RepeatedRow.fromBuffer(payload)), + (error) => createRowNotifier.value = right(error), + ); + break; + case GridNotification.GridDidDeleteRow: + result.fold( + (payload) => deleteRowNotifier.value = left(RepeatedRow.fromBuffer(payload)), + (error) => deleteRowNotifier.value = right(error), + ); + break; + + default: + break; + } + } + + Future close() async { + await _subscription?.cancel(); + createRowNotifier.dispose(); + deleteRowNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/view/view_listener.dart b/frontend/app_flowy/lib/workspace/application/view/view_listener.dart index c5a202e25e..f400124805 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_listener.dart @@ -9,15 +9,15 @@ import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_infra/notifier.dart'; -typedef DeleteNotifierValue = Either; -typedef UpdateNotifierValue = Either; -typedef RestoreNotifierValue = Either; +typedef DeleteViewNotifyValue = Either; +typedef UpdateViewNotifiedValue = Either; +typedef RestoreViewNotifiedValue = Either; class ViewListener { StreamSubscription? _subscription; - PublishNotifier updatedNotifier = PublishNotifier(); - PublishNotifier deletedNotifier = PublishNotifier(); - PublishNotifier restoredNotifier = PublishNotifier(); + PublishNotifier updatedNotifier = PublishNotifier(); + PublishNotifier deletedNotifier = PublishNotifier(); + PublishNotifier restoredNotifier = PublishNotifier(); late FolderNotificationParser _parser; View view; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 7435ea0e5f..c396e7d71f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -139,9 +139,10 @@ class _GridBodyState extends State { delegate: SliverChildBuilderDelegate( (context, index) { final data = gridInfo.rowAtIndex(index); - return RepaintBoundary(child: GridRowWidget(data: data)); + return GridRowWidget(data: data); }, childCount: gridInfo.numberOfRows(), + addRepaintBoundaries: true, ), ); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index f89285ba92..21f7e0f4a8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -607,6 +607,47 @@ class Cell extends $pb.GeneratedMessage { void clearContent() => clearField(2); } +class RepeatedCell extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedCell', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Cell.create) + ..hasRequiredFields = false + ; + + RepeatedCell._() : super(); + factory RepeatedCell({ + $core.Iterable? items, + }) { + final _result = create(); + if (items != null) { + _result.items.addAll(items); + } + return _result; + } + factory RepeatedCell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RepeatedCell.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') + RepeatedCell clone() => RepeatedCell()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + RepeatedCell copyWith(void Function(RepeatedCell) updates) => super.copyWith((message) => updates(message as RepeatedCell)) as RepeatedCell; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RepeatedCell create() => RepeatedCell._(); + RepeatedCell createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static RepeatedCell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static RepeatedCell? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get items => $_getList(0); +} + 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') diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 1504b31506..a6a7eb79d3 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -131,6 +131,16 @@ const Cell$json = const { /// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhgKB2NvbnRlbnQYAiABKAlSB2NvbnRlbnQ='); +@$core.Deprecated('Use repeatedCellDescriptor instead') +const RepeatedCell$json = const { + '1': 'RepeatedCell', + '2': const [ + const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Cell', '10': 'items'}, + ], +}; + +/// Descriptor for `RepeatedCell`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List repeatedCellDescriptor = $convert.base64Decode('CgxSZXBlYXRlZENlbGwSGwoFaXRlbXMYASADKAsyBS5DZWxsUgVpdGVtcw=='); @$core.Deprecated('Use createGridPayloadDescriptor instead') const CreateGridPayload$json = const { '1': 'CreateGridPayload', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pb.dart new file mode 100644 index 0000000000..402c0a4115 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pb.dart @@ -0,0 +1,11 @@ +/// +// Generated code. Do not modify. +// source: dart_notification.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 'dart_notification.pbenum.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart new file mode 100644 index 0000000000..9f4245122f --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart @@ -0,0 +1,34 @@ +/// +// Generated code. Do not modify. +// source: dart_notification.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 GridNotification extends $pb.ProtobufEnum { + static const GridNotification Unknown = GridNotification._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown'); + static const GridNotification GridDidCreateRows = GridNotification._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateRows'); + static const GridNotification GridDidDeleteRow = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidDeleteRow'); + static const GridNotification GridDidUpdateRows = GridNotification._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateRows'); + static const GridNotification GridDidUpdateCells = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); + static const GridNotification GridDidUpdateFields = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateFields'); + + static const $core.List values = [ + Unknown, + GridDidCreateRows, + GridDidDeleteRow, + GridDidUpdateRows, + GridDidUpdateCells, + GridDidUpdateFields, + ]; + + static final $core.Map<$core.int, GridNotification> _byValue = $pb.ProtobufEnum.initByValue(values); + static GridNotification? valueOf($core.int value) => _byValue[value]; + + const GridNotification._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart new file mode 100644 index 0000000000..5100550835 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart @@ -0,0 +1,25 @@ +/// +// Generated code. Do not modify. +// source: dart_notification.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 gridNotificationDescriptor instead') +const GridNotification$json = const { + '1': 'GridNotification', + '2': const [ + const {'1': 'Unknown', '2': 0}, + const {'1': 'GridDidCreateRows', '2': 10}, + const {'1': 'GridDidDeleteRow', '2': 11}, + const {'1': 'GridDidUpdateRows', '2': 12}, + const {'1': 'GridDidUpdateCells', '2': 20}, + const {'1': 'GridDidUpdateFields', '2': 30}, + ], +}; + +/// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIVChFHcmlkRGlkQ3JlYXRlUm93cxAKEhQKEEdyaWREaWREZWxldGVSb3cQCxIVChFHcmlkRGlkVXBkYXRlUm93cxAMEhYKEkdyaWREaWRVcGRhdGVDZWxscxAUEhcKE0dyaWREaWRVcGRhdGVGaWVsZHMQHg=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbserver.dart new file mode 100644 index 0000000000..8be819e83e --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: dart_notification.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 'dart_notification.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart index 0ad090edd5..daefe6a170 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart @@ -1,6 +1,7 @@ // Auto-generated, do not edit export './date_description.pb.dart'; export './text_description.pb.dart'; +export './dart_notification.pb.dart'; export './checkbox_description.pb.dart'; export './selection_description.pb.dart'; export './event_map.pb.dart'; diff --git a/frontend/rust-lib/flowy-grid/Flowy.toml b/frontend/rust-lib/flowy-grid/Flowy.toml index 4d1a277df3..b310e3fcd7 100644 --- a/frontend/rust-lib/flowy-grid/Flowy.toml +++ b/frontend/rust-lib/flowy-grid/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/event_map.rs", "src/services/cell/description"] +proto_crates = ["src/event_map.rs", "src/services/cell/description", "src/dart_notification.rs"] event_files = ["src/event_map.rs"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs new file mode 100644 index 0000000000..d6fb15d719 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -0,0 +1,36 @@ +use dart_notify::DartNotifyBuilder; +use flowy_derive::ProtoBuf_Enum; +const OBSERVABLE_CATEGORY: &str = "Grid"; + +#[derive(ProtoBuf_Enum, Debug)] +pub enum GridNotification { + Unknown = 0, + GridDidCreateRows = 10, + GridDidDeleteRow = 11, + GridDidUpdateRows = 12, + + GridDidUpdateCells = 20, + GridDidUpdateFields = 30, +} + +impl std::default::Default for GridNotification { + fn default() -> Self { + GridNotification::Unknown + } +} + +impl std::convert::From for i32 { + fn from(notification: GridNotification) -> Self { + notification as i32 + } +} + +#[tracing::instrument(level = "trace")] +pub fn send_dart_notification(id: &str, ty: GridNotification) -> DartNotifyBuilder { + DartNotifyBuilder::new(id, ty, OBSERVABLE_CATEGORY) +} + +#[tracing::instrument(level = "trace")] +pub fn send_anonymous_dart_notification(ty: GridNotification) -> DartNotifyBuilder { + DartNotifyBuilder::new("", ty, OBSERVABLE_CATEGORY) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index e92556b554..9d0001305d 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -45,11 +45,11 @@ pub(crate) async fn get_fields_handler( pub(crate) async fn create_row_handler( data: Data, manager: AppData>, -) -> DataResult { +) -> Result<(), FlowyError> { let payload: CreateRowPayload = data.into_inner(); let editor = manager.get_grid_editor(payload.grid_id.as_ref())?; - let row = editor.create_row(payload.upper_row_id).await?; - data_result(row) + let _ = editor.create_row(payload.upper_row_id).await?; + Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] diff --git a/frontend/rust-lib/flowy-grid/src/lib.rs b/frontend/rust-lib/flowy-grid/src/lib.rs index 526e1e4267..a3ac3411e2 100644 --- a/frontend/rust-lib/flowy-grid/src/lib.rs +++ b/frontend/rust-lib/flowy-grid/src/lib.rs @@ -5,6 +5,7 @@ mod event_handler; pub mod event_map; pub mod manager; +mod dart_notification; mod protobuf; pub mod services; pub mod util; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs new file mode 100644 index 0000000000..63676bd6e6 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -0,0 +1,106 @@ +// 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 `dart_notification.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 GridNotification { + Unknown = 0, + GridDidCreateRows = 10, + GridDidDeleteRow = 11, + GridDidUpdateRows = 12, + GridDidUpdateCells = 20, + GridDidUpdateFields = 30, +} + +impl ::protobuf::ProtobufEnum for GridNotification { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(GridNotification::Unknown), + 10 => ::std::option::Option::Some(GridNotification::GridDidCreateRows), + 11 => ::std::option::Option::Some(GridNotification::GridDidDeleteRow), + 12 => ::std::option::Option::Some(GridNotification::GridDidUpdateRows), + 20 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), + 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateFields), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [GridNotification] = &[ + GridNotification::Unknown, + GridNotification::GridDidCreateRows, + GridNotification::GridDidDeleteRow, + GridNotification::GridDidUpdateRows, + GridNotification::GridDidUpdateCells, + GridNotification::GridDidUpdateFields, + ]; + 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::("GridNotification", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for GridNotification { +} + +impl ::std::default::Default for GridNotification { + fn default() -> Self { + GridNotification::Unknown + } +} + +impl ::protobuf::reflect::ProtobufValue for GridNotification { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x17dart_notification.proto*\x94\x01\n\x10GridNotification\x12\x0b\n\ + \x07Unknown\x10\0\x12\x15\n\x11GridDidCreateRows\x10\n\x12\x14\n\x10Grid\ + DidDeleteRow\x10\x0b\x12\x15\n\x11GridDidUpdateRows\x10\x0c\x12\x16\n\ + \x12GridDidUpdateCells\x10\x14\x12\x17\n\x13GridDidUpdateFields\x10\x1eb\ + \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() + }) +} diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs index fb32dca3f2..a616a281d6 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs @@ -7,6 +7,9 @@ pub use date_description::*; mod text_description; pub use text_description::*; +mod dart_notification; +pub use dart_notification::*; + mod checkbox_description; pub use checkbox_description::*; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto new file mode 100644 index 0000000000..9c606ac091 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +enum GridNotification { + Unknown = 0; + GridDidCreateRows = 10; + GridDidDeleteRow = 11; + GridDidUpdateRows = 12; + GridDidUpdateCells = 20; + GridDidUpdateFields = 30; +} diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs index 0da4b9e609..8e49a47588 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs @@ -1,5 +1,5 @@ use crate::manager::GridUser; -use crate::services::row::make_row_ids_per_block; +use crate::services::row::{make_cell, make_row_ids_per_block, make_rows}; use bytes::Bytes; use dashmap::DashMap; @@ -8,7 +8,8 @@ use flowy_collaboration::entities::revision::Revision; use flowy_collaboration::util::make_delta_from_revisions; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - GridBlock, GridBlockChangeset, RepeatedRowOrder, RowMeta, RowMetaChangeset, RowOrder, + Cell, FieldMeta, GridBlock, GridBlockChangeset, RepeatedCell, RepeatedRow, RepeatedRowOrder, RowMeta, + RowMetaChangeset, RowOrder, }; use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_sync::{ @@ -19,6 +20,7 @@ use lib_ot::core::PlainTextAttributes; use std::collections::HashMap; +use crate::dart_notification::{send_dart_notification, GridNotification}; use std::sync::Arc; use tokio::sync::RwLock; @@ -26,17 +28,20 @@ type RowId = String; type BlockId = String; pub(crate) struct GridBlockMetaEditorManager { + grid_id: String, user: Arc, editor_map: DashMap>, block_id_by_row_id: DashMap, } impl GridBlockMetaEditorManager { - pub(crate) async fn new(user: &Arc, blocks: Vec) -> FlowyResult { + pub(crate) async fn new(grid_id: &str, user: &Arc, blocks: Vec) -> FlowyResult { let editor_map = make_block_meta_editor_map(user, blocks).await?; let user = user.clone(); let block_id_by_row_id = DashMap::new(); + let grid_id = grid_id.to_owned(); let manager = Self { + grid_id, user, editor_map, block_id_by_row_id, @@ -56,25 +61,41 @@ impl GridBlockMetaEditorManager { } } - pub(crate) async fn create_row(&self, row: RowMeta, upper_row_id: Option) -> FlowyResult { - self.block_id_by_row_id.insert(row.id.clone(), row.block_id.clone()); - let editor = self.get_editor(&row.block_id).await?; - editor.create_row(row, upper_row_id).await + pub(crate) async fn create_row( + &self, + field_metas: &[FieldMeta], + row_meta: RowMeta, + upper_row_id: Option, + ) -> FlowyResult { + self.block_id_by_row_id + .insert(row_meta.id.clone(), row_meta.block_id.clone()); + let editor = self.get_editor(&row_meta.block_id).await?; + + let rows = make_rows(field_metas, vec![row_meta.clone().into()]); + send_dart_notification(&self.grid_id, GridNotification::GridDidCreateRows) + .payload(RepeatedRow::from(rows)) + .send(); + + self.notify_did_create_rows(field_metas, vec![row_meta.clone()]); + + editor.create_row(row_meta, upper_row_id).await } pub(crate) async fn insert_row( &self, + field_metas: &[FieldMeta], rows_by_block_id: HashMap>, ) -> FlowyResult> { let mut changesets = vec![]; - for (block_id, rows) in rows_by_block_id { + for (block_id, row_metas) in rows_by_block_id { let editor = self.get_editor(&block_id).await?; let mut row_count = 0; - for row in rows { + for row in &row_metas { self.block_id_by_row_id.insert(row.id.clone(), row.block_id.clone()); - row_count = editor.create_row(row, None).await?; + row_count = editor.create_row(row.clone(), None).await?; } changesets.push(GridBlockChangeset::from_row_count(&block_id, row_count)); + self.notify_did_create_rows(field_metas, row_metas); } Ok(changesets) @@ -104,19 +125,17 @@ impl GridBlockMetaEditorManager { } pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { - match self.block_id_by_row_id.get(&changeset.row_id) { - None => { - let msg = format!( - "Update Row failed. Can't find the corresponding block with row_id: {}", - changeset.row_id - ); - Err(FlowyError::internal().context(msg)) - } - Some(block_id) => { - let editor = self.get_editor(&block_id).await?; - editor.update_row(changeset).await - } - } + let editor = self.get_editor_from_row_id(&changeset.row_id).await?; + let _ = editor.update_row(changeset.clone()).await?; + let _ = self.notify_did_update_row()?; + Ok(()) + } + + pub async fn update_cells(&self, field_metas: &[FieldMeta], changeset: RowMetaChangeset) -> FlowyResult<()> { + let editor = self.get_editor_from_row_id(&changeset.row_id).await?; + let _ = editor.update_row(changeset.clone()).await?; + self.notify_did_update_cells(changeset, field_metas)?; + Ok(()) } pub(crate) async fn get_all_rows(&self, grid_blocks: Vec) -> FlowyResult>> { @@ -159,6 +178,68 @@ impl GridBlockMetaEditorManager { } Ok(row_metas) } + + async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { + match self.block_id_by_row_id.get(row_id) { + None => { + let msg = format!( + "Update Row failed. Can't find the corresponding block with row_id: {}", + row_id + ); + Err(FlowyError::internal().context(msg)) + } + Some(block_id) => { + let editor = self.get_editor(&block_id).await?; + Ok(editor) + } + } + } + + fn notify_did_create_rows(&self, field_metas: &[FieldMeta], row_metas: Vec) { + let rows = make_rows( + field_metas, + row_metas + .into_iter() + .map(|row_meta| Arc::new(row_meta)) + .collect::>(), + ); + send_dart_notification(&self.grid_id, GridNotification::GridDidCreateRows) + .payload(RepeatedRow::from(rows)) + .send(); + } + + fn notify_did_update_row(&self) -> FlowyResult<()> { + // send_dart_notification(&changeset.row_id, GridNotification::GridDidUpdateRows) + // .payload(RepeatedRow::from(cells)) + // .send(); + + todo!() + } + + fn notify_did_update_cells(&self, changeset: RowMetaChangeset, field_metas: &[FieldMeta]) -> FlowyResult<()> { + let field_meta_map = field_metas + .iter() + .map(|field_meta| (&field_meta.id, field_meta)) + .collect::>(); + + let mut cells = vec![]; + changeset + .cell_by_field_id + .into_iter() + .for_each( + |(field_id, cell_meta)| match make_cell(&field_meta_map, field_id, cell_meta) { + None => {} + Some((_, cell)) => cells.push(cell), + }, + ); + + if !cells.is_empty() { + send_dart_notification(&changeset.row_id, GridNotification::GridDidUpdateCells) + .payload(RepeatedCell::from(cells)) + .send(); + } + Ok(()) + } } async fn make_block_meta_editor_map( diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index f6730565ed..491a2831bb 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,16 +1,17 @@ use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; use bytes::Bytes; -use flowy_collaboration::client_grid::{GridChange, GridMetaPad}; +use flowy_collaboration::client_grid::{GridChangeset, GridMetaPad}; use flowy_collaboration::entities::revision::Revision; use flowy_collaboration::util::make_delta_from_revisions; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - CellMetaChangeset, FieldChangeset, FieldMeta, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder, - RepeatedRowOrder, Row, RowMeta, RowMetaChangeset, + Cell, CellMetaChangeset, Field, FieldChangeset, FieldMeta, Grid, GridBlock, GridBlockChangeset, RepeatedField, + RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder, Row, RowMeta, RowMetaChangeset, }; use std::collections::HashMap; +use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::services::row::{ make_row_by_row_id, make_rows, row_meta_from_context, serialize_cell_data, RowMetaContext, RowMetaContextBuilder, }; @@ -40,8 +41,9 @@ impl ClientGridEditor { let rev_manager = Arc::new(rev_manager); let grid_meta_pad = Arc::new(RwLock::new(grid_pad)); - let block_meta_manager = - Arc::new(GridBlockMetaEditorManager::new(&user, grid_meta_pad.read().await.get_blocks().clone()).await?); + let block_meta_manager = Arc::new( + GridBlockMetaEditorManager::new(grid_id, &user, grid_meta_pad.read().await.get_blocks().clone()).await?, + ); Ok(Arc::new(Self { grid_id: grid_id.to_owned(), @@ -54,6 +56,7 @@ impl ClientGridEditor { pub async fn create_field(&self, field_meta: FieldMeta) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.create_field(field_meta)?)).await?; + let _ = self.notify_did_update_fields().await?; Ok(()) } @@ -81,7 +84,7 @@ impl ClientGridEditor { Ok(()) } - pub async fn create_row(&self, upper_row_id: Option) -> FlowyResult { + pub async fn create_row(&self, upper_row_id: Option) -> FlowyResult<()> { let field_metas = self.grid_meta_pad.read().await.get_field_metas(None)?; let block_id = self.last_block_id().await?; @@ -92,17 +95,17 @@ impl ClientGridEditor { // insert the row let row_count = self .block_meta_manager - .create_row(row_meta.clone(), upper_row_id) + .create_row(&field_metas, row_meta, upper_row_id) .await?; - let row = make_rows(&field_metas, vec![row_meta.into()]).pop().unwrap(); // update block row count let changeset = GridBlockChangeset::from_row_count(&block_id, row_count); let _ = self.update_block(changeset).await?; - Ok(row) + Ok(()) } pub async fn insert_rows(&self, contexts: Vec) -> FlowyResult<()> { + let field_metas = self.grid_meta_pad.read().await.get_field_metas(None)?; let block_id = self.last_block_id().await?; let mut rows_by_block_id: HashMap> = HashMap::new(); for ctx in contexts { @@ -112,7 +115,10 @@ impl ClientGridEditor { .or_insert_with(Vec::new) .push(row_meta); } - let changesets = self.block_meta_manager.insert_row(rows_by_block_id).await?; + let changesets = self + .block_meta_manager + .insert_row(&field_metas, rows_by_block_id) + .await?; for changeset in changesets { let _ = self.update_block(changeset).await?; } @@ -136,8 +142,13 @@ impl ClientGridEditor { } } + let field_metas = self.get_field_metas(None).await?; let row_changeset: RowMetaChangeset = changeset.into(); - self.update_row(row_changeset).await + let _ = self + .block_meta_manager + .update_cells(&field_metas, row_changeset) + .await?; + Ok(()) } pub async fn get_rows(&self, row_orders: Option) -> FlowyResult> { @@ -205,7 +216,7 @@ impl ClientGridEditor { async fn modify(&self, f: F) -> FlowyResult<()> where - F: for<'a> FnOnce(&'a mut GridMetaPad) -> FlowyResult>, + F: for<'a> FnOnce(&'a mut GridMetaPad) -> FlowyResult>, { let mut write_guard = self.grid_meta_pad.write().await; match f(&mut *write_guard)? { @@ -217,8 +228,8 @@ impl ClientGridEditor { Ok(()) } - async fn apply_change(&self, change: GridChange) -> FlowyResult<()> { - let GridChange { delta, md5 } = change; + async fn apply_change(&self, change: GridChangeset) -> FlowyResult<()> { + let GridChangeset { delta, md5 } = change; let user_id = self.user.user_id()?; let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let delta_data = delta.to_delta_bytes(); @@ -243,6 +254,15 @@ impl ClientGridEditor { Some(grid_block) => Ok(grid_block.id.clone()), } } + + async fn notify_did_update_fields(&self) -> FlowyResult<()> { + let field_metas = self.get_field_metas(None).await?; + let repeated_field: RepeatedField = field_metas.into_iter().map(Field::from).collect::>().into(); + send_dart_notification(&self.grid_id, GridNotification::GridDidUpdateFields) + .payload(repeated_field) + .send(); + Ok(()) + } } #[cfg(feature = "flowy_unit_test")] diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index 02a6f760e0..6283db0540 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -48,7 +48,11 @@ pub(crate) fn make_rows(fields: &[FieldMeta], row_metas: Vec>) -> V } #[inline(always)] -fn make_cell(field_map: &HashMap<&String, &FieldMeta>, field_id: String, raw_cell: CellMeta) -> Option<(String, Cell)> { +pub fn make_cell( + field_map: &HashMap<&String, &FieldMeta>, + field_id: String, + raw_cell: CellMeta, +) -> Option<(String, Cell)> { let field_meta = field_map.get(&field_id)?; match deserialize_cell_data(raw_cell.data, field_meta) { Ok(content) => { @@ -63,9 +67,9 @@ fn make_cell(field_map: &HashMap<&String, &FieldMeta>, field_id: String, raw_cel } pub(crate) fn make_row_by_row_id(fields: &[FieldMeta], row_metas: Vec>) -> HashMap { - let field_map = fields + let field_meta_map = fields .iter() - .map(|field| (&field.id, field)) + .map(|field_meta| (&field_meta.id, field_meta)) .collect::>(); let make_row = |row_meta: Arc| { @@ -73,7 +77,7 @@ pub(crate) fn make_row_by_row_id(fields: &[FieldMeta], row_metas: Vec>(); let row = Row { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index a9bc34c18c..6449d09f6f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -172,7 +172,7 @@ impl GridEditorTest { assert_eq!(compared_block, block); } EditorScript::CreateEmptyRow => { - self.editor.create_row().await.unwrap(); + self.editor.create_row(None).await.unwrap(); self.row_metas = self.editor.get_row_metas(None).await.unwrap(); self.grid_blocks = self.editor.get_blocks().await.unwrap(); } diff --git a/shared-lib/flowy-collaboration/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-collaboration/src/client_grid/grid_meta_pad.rs index e836034fae..a403b9c1c9 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/grid_meta_pad.rs @@ -35,7 +35,7 @@ impl GridMetaPad { Self::from_delta(grid_delta) } - pub fn create_field(&mut self, field_meta: FieldMeta) -> CollaborateResult> { + pub fn create_field(&mut self, field_meta: FieldMeta) -> CollaborateResult> { self.modify_grid(|grid| { if grid.fields.contains(&field_meta) { tracing::warn!("Duplicate grid field"); @@ -47,7 +47,7 @@ impl GridMetaPad { }) } - pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult> { + pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult> { self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) { None => Ok(None), Some(index) => { @@ -95,7 +95,7 @@ impl GridMetaPad { } } - pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult> { + pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult> { let field_id = changeset.field_id.clone(); self.modify_field(&field_id, |field| { let mut is_changed = None; @@ -138,7 +138,7 @@ impl GridMetaPad { }) } - pub fn create_block(&mut self, block: GridBlock) -> CollaborateResult> { + pub fn create_block(&mut self, block: GridBlock) -> CollaborateResult> { self.modify_grid(|grid| { if grid.blocks.iter().any(|b| b.id == block.id) { tracing::warn!("Duplicate grid block"); @@ -165,7 +165,7 @@ impl GridMetaPad { self.grid_meta.blocks.clone() } - pub fn update_block(&mut self, changeset: GridBlockChangeset) -> CollaborateResult> { + pub fn update_block(&mut self, changeset: GridBlockChangeset) -> CollaborateResult> { let block_id = changeset.block_id.clone(); self.modify_block(&block_id, |block| { let mut is_changed = None; @@ -200,7 +200,7 @@ impl GridMetaPad { &self.grid_meta.fields } - fn modify_grid(&mut self, f: F) -> CollaborateResult> + fn modify_grid(&mut self, f: F) -> CollaborateResult> where F: FnOnce(&mut GridMeta) -> CollaborateResult>, { @@ -214,14 +214,14 @@ impl GridMetaPad { None => Ok(None), Some(delta) => { self.delta = self.delta.compose(&delta)?; - Ok(Some(GridChange { delta, md5: self.md5() })) + Ok(Some(GridChangeset { delta, md5: self.md5() })) } } } } } - pub fn modify_block(&mut self, block_id: &str, f: F) -> CollaborateResult> + pub fn modify_block(&mut self, block_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut GridBlock) -> CollaborateResult>, { @@ -234,7 +234,7 @@ impl GridMetaPad { }) } - pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> + pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut FieldMeta) -> CollaborateResult>, { @@ -254,7 +254,7 @@ fn json_from_grid(grid: &Arc) -> CollaborateResult { Ok(json) } -pub struct GridChange { +pub struct GridChangeset { pub delta: GridMetaDelta, /// md5: the md5 of the grid after applying the change. pub md5: String, diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index 441cc7d39e..36e8e211e3 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -204,6 +204,31 @@ impl Cell { } } +#[derive(Debug, Default, ProtoBuf)] +pub struct RepeatedCell { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::ops::Deref for RepeatedCell { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.items + } +} + +impl std::ops::DerefMut for RepeatedCell { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.items + } +} + +impl std::convert::From> for RepeatedCell { + fn from(items: Vec) -> Self { + Self { items } + } +} + #[derive(ProtoBuf, Default)] pub struct CreateGridPayload { #[pb(index = 1)] diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index abe55edbad..9702766975 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -2115,6 +2115,172 @@ impl ::protobuf::reflect::ProtobufValue for Cell { } } +#[derive(PartialEq,Clone,Default)] +pub struct RepeatedCell { + // message fields + pub items: ::protobuf::RepeatedField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a RepeatedCell { + fn default() -> &'a RepeatedCell { + ::default_instance() + } +} + +impl RepeatedCell { + pub fn new() -> RepeatedCell { + ::std::default::Default::default() + } + + // repeated .Cell items = 1; + + + pub fn get_items(&self) -> &[Cell] { + &self.items + } + pub fn clear_items(&mut self) { + self.items.clear(); + } + + // Param is passed by value, moved + pub fn set_items(&mut self, v: ::protobuf::RepeatedField) { + self.items = v; + } + + // Mutable pointer to the field. + pub fn mut_items(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.items + } + + // Take field + pub fn take_items(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.items, ::protobuf::RepeatedField::new()) + } +} + +impl ::protobuf::Message for RepeatedCell { + fn is_initialized(&self) -> bool { + for v in &self.items { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.items)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + for value in &self.items { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + for v in &self.items { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> RepeatedCell { + RepeatedCell::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "items", + |m: &RepeatedCell| { &m.items }, + |m: &mut RepeatedCell| { &mut m.items }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "RepeatedCell", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static RepeatedCell { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(RepeatedCell::new) + } +} + +impl ::protobuf::Clear for RepeatedCell { + fn clear(&mut self) { + self.items.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for RepeatedCell { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for RepeatedCell { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct CreateGridPayload { // message fields @@ -3129,16 +3295,17 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\ \x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\";\n\x04Cell\x12\ \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\ - \x18\x02\x20\x01(\tR\x07content\"'\n\x11CreateGridPayload\x12\x12\n\x04n\ - ame\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\ - \x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\ - \x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cupper_row_id\x18\x02\x20\x01(\ - \tH\0R\nupperRowIdB\x15\n\x13one_of_upper_row_id\"d\n\x11QueryFieldPaylo\ - ad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_or\ - ders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"\\\n\ - \x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x120\n\nrow_orders\x18\x02\x20\x01(\x0b2\x11.RepeatedRowOrderR\trowOrde\ - rsb\x06proto3\ + \x18\x02\x20\x01(\tR\x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\ + \x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\ + \x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\ + \x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayload\x12\x17\ + \n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cupper_row_id\x18\ + \x02\x20\x01(\tH\0R\nupperRowIdB\x15\n\x13one_of_upper_row_id\"d\n\x11Qu\ + eryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\ + \n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfiel\ + dOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\t\ + R\x06gridId\x120\n\nrow_orders\x18\x02\x20\x01(\x0b2\x11.RepeatedRowOrde\ + rR\trowOrdersb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index 7f01016174..ed6fc83b65 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -43,6 +43,9 @@ message Cell { string field_id = 1; string content = 2; } +message RepeatedCell { + repeated Cell items = 1; +} message CreateGridPayload { string name = 1; }