From 1f30a77f1d43681840f342887721b61973508193 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 20 Mar 2022 17:17:06 +0800 Subject: [PATCH 01/47] feat: save text cell data --- frontend/app_flowy/lib/plugin/plugin.dart | 6 - .../lib/workspace/application/appearance.dart | 14 +- .../grid/cell_bloc/text_cell_bloc.dart | 1 + .../workspace/application/grid/grid_bloc.dart | 56 +++---- .../application/grid/grid_block_service.dart | 56 ++++--- .../application/grid/grid_service.dart | 4 +- .../workspace/application/grid/row_bloc.dart | 34 ++--- .../home/menu/app/section/section.dart | 8 +- .../presentation/plugins/blank/blank.dart | 2 +- .../presentation/plugins/doc/document.dart | 84 +---------- .../presentation/plugins/grid/grid.dart | 6 +- .../plugins/grid/src/grid_page.dart | 72 ++++----- .../grid/src/widgets/content/grid_row.dart | 139 +++++++++--------- .../grid/src/widgets/content/text_cell.dart | 39 +++-- .../grid/src/widgets/header/header.dart | 18 ++- .../plugins/widgets/left_bar_item.dart | 74 ++++++++++ .../packages/flowy_infra/lib/notifier.dart | 21 ++- .../flowy-grid-data-model/grid.pb.dart | 16 +- .../flowy-grid-data-model/grid.pbjson.dart | 4 +- .../flowy-grid/dart_notification.pbenum.dart | 8 +- .../flowy-grid/dart_notification.pbjson.dart | 8 +- .../flowy-grid/src/dart_notification.rs | 8 +- frontend/rust-lib/flowy-grid/src/manager.rs | 2 +- .../src/protobuf/model/dart_notification.rs | 22 +-- .../protobuf/proto/dart_notification.proto | 6 +- .../src/services/block_meta_editor.rs | 35 +++-- .../flowy-grid/src/services/row/row_loader.rs | 6 +- .../flowy-revision/src/rev_manager.rs | 2 + .../src/entities/grid.rs | 10 +- .../src/protobuf/model/grid.rs | 78 +++++----- .../src/protobuf/proto/grid.proto | 2 +- .../src/client_grid/grid_block_meta_pad.rs | 37 ++--- 32 files changed, 473 insertions(+), 405 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart diff --git a/frontend/app_flowy/lib/plugin/plugin.dart b/frontend/app_flowy/lib/plugin/plugin.dart index 607ebaab53..8d30b122ad 100644 --- a/frontend/app_flowy/lib/plugin/plugin.dart +++ b/frontend/app_flowy/lib/plugin/plugin.dart @@ -61,12 +61,6 @@ abstract class PluginConfig { } abstract class PluginDisplay with NavigationItem { - @override - Widget get leftBarItem; - - @override - Widget? get rightBarItem; - List get navigationItems; PublishNotifier? get notifier => null; diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 87cd7e1af8..ffd7e18c92 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:app_flowy/user/application/user_settings_service.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_infra/theme.dart'; @@ -11,7 +13,7 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { AppearanceSettings setting; AppTheme _theme; Locale _locale; - CancelableOperation? _saveOperation; + Timer? _saveOperation; AppearanceSettingModel(this.setting) : _theme = AppTheme.fromName(name: setting.theme), @@ -21,12 +23,10 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { Locale get locale => _locale; Future save() async { - _saveOperation?.cancel; - _saveOperation = CancelableOperation.fromFuture( - Future.delayed(const Duration(seconds: 1), () async { - await UserSettingsService().setAppearanceSettings(setting); - }), - ); + _saveOperation?.cancel(); + _saveOperation = Timer(const Duration(seconds: 2), () async { + await UserSettingsService().setAppearanceSettings(setting); + }); } @override diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index 80bc722be7..407cde3d2c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -17,6 +17,7 @@ class TextCellBloc extends Bloc { initial: (_InitialCell value) async {}, updateText: (_UpdateText value) { service.updateCell(data: value.text); + emit(state.copyWith(content: value.text)); }, ); }, 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 1db06d815c..fd2fefbac5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -1,5 +1,6 @@ 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'; @@ -32,7 +33,7 @@ class GridBloc extends Bloc { delete: (_Delete value) {}, rename: (_Rename value) {}, updateDesc: (_Desc value) {}, - didLoadRows: (_DidLoadRows value) { + rowsDidUpdate: (_RowsDidUpdate value) { emit(state.copyWith(rows: value.rows)); }, ); @@ -47,10 +48,19 @@ class GridBloc extends Bloc { return super.close(); } - Future _startGridListening() async { - _blockService.didLoadRowscallback = (rows) { - add(GridEvent.didLoadRows(rows)); - }; + Future _initGridBlockService(Grid grid, List fields) async { + _blockService = GridBlockService( + gridId: grid.id, + fields: fields, + blockOrders: grid.blockOrders, + ); + + _blockService.rowsUpdateNotifier.addPublishListener((result) { + result.fold( + (rows) => add(GridEvent.rowsDidUpdate(rows)), + (err) => Log.error('$err'), + ); + }); _gridListener.start(); } @@ -70,36 +80,18 @@ class GridBloc extends Bloc { final result = await service.getFields(gridId: grid.id, fieldOrders: grid.fieldOrders); return Future( () => result.fold( - (fields) => _loadGridBlocks(grid, fields.items, emit), + (fields) { + _initGridBlockService(grid, fields.items); + emit(state.copyWith( + grid: Some(grid), + fields: Some(fields.items), + loadingState: GridLoadingState.finish(left(unit)), + )); + }, (err) => emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))), ), ); } - - Future _loadGridBlocks(Grid grid, List fields, Emitter emit) async { - final result = await service.getGridBlocks(gridId: grid.id, blockOrders: grid.blockOrders); - result.fold( - (repeatedGridBlock) { - final gridBlocks = repeatedGridBlock.items; - final gridId = view.id; - _blockService = GridBlockService( - gridId: gridId, - fields: fields, - gridBlocks: gridBlocks, - ); - final rows = _blockService.rows(); - - _startGridListening(); - emit(state.copyWith( - grid: Some(grid), - fields: Some(fields), - rows: rows, - loadingState: GridLoadingState.finish(left(unit)), - )); - }, - (err) => emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)), rows: [])), - ); - } } @freezed @@ -109,7 +101,7 @@ abstract class GridEvent with _$GridEvent { const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; - const factory GridEvent.didLoadRows(List rows) = _DidLoadRows; + const factory GridEvent.rowsDidUpdate(List rows) = _RowsDidUpdate; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart index 3672a910f4..f84278399c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart @@ -1,5 +1,7 @@ import 'dart:collection'; import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; @@ -9,40 +11,38 @@ import 'package:flowy_infra/notifier.dart'; import 'dart:async'; import 'dart:typed_data'; import 'package:app_flowy/core/notification_helper.dart'; - import 'grid_service.dart'; -typedef DidLoadRowsCallback = void Function(List); -typedef GridBlockUpdateNotifiedValue = Either; +typedef RowsUpdateNotifierValue = Either, FlowyError>; class GridBlockService { String gridId; List fields; LinkedHashMap blockMap = LinkedHashMap(); late GridBlockListener _blockListener; - DidLoadRowsCallback? didLoadRowscallback; + PublishNotifier rowsUpdateNotifier = PublishNotifier(); - GridBlockService({required this.gridId, required this.fields, required List gridBlocks}) { - for (final gridBlock in gridBlocks) { - blockMap[gridBlock.blockId] = gridBlock; - } + GridBlockService({required this.gridId, required this.fields, required List blockOrders}) { + _loadGridBlocks(blockOrders: blockOrders); _blockListener = GridBlockListener(gridId: gridId); - _blockListener.blockUpdateNotifier.addPublishListener((result) { - result.fold((blockId) { - // - }, (err) => null); + _blockListener.rowsUpdateNotifier.addPublishListener((result) { + result.fold( + (blockId) => _loadGridBlocks(blockOrders: [GridBlockOrder.create()..blockId = blockId.value]), + (err) => Log.error(err), + ); }); + _blockListener.start(); } - List rows() { + List buildRows() { List rows = []; blockMap.forEach((_, GridBlock gridBlock) { rows.addAll(gridBlock.rowOrders.map( (rowOrder) => GridRowData( gridId: gridId, fields: fields, - blockId: gridBlock.blockId, + blockId: gridBlock.id, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), ), @@ -54,11 +54,29 @@ class GridBlockService { Future stop() async { await _blockListener.stop(); } + + void _loadGridBlocks({required List blockOrders}) { + final payload = QueryGridBlocksPayload.create() + ..gridId = gridId + ..blockOrders.addAll(blockOrders); + + GridEventGetGridBlocks(payload).send().then((result) { + result.fold( + (repeatedBlocks) { + for (final gridBlock in repeatedBlocks.items) { + blockMap[gridBlock.id] = gridBlock; + } + rowsUpdateNotifier.value = left(buildRows()); + }, + (err) => rowsUpdateNotifier.value = right(err), + ); + }); + } } class GridBlockListener { final String gridId; - PublishNotifier blockUpdateNotifier = PublishNotifier(); + PublishNotifier> rowsUpdateNotifier = PublishNotifier(comparable: null); StreamSubscription? _subscription; late GridNotificationParser _parser; @@ -77,10 +95,10 @@ class GridBlockListener { void _handleObservableType(GridNotification ty, Either result) { switch (ty) { - case GridNotification.GridDidUpdateBlock: + case GridNotification.BlockDidUpdateRow: result.fold( - (payload) => blockUpdateNotifier.value = left(GridBlockId.fromBuffer(payload)), - (error) => blockUpdateNotifier.value = right(error), + (payload) => rowsUpdateNotifier.value = left(GridBlockId.fromBuffer(payload)), + (error) => rowsUpdateNotifier.value = right(error), ); break; @@ -91,6 +109,6 @@ class GridBlockListener { Future stop() async { await _subscription?.cancel(); - blockUpdateNotifier.dispose(); + rowsUpdateNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 506401706b..2aafd02fba 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -13,9 +13,9 @@ class GridService { return GridEventGetGridData(payload).send(); } - Future> createRow({required String gridId, Option? upperRowId}) { + Future> createRow({required String gridId, Option? startRowId}) { CreateRowPayload payload = CreateRowPayload.create()..gridId = gridId; - upperRowId?.fold(() => null, (id) => payload.startRowId = id); + startRowId?.fold(() => null, (id) => payload.startRowId = id); return GridEventCreateRow(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart index bf13c682d7..67fcc5cbc2 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart @@ -19,7 +19,7 @@ class RowBloc extends Bloc { await event.map( initial: (_InitialRow value) async { _startRowListening(); - await _loadCellDatas(emit); + await _loadRow(emit); }, createRow: (_CreateRow value) { rowService.createRow(); @@ -58,20 +58,20 @@ class RowBloc extends Bloc { listener.start(); } - Future _loadCellDatas(Emitter emit) async { - final result = await rowService.getRow(); - result.fold( - (row) { - emit(state.copyWith( - cellDatas: makeGridCellDatas(row), - rowHeight: row.height.toDouble(), - )); - }, - (e) => Log.error(e), - ); + Future _loadRow(Emitter emit) async { + final Future> cellDatas = rowService.getRow().then((result) { + return result.fold( + (row) => _makeCellDatas(row), + (e) { + Log.error(e); + return []; + }, + ); + }); + emit(state.copyWith(cellDatas: cellDatas)); } - List makeGridCellDatas(Row row) { + List _makeCellDatas(Row row) { return rowService.rowData.fields.map((field) { final cell = row.cellByFieldId[field.id]; final rowData = rowService.rowData; @@ -96,18 +96,18 @@ abstract class RowEvent with _$RowEvent { } @freezed -abstract class RowState with _$RowState { +class RowState with _$RowState { const factory RowState({ required String rowId, required double rowHeight, - required List cellDatas, + required Future> cellDatas, required bool active, }) = _RowState; factory RowState.initial(GridRowData data) => RowState( rowId: data.rowId, - active: false, rowHeight: data.height, - cellDatas: [], + cellDatas: Future(() => []), + active: false, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart index dcb2d454b9..ed0a718f58 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/view/view_ext.dart'; import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; @@ -64,7 +66,7 @@ class ViewSectionNotifier with ChangeNotifier { bool isDisposed = false; List _views; View? _selectedView; - CancelableOperation? _notifyListenerOperation; + Timer? _notifyListenerOperation; ViewSectionNotifier({ required BuildContext context, @@ -120,9 +122,7 @@ class ViewSectionNotifier with ChangeNotifier { void _notifyListeners() { _notifyListenerOperation?.cancel(); - _notifyListenerOperation = CancelableOperation.fromFuture( - Future.delayed(const Duration(milliseconds: 30), () {}), - ).then((_) { + _notifyListenerOperation = Timer(const Duration(milliseconds: 30), () { if (!isDisposed) { notifyListeners(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart index 598f6971f2..05456f20f4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/blank/blank.dart @@ -40,7 +40,7 @@ class BlankPagePlugin extends Plugin { PluginType get ty => _pluginType; } -class BlankPagePluginDisplay extends PluginDisplay { +class BlankPagePluginDisplay extends PluginDisplay with NavigationItem { @override Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart index f027bf3e7a..e8f0290123 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart @@ -10,14 +10,13 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/share_bloc.dart'; import 'package:app_flowy/workspace/application/view/view_listener.dart'; -import 'package:app_flowy/workspace/application/view/view_service.dart'; import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; +import 'package:app_flowy/workspace/presentation/plugins/widgets/left_bar_item.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_infra/size.dart'; -import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_sdk/log.dart'; @@ -89,7 +88,7 @@ class DocumentPlugin implements Plugin { PluginId get id => _view.id; } -class DocumentPluginDisplay extends PluginDisplay { +class DocumentPluginDisplay extends PluginDisplay with NavigationItem { final PublishNotifier _displayNotifier = PublishNotifier(); final View _view; @@ -99,91 +98,16 @@ class DocumentPluginDisplay extends PluginDisplay { Widget buildWidget() => DocumentPage(view: _view, key: ValueKey(_view.id)); @override - Widget get leftBarItem => DocumentLeftBarItem(view: _view); + Widget get leftBarItem => ViewLeftBarItem(view: _view); @override Widget? get rightBarItem => DocumentShareButton(view: _view); @override - List get navigationItems => _makeNavigationItems(); + List get navigationItems => [this]; @override PublishNotifier? get notifier => _displayNotifier; - - List _makeNavigationItems() { - return [ - this, - ]; - } -} - -class DocumentLeftBarItem extends StatefulWidget { - final View view; - - DocumentLeftBarItem({required this.view, Key? key}) : super(key: ValueKey(view.hashCode)); - - @override - State createState() => _DocumentLeftBarItemState(); -} - -class _DocumentLeftBarItemState extends State { - final _controller = TextEditingController(); - final _focusNode = FocusNode(); - late ViewService service; - - @override - void initState() { - service = ViewService(/*view: widget.view*/); - _focusNode.addListener(_handleFocusChanged); - super.initState(); - } - - @override - void dispose() { - _controller.dispose(); - _focusNode.removeListener(_handleFocusChanged); - _focusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - _controller.text = widget.view.name; - - final theme = context.watch(); - return IntrinsicWidth( - key: ValueKey(_controller.text), - child: TextField( - controller: _controller, - focusNode: _focusNode, - scrollPadding: EdgeInsets.zero, - decoration: const InputDecoration( - contentPadding: EdgeInsets.zero, - border: InputBorder.none, - isDense: true, - ), - style: TextStyle( - color: theme.textColor, - fontSize: 14, - fontWeight: FontWeight.w500, - overflow: TextOverflow.ellipsis, - ), - // cursorColor: widget.cursorColor, - // obscureText: widget.enableObscure, - ), - ); - } - - void _handleFocusChanged() { - if (_controller.text.isEmpty) { - _controller.text = widget.view.name; - return; - } - - if (_controller.text != widget.view.name) { - service.updateView(viewId: widget.view.id, name: _controller.text); - } - } } class DocumentShareButton extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart index cf6b4c9032..adc2a91fa9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/grid.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:app_flowy/workspace/presentation/plugins/widgets/left_bar_item.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:app_flowy/plugin/plugin.dart'; import 'package:flutter/material.dart'; @@ -28,7 +28,7 @@ class GridPluginBuilder implements PluginBuilder { class GridPluginConfig implements PluginConfig { @override - bool get creatable => false; + bool get creatable => true; } class GridPlugin extends Plugin { @@ -56,7 +56,7 @@ class GridPluginDisplay extends PluginDisplay { GridPluginDisplay({required View view, Key? key}) : _view = view; @override - Widget get leftBarItem => const FlowyText.medium("Grid demo", fontSize: 12); + Widget get leftBarItem => ViewLeftBarItem(view: _view); @override Widget buildWidget() => GridPage(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 4e7747ac1d..1d6bc07891 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 @@ -84,42 +84,38 @@ class _FlowyGridState extends State { @override Widget build(BuildContext context) { return BlocBuilder( + buildWhen: (previous, current) => previous.fields != current.fields, builder: (context, state) { return state.fields.fold( () => const Center(child: CircularProgressIndicator.adaptive()), - (fields) => _renderGrid(context, fields), + (fields) => _wrapScrollbar(fields, [ + _buildHeader(fields), + _buildRows(context), + const GridFooter(), + ]), ); }, ); } - Widget _renderGrid(BuildContext context, List fields) { - return Stack( - children: [ - StyledSingleChildScrollView( - controller: _scrollController.horizontalController, - axis: Axis.horizontal, - child: SizedBox( - width: GridLayout.headerWidth(fields), - child: CustomScrollView( - physics: StyledScrollPhysics(), - controller: _scrollController.verticalController, - slivers: [ - _buildHeader(fields), - _buildRows(context), - const GridFooter(), - ], - ), + Widget _wrapScrollbar(List fields, List children) { + return ScrollbarListStack( + axis: Axis.vertical, + controller: _scrollController.verticalController, + barSize: GridSize.scrollBarSize, + child: StyledSingleChildScrollView( + controller: _scrollController.horizontalController, + axis: Axis.horizontal, + child: SizedBox( + width: GridLayout.headerWidth(fields), + child: CustomScrollView( + physics: StyledScrollPhysics(), + controller: _scrollController.verticalController, + slivers: [...children], ), ), - ScrollbarListStack( - axis: Axis.vertical, - controller: _scrollController.verticalController, - barSize: GridSize.scrollBarSize, - child: Container(), - ).padding(right: 0, top: GridSize.headerHeight, bottom: GridSize.scrollBarSize), - ], - ); + ), + ).padding(right: 0, top: GridSize.headerHeight, bottom: GridSize.scrollBarSize); } Widget _buildHeader(List fields) { @@ -131,15 +127,21 @@ class _FlowyGridState extends State { } Widget _buildRows(BuildContext context) { - return SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - final rowData = context.read().state.rows[index]; - return GridRowWidget(data: rowData); - }, - childCount: context.read().state.rows.length, - addRepaintBoundaries: true, - ), + return BlocBuilder( + buildWhen: (previous, current) => previous.rows.length != current.rows.length, + builder: (context, state) { + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final rowData = context.read().state.rows[index]; + return GridRowWidget(data: rowData); + }, + childCount: context.read().state.rows.length, + addRepaintBoundaries: true, + addAutomaticKeepAlives: true, + ), + ); + }, ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index f062202744..3efc47d33c 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -11,7 +11,7 @@ import 'cell_container.dart'; class GridRowWidget extends StatefulWidget { final GridRowData data; - GridRowWidget({required this.data, Key? key}) : super(key: ObjectKey(data.rowId)); + GridRowWidget({required this.data, Key? key}) : super(key: ValueKey(data.rowId)); @override State createState() => _GridRowWidgetState(); @@ -30,28 +30,25 @@ class _GridRowWidgetState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _rowBloc, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), - onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: _rowBloc.state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const LeadingRow(), - _buildCells(), - const TrailingRow(), - ], - ), - ); - }, - ), + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), + onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: _rowBloc.state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, ), ), ); @@ -62,69 +59,37 @@ class _GridRowWidgetState extends State { _rowBloc.close(); super.dispose(); } - - Widget _buildCells() { - return BlocBuilder( - buildWhen: (p, c) => p.cellDatas != c.cellDatas, - builder: (context, state) { - return Row( - children: state.cellDatas - .map( - (cellData) => CellContainer( - width: cellData.field.width.toDouble(), - child: buildGridCell(cellData), - ), - ) - .toList(), - ); - }, - ); - } } -class LeadingRow extends StatelessWidget { - const LeadingRow({Key? key}) : super(key: key); +class _RowLeading extends StatelessWidget { + const _RowLeading({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocSelector( selector: (state) => state.active, builder: (context, isActive) { - return SizedBox( - width: GridSize.leadingHeaderPadding, - child: isActive - ? Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - AppendRowButton(), - ], - ) - : null, - ); + return SizedBox(width: GridSize.leadingHeaderPadding, child: isActive ? _activeWidget() : null); }, ); } + + Widget _activeWidget() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + AppendRowButton(), + ], + ); + } } -class TrailingRow extends StatelessWidget { - const TrailingRow({Key? key}) : super(key: key); +class _RowTrailing extends StatelessWidget { + const _RowTrailing({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final theme = context.watch(); - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - - return BlocBuilder( - builder: (context, state) { - return Container( - width: GridSize.trailHeaderPadding, - decoration: BoxDecoration( - border: Border(bottom: borderSide), - ), - padding: GridSize.cellContentInsets, - ); - }, - ); + return const SizedBox(); } } @@ -143,3 +108,37 @@ class AppendRowButton extends StatelessWidget { ); } } + +class _RowCells extends StatelessWidget { + const _RowCells({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) => previous.cellDatas != current.cellDatas, + builder: (context, state) { + return FutureBuilder( + future: state.cellDatas, + builder: builder, + ); + }, + ); + } + + Widget builder(context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + List cellDatas = snapshot.data; + return Row(children: cellDatas.map(_toCell).toList()); + default: + return const SizedBox(); + } + } + + Widget _toCell(GridCellData data) { + return CellContainer( + width: data.field.width.toDouble(), + child: buildGridCell(data), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart index 71ab0c41bd..937c5d84ab 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart @@ -1,6 +1,9 @@ +import 'dart:async'; + import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/cell_bloc/text_cell_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -19,27 +22,40 @@ class GridTextCell extends StatefulWidget { class _GridTextCellState extends State { late TextEditingController _controller; + Timer? _delayOperation; final _focusNode = FocusNode(); - late TextCellBloc _cellBloc; + TextCellBloc? _cellBloc; @override void initState() { _cellBloc = getIt(param1: widget.cellData); - _controller = TextEditingController(text: _cellBloc.state.content); - _focusNode.addListener(_focusChanged); + _controller = TextEditingController(text: _cellBloc!.state.content); + _focusNode.addListener(save); super.initState(); } @override Widget build(BuildContext context) { return BlocProvider.value( - value: _cellBloc, + value: _cellBloc!, child: BlocBuilder( + buildWhen: (previous, current) { + return _controller.text != current.content; + }, builder: (context, state) { return TextField( controller: _controller, focusNode: _focusNode, - onChanged: (value) {}, + onChanged: (value) { + Log.info("On change"); + save(); + }, + onEditingComplete: () { + Log.info("On complete"); + }, + onSubmitted: (value) { + Log.info("On submit"); + }, maxLines: 1, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), decoration: const InputDecoration( @@ -55,13 +71,18 @@ class _GridTextCellState extends State { @override Future dispose() async { - _cellBloc.close(); - _focusNode.removeListener(_focusChanged); + _cellBloc?.close(); + _cellBloc = null; + _focusNode.removeListener(save); _focusNode.dispose(); super.dispose(); } - void _focusChanged() { - _cellBloc.add(TextCellEvent.updateText(_controller.text)); + Future save() async { + _delayOperation?.cancel(); + _delayOperation = Timer(const Duration(seconds: 2), () { + _cellBloc?.add(TextCellEvent.updateText(_controller.text)); + }); + // and later, before the timer goes off... } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index 83d24535f4..e84640a584 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -42,6 +42,7 @@ class GridHeader extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = context.watch(); return BlocProvider( create: (context) => getIt(param1: fields)..add(const ColumnEvent.initial()), child: BlocBuilder( @@ -55,13 +56,16 @@ class GridHeader extends StatelessWidget { ) .toList(); - return Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const LeadingHeaderCell(), - ...headers, - const TrailingHeaderCell(), - ], + return Container( + color: theme.surface, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const LeadingHeaderCell(), + ...headers, + const TrailingHeaderCell(), + ], + ), ); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart new file mode 100644 index 0000000000..7c1e819cc5 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart @@ -0,0 +1,74 @@ +import 'package:app_flowy/workspace/application/view/view_service.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class ViewLeftBarItem extends StatefulWidget { + final View view; + + ViewLeftBarItem({required this.view, Key? key}) : super(key: ValueKey(view.hashCode)); + + @override + State createState() => _ViewLeftBarItemState(); +} + +class _ViewLeftBarItemState extends State { + final _controller = TextEditingController(); + final _focusNode = FocusNode(); + late ViewService serviceService; + + @override + void initState() { + serviceService = ViewService(/*view: widget.view*/); + _focusNode.addListener(_handleFocusChanged); + super.initState(); + } + + @override + void dispose() { + _controller.dispose(); + _focusNode.removeListener(_handleFocusChanged); + _focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _controller.text = widget.view.name; + + final theme = context.watch(); + return IntrinsicWidth( + key: ValueKey(_controller.text), + child: TextField( + controller: _controller, + focusNode: _focusNode, + scrollPadding: EdgeInsets.zero, + decoration: const InputDecoration( + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + isDense: true, + ), + style: TextStyle( + color: theme.textColor, + fontSize: 14, + fontWeight: FontWeight.w500, + overflow: TextOverflow.ellipsis, + ), + // cursorColor: widget.cursorColor, + // obscureText: widget.enableObscure, + ), + ); + } + + void _handleFocusChanged() { + if (_controller.text.isEmpty) { + _controller.text = widget.view.name; + return; + } + + if (_controller.text != widget.view.name) { + serviceService.updateView(viewId: widget.view.id, name: _controller.text); + } + } +} diff --git a/frontend/app_flowy/packages/flowy_infra/lib/notifier.dart b/frontend/app_flowy/packages/flowy_infra/lib/notifier.dart index 0e0c6bc4cf..0079ba51a1 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/notifier.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/notifier.dart @@ -1,10 +1,29 @@ import 'package:flutter/material.dart'; +abstract class Comparable { + bool compare(T? previous, T? current); +} + +class ObjectComparable extends Comparable { + @override + bool compare(T? previous, T? current) { + return previous == current; + } +} + class PublishNotifier extends ChangeNotifier { T? _value; + Comparable? comparable = ObjectComparable(); + + PublishNotifier({this.comparable}); set value(T newValue) { - if (_value != newValue) { + if (comparable != null) { + if (comparable!.compare(_value, newValue)) { + _value = newValue; + notifyListeners(); + } + } else { _value = newValue; notifyListeners(); } 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 bc713bbdb8..4462ce8b10 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 @@ -609,19 +609,19 @@ class GridBlockOrder extends $pb.GeneratedMessage { class GridBlock extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlock', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowOrders', $pb.PbFieldType.PM, subBuilder: RowOrder.create) ..hasRequiredFields = false ; GridBlock._() : super(); factory GridBlock({ - $core.String? blockId, + $core.String? id, $core.Iterable? rowOrders, }) { final _result = create(); - if (blockId != null) { - _result.blockId = blockId; + if (id != null) { + _result.id = id; } if (rowOrders != null) { _result.rowOrders.addAll(rowOrders); @@ -650,13 +650,13 @@ class GridBlock extends $pb.GeneratedMessage { static GridBlock? _defaultInstance; @$pb.TagNumber(1) - $core.String get blockId => $_getSZ(0); + $core.String get id => $_getSZ(0); @$pb.TagNumber(1) - set blockId($core.String v) { $_setString(0, v); } + set id($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasBlockId() => $_has(0); + $core.bool hasId() => $_has(0); @$pb.TagNumber(1) - void clearBlockId() => clearField(1); + void clearId() => clearField(1); @$pb.TagNumber(2) $core.List get rowOrders => $_getList(1); 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 5e24c82178..cde3112874 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 @@ -135,13 +135,13 @@ final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg const GridBlock$json = const { '1': 'GridBlock', '2': const [ - const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, const {'1': 'row_orders', '3': 2, '4': 3, '5': 11, '6': '.RowOrder', '10': 'rowOrders'}, ], }; /// Descriptor for `GridBlock`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockDescriptor = $convert.base64Decode('CglHcmlkQmxvY2sSGQoIYmxvY2tfaWQYASABKAlSB2Jsb2NrSWQSKAoKcm93X29yZGVycxgCIAMoCzIJLlJvd09yZGVyUglyb3dPcmRlcnM='); +final $typed_data.Uint8List gridBlockDescriptor = $convert.base64Decode('CglHcmlkQmxvY2sSDgoCaWQYASABKAlSAmlkEigKCnJvd19vcmRlcnMYAiADKAsyCS5Sb3dPcmRlclIJcm93T3JkZXJz'); @$core.Deprecated('Use cellDescriptor instead') const Cell$json = const { '1': 'Cell', 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 index f68b10f292..27985d016c 100644 --- 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 @@ -11,15 +11,15 @@ 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 GridDidUpdateBlock = GridNotification._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateBlock'); static const GridNotification GridDidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateBlock'); - 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 GridNotification BlockDidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockDidUpdateRow'); + static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); + static const GridNotification GridDidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateFields'); static const $core.List values = [ Unknown, - GridDidUpdateBlock, GridDidCreateBlock, + BlockDidUpdateRow, GridDidUpdateCells, GridDidUpdateFields, ]; 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 index b266e63e09..0eebf85cc6 100644 --- 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 @@ -13,12 +13,12 @@ const GridNotification$json = const { '1': 'GridNotification', '2': const [ const {'1': 'Unknown', '2': 0}, - const {'1': 'GridDidUpdateBlock', '2': 10}, const {'1': 'GridDidCreateBlock', '2': 11}, - const {'1': 'GridDidUpdateCells', '2': 20}, - const {'1': 'GridDidUpdateFields', '2': 30}, + const {'1': 'BlockDidUpdateRow', '2': 20}, + const {'1': 'GridDidUpdateCells', '2': 30}, + const {'1': 'GridDidUpdateFields', '2': 40}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkVXBkYXRlQmxvY2sQChIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIWChJHcmlkRGlkVXBkYXRlQ2VsbHMQFBIXChNHcmlkRGlkVXBkYXRlRmllbGRzEB4='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIVChFCbG9ja0RpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhcKE0dyaWREaWRVcGRhdGVGaWVsZHMQKA=='); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 82ab35bdee..927b71d957 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -5,11 +5,13 @@ const OBSERVABLE_CATEGORY: &str = "Grid"; #[derive(ProtoBuf_Enum, Debug)] pub enum GridNotification { Unknown = 0, - GridDidUpdateBlock = 10, + GridDidCreateBlock = 11, - GridDidUpdateCells = 20, - GridDidUpdateFields = 30, + BlockDidUpdateRow = 20, + + GridDidUpdateCells = 30, + GridDidUpdateFields = 40, } impl std::default::Default for GridNotification { diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 75499acdac..e4f24a8547 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -83,7 +83,7 @@ impl GridManager { Ok(()) } - #[tracing::instrument(level = "debug", skip(self), err)] + // #[tracing::instrument(level = "debug", skip(self), err)] pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult> { match self.editor_map.get(grid_id) { None => Err(FlowyError::internal().context("Should call open_grid function first")), 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 index 72b3f12abd..4562b238c0 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -26,10 +26,10 @@ #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum GridNotification { Unknown = 0, - GridDidUpdateBlock = 10, GridDidCreateBlock = 11, - GridDidUpdateCells = 20, - GridDidUpdateFields = 30, + BlockDidUpdateRow = 20, + GridDidUpdateCells = 30, + GridDidUpdateFields = 40, } impl ::protobuf::ProtobufEnum for GridNotification { @@ -40,10 +40,10 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), - 10 => ::std::option::Option::Some(GridNotification::GridDidUpdateBlock), 11 => ::std::option::Option::Some(GridNotification::GridDidCreateBlock), - 20 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), - 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateFields), + 20 => ::std::option::Option::Some(GridNotification::BlockDidUpdateRow), + 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), + 40 => ::std::option::Option::Some(GridNotification::GridDidUpdateFields), _ => ::std::option::Option::None } } @@ -51,8 +51,8 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn values() -> &'static [Self] { static values: &'static [GridNotification] = &[ GridNotification::Unknown, - GridNotification::GridDidUpdateBlock, GridNotification::GridDidCreateBlock, + GridNotification::BlockDidUpdateRow, GridNotification::GridDidUpdateCells, GridNotification::GridDidUpdateFields, ]; @@ -83,10 +83,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x80\x01\n\x10GridNotification\x12\x0b\n\ - \x07Unknown\x10\0\x12\x16\n\x12GridDidUpdateBlock\x10\n\x12\x16\n\x12Gri\ - dDidCreateBlock\x10\x0b\x12\x16\n\x12GridDidUpdateCells\x10\x14\x12\x17\ - \n\x13GridDidUpdateFields\x10\x1eb\x06proto3\ + \n\x17dart_notification.proto*\x7f\n\x10GridNotification\x12\x0b\n\x07Un\ + known\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x15\n\x11BlockDi\ + dUpdateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x17\n\x13\ + GridDidUpdateFields\x10(b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 index 0262b34477..be25f80f3b 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -2,8 +2,8 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; - GridDidUpdateBlock = 10; GridDidCreateBlock = 11; - GridDidUpdateCells = 20; - GridDidUpdateFields = 30; + BlockDidUpdateRow = 20; + GridDidUpdateCells = 30; + GridDidUpdateFields = 40; } 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 ca3f99b363..4a73ccd1b1 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 @@ -46,7 +46,9 @@ impl GridBlockMetaEditorManager { Ok(manager) } + // #[tracing::instrument(level = "trace", skip(self))] pub(crate) async fn get_editor(&self, block_id: &str) -> FlowyResult> { + debug_assert!(!block_id.is_empty()); match self.editor_map.get(block_id) { None => { tracing::error!("The is a fatal error, block is not exist"); @@ -68,7 +70,7 @@ impl GridBlockMetaEditorManager { .insert(row_meta.id.clone(), row_meta.block_id.clone()); let editor = self.get_editor(&row_meta.block_id).await?; let row_count = editor.create_row(row_meta, start_row_id).await?; - self.notify_did_update_block(block_id).await?; + self.notify_block_did_update_row(&block_id).await?; Ok(row_count) } @@ -85,7 +87,7 @@ impl GridBlockMetaEditorManager { row_count = editor.create_row(row.clone(), None).await?; } changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); - let _ = self.notify_did_update_block(&block_id).await?; + let _ = self.notify_block_did_update_row(&block_id).await?; } Ok(changesets) @@ -108,7 +110,7 @@ impl GridBlockMetaEditorManager { pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; - let _ = self.notify_did_update_block(&editor.block_id).await?; + let _ = self.notify_block_did_update_row(&editor.block_id).await?; Ok(()) } @@ -183,11 +185,9 @@ impl GridBlockMetaEditorManager { } } - async fn notify_did_update_block(&self, block_id: &str) -> FlowyResult<()> { - let block_id = GridBlockId { - value: block_id.to_owned(), - }; - send_dart_notification(&self.grid_id, GridNotification::GridDidUpdateBlock) + async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { + let block_id: GridBlockId = block_id.into(); + send_dart_notification(&self.grid_id, GridNotification::BlockDidUpdateRow) .payload(block_id) .send(); Ok(()) @@ -277,7 +277,7 @@ impl ClientGridBlockMetaEditor { let mut row_count = 0; let _ = self .modify(|pad| { - let change = pad.add_row(row, start_row_id)?; + let change = pad.add_row_meta(row, start_row_id)?; row_count = pad.number_of_rows(); Ok(change) }) @@ -298,13 +298,22 @@ impl ClientGridBlockMetaEditor { Ok(row_count) } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { + pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult { + let row_id = changeset.row_id.clone(); let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?; - Ok(()) + let mut row_metas = self.get_row_metas(Some(vec![row_id.clone()])).await?; + debug_assert_eq!(row_metas.len(), 1); + + if row_metas.is_empty() { + return Err(FlowyError::record_not_found().context(format!("Can't find the row with id: {}", &row_id))); + } else { + let a = (**row_metas.pop().as_ref().unwrap()).clone(); + Ok(a) + } } pub async fn get_row_metas(&self, row_ids: Option>) -> FlowyResult>> { - let row_metas = self.pad.read().await.get_rows(row_ids)?; + let row_metas = self.pad.read().await.get_row_metas(row_ids)?; Ok(row_metas) } @@ -313,7 +322,7 @@ impl ClientGridBlockMetaEditor { .pad .read() .await - .get_rows(row_ids)? + .get_row_metas(row_ids)? .iter() .map(RowOrder::from) .collect::>(); 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 bf2f62c776..70cea1b4c8 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 @@ -43,10 +43,10 @@ pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec) -> FlowyResult { Ok(block_meta_snapshots .into_iter() - .map(|row_metas_per_block| { - let row_orders = make_row_orders_from_row_metas(&row_metas_per_block.row_metas); + .map(|block_meta_data| { + let row_orders = make_row_orders_from_row_metas(&block_meta_data.row_metas); GridBlock { - block_id: row_metas_per_block.block_id, + id: block_meta_data.block_id, row_orders, } }) diff --git a/frontend/rust-lib/flowy-revision/src/rev_manager.rs b/frontend/rust-lib/flowy-revision/src/rev_manager.rs index 3cd9b54de0..68d8db6f27 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_manager.rs @@ -67,6 +67,7 @@ impl RevisionManager { } } + #[tracing::instrument(level = "debug", skip_all, fields(object_id) err)] pub async fn load(&mut self, cloud: Option>) -> FlowyResult where B: RevisionObjectBuilder, @@ -80,6 +81,7 @@ impl RevisionManager { .load() .await?; self.rev_id_counter.set(rev_id); + tracing::Span::current().record("object_id", &self.object_id.as_str()); B::build_object(&self.object_id, revisions) } 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 c195a85c24..e9a80c4be3 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -181,7 +181,7 @@ pub struct GridBlockOrder { #[derive(Debug, Default, ProtoBuf)] pub struct GridBlock { #[pb(index = 1)] - pub block_id: String, + pub id: String, #[pb(index = 2)] pub row_orders: Vec, @@ -190,7 +190,7 @@ pub struct GridBlock { impl GridBlock { pub fn new(block_id: &str, row_orders: Vec) -> Self { Self { - block_id: block_id.to_owned(), + id: block_id.to_owned(), row_orders, } } @@ -269,6 +269,12 @@ impl AsRef for GridBlockId { } } +impl std::convert::From<&str> for GridBlockId { + fn from(s: &str) -> Self { + GridBlockId { value: s.to_owned() } + } +} + #[derive(ProtoBuf, Default)] pub struct CreateRowPayload { #[pb(index = 1)] 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 fc538875c9..f947f70851 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 @@ -2111,7 +2111,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockOrder { #[derive(PartialEq,Clone,Default)] pub struct GridBlock { // message fields - pub block_id: ::std::string::String, + pub id: ::std::string::String, pub row_orders: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -2129,30 +2129,30 @@ impl GridBlock { ::std::default::Default::default() } - // string block_id = 1; + // string id = 1; - pub fn get_block_id(&self) -> &str { - &self.block_id + pub fn get_id(&self) -> &str { + &self.id } - pub fn clear_block_id(&mut self) { - self.block_id.clear(); + pub fn clear_id(&mut self) { + self.id.clear(); } // Param is passed by value, moved - pub fn set_block_id(&mut self, v: ::std::string::String) { - self.block_id = v; + pub fn set_id(&mut self, v: ::std::string::String) { + self.id = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_block_id(&mut self) -> &mut ::std::string::String { - &mut self.block_id + pub fn mut_id(&mut self) -> &mut ::std::string::String { + &mut self.id } // Take field - pub fn take_block_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) + pub fn take_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.id, ::std::string::String::new()) } // repeated .RowOrder row_orders = 2; @@ -2196,7 +2196,7 @@ impl ::protobuf::Message for GridBlock { 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.block_id)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; }, 2 => { ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.row_orders)?; @@ -2213,8 +2213,8 @@ impl ::protobuf::Message for GridBlock { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if !self.block_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.block_id); + if !self.id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.id); } for value in &self.row_orders { let len = value.compute_size(); @@ -2226,8 +2226,8 @@ impl ::protobuf::Message for GridBlock { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.block_id.is_empty() { - os.write_string(1, &self.block_id)?; + if !self.id.is_empty() { + os.write_string(1, &self.id)?; } for v in &self.row_orders { os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; @@ -2273,9 +2273,9 @@ impl ::protobuf::Message for GridBlock { descriptor.get(|| { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "block_id", - |m: &GridBlock| { &m.block_id }, - |m: &mut GridBlock| { &mut m.block_id }, + "id", + |m: &GridBlock| { &m.id }, + |m: &mut GridBlock| { &mut m.id }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "row_orders", @@ -2298,7 +2298,7 @@ impl ::protobuf::Message for GridBlock { impl ::protobuf::Clear for GridBlock { fn clear(&mut self) { - self.block_id.clear(); + self.id.clear(); self.row_orders.clear(); self.unknown_fields.clear(); } @@ -4091,24 +4091,24 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\ \x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\ \x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockO\ - rder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"P\n\tGridBloc\ - k\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_order\ - s\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\ - \x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\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\x05valu\ - e\x18\x01\x20\x01(\tR\x05value\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\ - \x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\"d\n\x11QueryField\ - Payload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfie\ - ld_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"\ - e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ - \x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrd\ - erR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ - \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ - kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowIdb\x06proto3\ + rder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBloc\ + k\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ + \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ + \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\ + 2\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\ + RowIdB\x15\n\x13one_of_start_row_id\"d\n\x11QueryFieldPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\ + \x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\ + locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\ + \x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\ + s\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ + ridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x15\n\x06\ + row_id\x18\x03\x20\x01(\tR\x05rowIdb\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 2ce7c429d5..00dee86f6b 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 @@ -44,7 +44,7 @@ message GridBlockOrder { string block_id = 1; } message GridBlock { - string block_id = 1; + string id = 1; repeated RowOrder row_orders = 2; } message Cell { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index 7bfef998c2..768c7bf60a 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -47,20 +47,21 @@ impl GridBlockMetaPad { Self::from_delta(block_delta) } - pub fn add_row( + #[tracing::instrument(level = "trace", skip(self, row), err)] + pub fn add_row_meta( &mut self, row: RowMeta, start_row_id: Option, ) -> CollaborateResult> { self.modify(|rows| { - if let Some(upper_row_id) = start_row_id { - if upper_row_id.is_empty() { + if let Some(start_row_id) = start_row_id { + if start_row_id.is_empty() { rows.insert(0, Arc::new(row)); return Ok(Some(())); } - if let Some(index) = rows.iter().position(|row| row.id == upper_row_id) { - rows.insert(index, Arc::new(row)); + if let Some(index) = rows.iter().position(|row| row.id == start_row_id) { + rows.insert(index + 1, Arc::new(row)); return Ok(Some(())); } } @@ -77,7 +78,7 @@ impl GridBlockMetaPad { }) } - pub fn get_rows(&self, row_ids: Option>) -> CollaborateResult>> { + pub fn get_row_metas(&self, row_ids: Option>) -> CollaborateResult>> { match row_ids { None => Ok(self.row_metas.to_vec()), Some(row_ids) => { @@ -229,7 +230,7 @@ mod tests { visibility: false, }; - let change = pad.add_row(row, None).unwrap().unwrap(); + let change = pad.add_row_meta(row, None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":29},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# @@ -243,19 +244,19 @@ mod tests { let row_2 = test_row_meta("2", &pad); let row_3 = test_row_meta("3", &pad); - let change = pad.add_row(row_1.clone(), None).unwrap().unwrap(); + let change = pad.add_row_meta(row_1.clone(), None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":29},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); - let change = pad.add_row(row_2.clone(), None).unwrap().unwrap(); + let change = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":106},{"insert":",{\"id\":\"2\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); - let change = pad.add_row(row_3.clone(), Some("2".to_string())).unwrap().unwrap(); + let change = pad.add_row_meta(row_3.clone(), Some("2".to_string())).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":114},{"insert":"3\",\"block_id\":\"1\",\"cell_by_field_id\":{},\"height\":0,\"visibility\":false},{\"id\":\""},{"retain":72}]"# @@ -283,9 +284,9 @@ mod tests { let row_2 = test_row_meta("2", &pad); let row_3 = test_row_meta("3", &pad); - let _ = pad.add_row(row_1.clone(), None).unwrap().unwrap(); - let _ = pad.add_row(row_2.clone(), None).unwrap().unwrap(); - let _ = pad.add_row(row_3.clone(), Some("1".to_string())).unwrap().unwrap(); + let _ = pad.add_row_meta(row_1.clone(), None).unwrap().unwrap(); + let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); + let _ = pad.add_row_meta(row_3.clone(), Some("1".to_string())).unwrap().unwrap(); assert_eq!(*pad.row_metas[0], row_3); assert_eq!(*pad.row_metas[1], row_1); @@ -299,9 +300,9 @@ mod tests { let row_2 = test_row_meta("2", &pad); let row_3 = test_row_meta("3", &pad); - let _ = pad.add_row(row_1.clone(), None).unwrap().unwrap(); - let _ = pad.add_row(row_2.clone(), None).unwrap().unwrap(); - let _ = pad.add_row(row_3.clone(), Some("".to_string())).unwrap().unwrap(); + let _ = pad.add_row_meta(row_1.clone(), None).unwrap().unwrap(); + let _ = pad.add_row_meta(row_2.clone(), None).unwrap().unwrap(); + let _ = pad.add_row_meta(row_3.clone(), Some("".to_string())).unwrap().unwrap(); assert_eq!(*pad.row_metas[0], row_3); assert_eq!(*pad.row_metas[1], row_1); @@ -320,7 +321,7 @@ mod tests { visibility: false, }; - let _ = pad.add_row(row.clone(), None).unwrap().unwrap(); + let _ = pad.add_row_meta(row.clone(), None).unwrap().unwrap(); let change = pad.delete_rows(&[row.id]).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), @@ -348,7 +349,7 @@ mod tests { cell_by_field_id: Default::default(), }; - let _ = pad.add_row(row, None).unwrap().unwrap(); + let _ = pad.add_row_meta(row, None).unwrap().unwrap(); let change = pad.update_row(changeset).unwrap().unwrap(); assert_eq!( From 475d5118292520811b6894e50c9f01d958fbbd5d Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 20 Mar 2022 22:38:57 +0800 Subject: [PATCH 02/47] fix: can't find overlay exists above editabletext --- .../home/menu/app/header/header.dart | 1 - .../menu/app/section/disclosure_action.dart | 2 +- .../home/menu/app/section/section.dart | 1 - .../presentation/plugins/doc/document.dart | 1 - .../doc/src/widget/toolbar/color_picker.dart | 9 ----- .../plugins/grid/src/layout/sizes.dart | 14 ++++---- .../grid/src/widgets/footer/grid_footer.dart | 2 +- .../grid/src/widgets/header/header.dart | 14 ++++---- .../grid/src/widgets/header/header_cell.dart | 29 ++++++++++++++-- .../presentation/plugins/trash/trash.dart | 4 +-- .../widgets/float_bubble/question_bubble.dart | 1 - .../presentation/widgets/pop_up_action.dart | 6 ++-- .../presentation/widgets/pop_up_window.dart | 1 + .../lib/src/flowy_overlay/flowy_overlay.dart | 7 ++-- .../lib/src/flowy_overlay/list_overlay.dart | 34 ------------------- .../lib/style_widget/button.dart | 16 ++++++--- 16 files changed, 66 insertions(+), 76 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart index da20eafc7b..b773814f2d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart @@ -81,7 +81,6 @@ class MenuAppHeader extends StatelessWidget { onSecondaryTap: () { final actionList = AppDisclosureActionSheet(onSelected: (action) => _handleAction(context, action)); actionList.show( - context, context, anchorDirection: AnchorDirection.bottomWithCenterAligned, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index a2cd2edcac..cf66476ab8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -32,7 +32,7 @@ class ViewDisclosureButton extends StatelessWidget width: 26, onPressed: () { onTap(); - show(context, context); + show(context); }, icon: svg("editor/details", color: theme.iconColor), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart index ed0a718f58..080211a8b7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart @@ -9,7 +9,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'item.dart'; -import 'package:async/async.dart'; class ViewSection extends StatelessWidget { final AppDataNotifier appData; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart index e8f0290123..83e577ec10 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart @@ -188,7 +188,6 @@ class DocumentShareButton extends StatelessWidget { }); }); actionList.show( - context, context, anchorDirection: AnchorDirection.bottomWithCenterAligned, anchorOffset: offset, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart index 793399989c..57299bd6cc 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/color_picker.dart @@ -117,15 +117,6 @@ class _FlowyColorButtonState extends State { } void _showColorPicker() { - // FlowyPoppuWindow.show( - // context, - // size: Size(600, 200), - // child: MaterialPicker( - // pickerColor: const Color(0x00000000), - // onColorChanged: (color) => _changeColor(context, color), - // ), - // ); - final style = widget.controller.getSelectionStyle(); final values = style.values.where((v) => v.key == Attribute.background.key).map((v) => v.value); int initialColor = 0; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart index 5f8f94e1a2..0daca272b6 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart @@ -8,13 +8,13 @@ class GridSize { static double get footerHeight => 40 * scale; static double get leadingHeaderPadding => 30 * scale; static double get trailHeaderPadding => 140 * scale; - static double get headerContentPadding => 8 * scale; - static double get cellContentPadding => 8 * scale; + static double get headerContainerPadding => 0 * scale; + static double get cellContentPadding => 10 * scale; // static EdgeInsets get headerContentInsets => EdgeInsets.symmetric( - horizontal: GridSize.headerContentPadding, - vertical: GridSize.headerContentPadding, + horizontal: GridSize.headerContainerPadding, + vertical: GridSize.headerContainerPadding, ); static EdgeInsets get cellContentInsets => EdgeInsets.symmetric( horizontal: GridSize.cellContentPadding, @@ -23,8 +23,8 @@ class GridSize { static EdgeInsets get footerContentInsets => EdgeInsets.fromLTRB( 0, - GridSize.headerContentPadding, - GridSize.headerContentPadding, - GridSize.headerContentPadding, + GridSize.headerContainerPadding, + GridSize.headerContainerPadding, + GridSize.headerContainerPadding, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart index 69e27a0fc4..7528c3c00a 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart @@ -39,7 +39,7 @@ class _AddRowButton extends StatelessWidget { text: const FlowyText.medium('New row', fontSize: 12), hoverColor: theme.hover, onTap: () => context.read().add(const GridEvent.createRow()), - icon: svg("home/add"), + leftIcon: svg("home/add"), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index e84640a584..a9fb91bb00 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -61,9 +61,9 @@ class GridHeader extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const LeadingHeaderCell(), + const _HeaderLeading(), ...headers, - const TrailingHeaderCell(), + const _HeaderTrailing(), ], ), ); @@ -73,8 +73,8 @@ class GridHeader extends StatelessWidget { } } -class LeadingHeaderCell extends StatelessWidget { - const LeadingHeaderCell({Key? key}) : super(key: key); +class _HeaderLeading extends StatelessWidget { + const _HeaderLeading({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -84,8 +84,8 @@ class LeadingHeaderCell extends StatelessWidget { } } -class TrailingHeaderCell extends StatelessWidget { - const TrailingHeaderCell({Key? key}) : super(key: key); +class _HeaderTrailing extends StatelessWidget { + const _HeaderTrailing({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -112,7 +112,7 @@ class CreateColumnButton extends StatelessWidget { text: const FlowyText.medium('New column', fontSize: 12), hoverColor: theme.hover, onTap: () => context.read().add(const ColumnEvent.createColumn()), - icon: svg("home/add"), + leftIcon: svg("home/add"), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index aacdcd251e..2f9b0b2fd2 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -1,7 +1,10 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/widgets/pop_up_window.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -14,9 +17,31 @@ class HeaderCell extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(field.name, fontSize: 12)), hoverColor: theme.hover, - onTap: () {}, + onTap: () { + FlowyPoppuWindow.show( + context, + size: Size(300, 100), + child: Container( + color: Colors.red, + child: TextField( + decoration: InputDecoration(hintText: 'Please enter a text'), + onSubmitted: print, + ), + ), + ); + + // StyledDialog( + // child: SingleChildScrollView( + // child: Container( + // color: Colors.red, + // child: TextField(), + // ), + // ), + // ).show(context); + }, + rightIcon: svg("editor/details", color: theme.iconColor), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart index e74289d982..14b12d77bf 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart @@ -146,7 +146,7 @@ class _TrashPageState extends State { size: const Size(102, 30), child: FlowyButton( text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), fontSize: 12), - icon: svg('editor/restore', color: theme.iconColor), + leftIcon: svg('editor/restore', color: theme.iconColor), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.restoreAll()), ), @@ -156,7 +156,7 @@ class _TrashPageState extends State { size: const Size(102, 30), child: FlowyButton( text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), fontSize: 12), - icon: svg('editor/delete', color: theme.iconColor), + leftIcon: svg('editor/delete', color: theme.iconColor), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.deleteAll()), ), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart index 2c28b88660..239918994e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart @@ -112,7 +112,6 @@ class QuestionBubble extends StatelessWidget { }); }); actionList.show( - context, context, anchorDirection: AnchorDirection.topWithRightAligned, anchorOffset: const Offset(0, -10), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart index 61caa84c2f..5c782d3ece 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart @@ -24,8 +24,8 @@ abstract class ActionList { FlowyOverlayDelegate? get delegate; void show( - BuildContext buildContext, - BuildContext anchorContext, { + BuildContext buildContext, { + BuildContext? anchorContext, AnchorDirection anchorDirection = AnchorDirection.bottomRight, Offset? anchorOffset, }) { @@ -47,7 +47,7 @@ abstract class ActionList { identifier: identifier, itemCount: widgets.length, itemBuilder: (context, index) => widgets[index], - anchorContext: anchorContext, + anchorContext: anchorContext ?? buildContext, anchorDirection: anchorDirection, width: maxWidth, height: widgets.length * (itemHeight + ActionListSizes.padding * 2), diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart index bea342747b..bad7eb2da6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart @@ -21,6 +21,7 @@ class FlowyPoppuWindow extends StatelessWidget { required Size size, }) async { final window = await getWindowInfo(); + FlowyOverlay.of(context).insertWithRect( widget: SizedBox.fromSize( size: size, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 84c2cddd82..4732374372 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -279,8 +279,11 @@ class FlowyOverlayState extends State { children.add(child); } - return Stack( - children: children..addAll(overlays), + return MaterialApp( + debugShowCheckedModeBanner: false, + home: Stack( + children: children..addAll(overlays), + ), ); } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart index 862f47b662..b83c454322 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart @@ -103,38 +103,4 @@ class ListOverlay extends StatelessWidget { style: style, ); } - - static void showWithRect( - BuildContext context, { - required BuildContext anchorContext, - required String identifier, - required IndexedWidgetBuilder itemBuilder, - int? itemCount, - ScrollController? controller, - double maxWidth = double.infinity, - double maxHeight = double.infinity, - required Offset anchorPosition, - required Size anchorSize, - AnchorDirection? anchorDirection, - FlowyOverlayDelegate? delegate, - OverlapBehaviour? overlapBehaviour, - FlowyOverlayStyle? style, - }) { - FlowyOverlay.of(context).insertWithRect( - widget: ListOverlay( - itemBuilder: itemBuilder, - itemCount: itemCount, - controller: controller, - width: maxWidth, - height: maxHeight, - ), - identifier: identifier, - anchorPosition: anchorPosition, - anchorSize: anchorSize, - anchorDirection: anchorDirection, - delegate: delegate, - overlapBehaviour: overlapBehaviour, - style: style, - ); - } } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index b7d8ea4e88..dee66a8f11 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -8,14 +8,16 @@ class FlowyButton extends StatelessWidget { final Widget text; final VoidCallback? onTap; final EdgeInsets padding; - final Widget? icon; + final Widget? leftIcon; + final Widget? rightIcon; final Color hoverColor; const FlowyButton({ Key? key, required this.text, this.onTap, this.padding = const EdgeInsets.symmetric(horizontal: 3, vertical: 2), - this.icon, + this.leftIcon, + this.rightIcon, this.hoverColor = Colors.transparent, }) : super(key: key); @@ -33,13 +35,19 @@ class FlowyButton extends StatelessWidget { Widget _render() { List children = List.empty(growable: true); - if (icon != null) { - children.add(SizedBox.fromSize(size: const Size.square(16), child: icon!)); + if (leftIcon != null) { + children.add(SizedBox.fromSize(size: const Size.square(16), child: leftIcon!)); children.add(const HSpace(6)); } children.add(Align(child: text)); + if (rightIcon != null) { + children.add(const Spacer()); + children.add(SizedBox.fromSize(size: const Size.square(16), child: rightIcon!)); + children.add(const HSpace(6)); + } + return Padding( padding: padding, child: Row( From 2bbcfaf3cec3b9aecaa93d718259d20338aaa063 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 21 Mar 2022 23:13:11 +0800 Subject: [PATCH 03/47] chore: config edit pannel --- .../lib/workspace/application/appearance.dart | 1 - .../application/edit_pannel/edit_context.dart | 13 +--------- .../edit_pannel/edit_pannel_bloc.dart | 1 - .../workspace/application/home/home_bloc.dart | 8 +++---- .../presentation/home/home_layout.dart | 2 +- .../presentation/home/home_screen.dart | 21 +++++++++++----- .../grid/src/widgets/header/field_editor.dart | 1 + .../grid/src/widgets/header/header_cell.dart | 24 ++++++++++++------- .../widgets/edit_pannel/edit_pannel.dart | 13 ++++------ .../presentation/widgets/pop_up_window.dart | 1 - .../lib/src/flowy_overlay/flowy_overlay.dart | 11 +++++++++ 11 files changed, 54 insertions(+), 42 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index ffd7e18c92..06473729a8 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -7,7 +7,6 @@ import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:async/async.dart'; class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { AppearanceSettings setting; diff --git a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart index cd52bc7f11..571461b365 100644 --- a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart +++ b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_context.dart @@ -5,19 +5,8 @@ abstract class EditPannelContext extends Equatable { final String identifier; final String title; final Widget child; - const EditPannelContext( - {required this.child, required this.identifier, required this.title}); + const EditPannelContext({required this.child, required this.identifier, required this.title}); @override List get props => [identifier]; } - -class BlankEditPannelContext extends EditPannelContext { - const BlankEditPannelContext() - : super(child: const Text('Blank'), identifier: '1', title: ''); -} - -class CellEditPannelContext extends EditPannelContext { - const CellEditPannelContext() - : super(child: const Text('shit'), identifier: 'test', title: 'test'); -} diff --git a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart index 0ae2e8326a..e1f2f5835d 100644 --- a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart @@ -1,7 +1,6 @@ import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; import 'package:dartz/dartz.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -// ignore: import_of_legacy_library_into_null_safe import 'package:flutter_bloc/flutter_bloc.dart'; part 'edit_pannel_bloc.freezed.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart index e4b0482989..5ed7ce959d 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart @@ -12,10 +12,10 @@ class HomeBloc extends Bloc { emit(state.copyWith(isLoading: e.isLoading)); }, setEditPannel: (e) async { - emit(state.copyWith(editContext: some(e.editContext))); + emit(state.copyWith(pannelContext: some(e.editContext))); }, dismissEditPannel: (value) async { - emit(state.copyWith(editContext: none())); + emit(state.copyWith(pannelContext: none())); }, forceCollapse: (e) async { emit(state.copyWith(forceCollapse: e.forceCollapse)); @@ -43,12 +43,12 @@ class HomeState with _$HomeState { const factory HomeState({ required bool isLoading, required bool forceCollapse, - required Option editContext, + required Option pannelContext, }) = _HomeState; factory HomeState.initial() => HomeState( isLoading: false, forceCollapse: false, - editContext: none(), + pannelContext: none(), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_layout.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_layout.dart index f0192a846b..0405279851 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_layout.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_layout.dart @@ -20,7 +20,7 @@ class HomeLayout { HomeLayout(BuildContext context, BoxConstraints homeScreenConstraint, bool forceCollapse) { final homeBlocState = context.read().state; - showEditPannel = homeBlocState.editContext.isSome(); + showEditPannel = homeBlocState.pannelContext.isSome(); menuWidth = Sizes.sideBarMed; if (context.widthPx >= PageBreaks.desktop) { diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index 88ec0f5ad6..e9bb80dd30 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -126,13 +126,22 @@ class _HomeScreenState extends State { Widget _buildEditPannel({required HomeState homeState, required BuildContext context, required HomeLayout layout}) { final homeBloc = context.read(); - Widget editPannel = EditPannel( - context: homeState.editContext, - onEndEdit: () => homeBloc.add(const HomeEvent.dismissEditPannel()), + return BlocBuilder( + buildWhen: (previous, current) => previous.pannelContext != current.pannelContext, + builder: (context, state) { + return state.pannelContext.fold( + () => const SizedBox(), + (pannelContext) => FocusTraversalGroup( + child: RepaintBoundary( + child: EditPannel( + pannelContext: pannelContext, + onEndEdit: () => homeBloc.add(const HomeEvent.dismissEditPannel()), + ), + ), + ), + ); + }, ); - // editPannel = RepaintBoundary(child: editPannel); - // editPannel = FocusTraversalGroup(child: editPannel); - return editPannel; } Widget _layoutWidgets({ diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -0,0 +1 @@ + diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index 2f9b0b2fd2..4e870ae27d 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -4,7 +4,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -23,13 +22,7 @@ class HeaderCell extends StatelessWidget { FlowyPoppuWindow.show( context, size: Size(300, 100), - child: Container( - color: Colors.red, - child: TextField( - decoration: InputDecoration(hintText: 'Please enter a text'), - onSubmitted: print, - ), - ), + child: CusTextField(), ); // StyledDialog( @@ -46,6 +39,21 @@ class HeaderCell extends StatelessWidget { } } +class CusTextField extends StatelessWidget { + const CusTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Container( + color: theme.bg3, + child: TextField( + decoration: InputDecoration(hintText: 'Please enter a text'), + onSubmitted: print, + )); + } +} + class HeaderCellContainer extends StatelessWidget { final HeaderCell child; final double width; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart index b892a8e49d..f9e5e0e6b5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart @@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dar import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; -import 'package:dartz/dartz.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/bar_title.dart'; import 'package:flowy_infra_ui/style_widget/close_button.dart'; @@ -11,15 +10,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; class EditPannel extends StatelessWidget { - late final EditPannelContext editContext; + final EditPannelContext pannelContext; final VoidCallback onEndEdit; - EditPannel({ + const EditPannel({ Key? key, - required Option context, + required this.pannelContext, required this.onEndEdit, - }) : super(key: key) { - editContext = context.fold(() => const BlankEditPannelContext(), (c) => c); - } + }) : super(key: key); @override Widget build(BuildContext context) { @@ -34,7 +31,7 @@ class EditPannel extends StatelessWidget { children: [ EditPannelTopBar(onClose: () => onEndEdit()), Expanded( - child: editContext.child, + child: pannelContext.child, ), ], ); diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart index bad7eb2da6..bea342747b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart @@ -21,7 +21,6 @@ class FlowyPoppuWindow extends StatelessWidget { required Size size, }) async { final window = await getWindowInfo(); - FlowyOverlay.of(context).insertWithRect( widget: SizedBox.fromSize( size: size, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 4732374372..11ec524ed4 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -279,6 +279,17 @@ class FlowyOverlayState extends State { children.add(child); } + // Try to fix there is no overlay for editabletext widget. e.g. TextField. + // // Check out the TextSelectionOverlay class in text_selection.dart. + // // ... + // // final OverlayState? overlay = Overlay.of(context, rootOverlay: true); + // // assert( + // // overlay != null, + // // 'No Overlay widget exists above $context.\n' + // // 'Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your ' + // // 'app content was created above the Navigator with the WidgetsApp builder parameter.', + // // ); + // // ... return MaterialApp( debugShowCheckedModeBanner: false, home: Stack( From 188302d4ba5eda194dac82b1aa4bd623f07a6eb0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 22 Mar 2022 20:51:15 +0800 Subject: [PATCH 04/47] chore: config field editor --- .../app_flowy/assets/images/grid/delete.svg | 6 + .../assets/images/grid/duplicate.svg | 4 + .../app_flowy/assets/images/grid/hide.svg | 4 + .../app_flowy/assets/images/grid/left.svg | 5 + .../app_flowy/assets/images/grid/right.svg | 5 + .../app_flowy/assets/translations/en.json | 9 + .../lib/startup/home_deps_resolver.dart | 15 +- .../lib/user/presentation/sign_in_screen.dart | 4 +- .../lib/user/presentation/sign_up_screen.dart | 6 +- .../grid/cell_bloc/cell_service.dart | 2 +- .../application/grid/column_bloc.dart | 42 ---- .../application/grid/column_service.dart | 1 - .../grid/field/field_edit_bloc.dart | 58 +++++ .../application/grid/field/field_service.dart | 1 + .../grid/field/grid_header_bloc.dart | 42 ++++ .../workspace/application/grid/prelude.dart | 9 +- .../application/grid/{ => row}/row_bloc.dart | 2 +- .../grid/{ => row}/row_listener.dart | 0 .../grid/{ => row}/row_service.dart | 2 +- .../plugins/grid/src/layout/sizes.dart | 5 + .../src/widgets/content/cell_builder.dart | 2 +- .../src/widgets/content/checkbox_cell.dart | 3 +- .../grid/src/widgets/content/date_cell.dart | 3 +- .../grid/src/widgets/content/number_cell.dart | 3 +- .../grid/src/widgets/content/text_cell.dart | 4 +- .../grid/src/widgets/header/field_editor.dart | 207 ++++++++++++++++++ .../grid/src/widgets/header/header.dart | 8 +- .../grid/src/widgets/header/header_cell.dart | 41 +--- .../presentation/widgets/pop_up_window.dart | 5 +- .../lib/src/flowy_overlay/flowy_overlay.dart | 2 + .../lib/src/flowy_overlay/list_overlay.dart | 39 ++-- .../src/flowy_overlay/overlay_container.dart | 30 +++ .../lib/style_widget/hover.dart | 17 +- .../lib/widget/rounded_input_field.dart | 109 +++++---- .../lib/widget/text_field_container.dart | 40 ---- frontend/app_flowy/pubspec.yaml | 1 + 36 files changed, 504 insertions(+), 232 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/delete.svg create mode 100644 frontend/app_flowy/assets/images/grid/duplicate.svg create mode 100644 frontend/app_flowy/assets/images/grid/hide.svg create mode 100644 frontend/app_flowy/assets/images/grid/left.svg create mode 100644 frontend/app_flowy/assets/images/grid/right.svg delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/column_bloc.dart delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/column_service.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart rename frontend/app_flowy/lib/workspace/application/grid/{ => row}/row_bloc.dart (97%) rename frontend/app_flowy/lib/workspace/application/grid/{ => row}/row_listener.dart (100%) rename frontend/app_flowy/lib/workspace/application/grid/{ => row}/row_service.dart (93%) create mode 100644 frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart delete mode 100644 frontend/app_flowy/packages/flowy_infra_ui/lib/widget/text_field_container.dart diff --git a/frontend/app_flowy/assets/images/grid/delete.svg b/frontend/app_flowy/assets/images/grid/delete.svg new file mode 100644 index 0000000000..fcfbf2f6dd --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/delete.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/app_flowy/assets/images/grid/duplicate.svg b/frontend/app_flowy/assets/images/grid/duplicate.svg new file mode 100644 index 0000000000..f11048fd2f --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/duplicate.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/hide.svg b/frontend/app_flowy/assets/images/grid/hide.svg new file mode 100644 index 0000000000..dfb6dbb90c --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/hide.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/left.svg b/frontend/app_flowy/assets/images/grid/left.svg new file mode 100644 index 0000000000..0f771a3858 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/left.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/app_flowy/assets/images/grid/right.svg b/frontend/app_flowy/assets/images/grid/right.svg new file mode 100644 index 0000000000..7d738f4e69 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/right.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 7717e71229..27574db94e 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -141,5 +141,14 @@ "lightLabel": "Light Mode", "darkLabel": "Dark Mode" } + }, + "grid": { + "field": { + "hide": "Hide", + "insertLeft": "Insert Left", + "insertRight": "Insert Right", + "duplicate": "Duplicate", + "delete": "Delete" + } } } diff --git a/frontend/app_flowy/lib/startup/home_deps_resolver.dart b/frontend/app_flowy/lib/startup/home_deps_resolver.dart index 2dcf6ca077..688c53ad2a 100644 --- a/frontend/app_flowy/lib/startup/home_deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/home_deps_resolver.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/user/application/user_service.dart'; import 'package:app_flowy/workspace/application/app/prelude.dart'; import 'package:app_flowy/workspace/application/doc/prelude.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/application/grid/row_listener.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_listener.dart'; import 'package:app_flowy/workspace/application/trash/prelude.dart'; import 'package:app_flowy/workspace/application/workspace/prelude.dart'; import 'package:app_flowy/workspace/application/view/prelude.dart'; @@ -101,10 +101,17 @@ class HomeDepsResolver { ), ); - getIt.registerFactoryParam, void>( - (data, _) => ColumnBloc( + getIt.registerFactoryParam, void>( + (data, _) => GridHeaderBloc( data: GridColumnData(fields: data), - service: ColumnService(), + service: FieldService(), + ), + ); + + getIt.registerFactoryParam( + (field, _) => FieldEditBloc( + field: field, + service: FieldService(), ), ); diff --git a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart index f7afa0b4d3..8124241cf4 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart @@ -174,7 +174,7 @@ class PasswordTextField extends StatelessWidget { obscureHideIcon: svg("home/show"), hintText: LocaleKeys.signIn_passwordHint.tr(), normalBorderColor: theme.shader4, - highlightBorderColor: theme.red, + errorBorderColor: theme.red, cursorColor: theme.main1, errorText: context.read().state.passwordError.fold(() => "", (error) => error), onChanged: (value) => context.read().add(SignInEvent.passwordChanged(value)), @@ -199,7 +199,7 @@ class EmailTextField extends StatelessWidget { hintText: LocaleKeys.signIn_emailHint.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), normalBorderColor: theme.shader4, - highlightBorderColor: theme.red, + errorBorderColor: theme.red, cursorColor: theme.main1, errorText: context.read().state.emailError.fold(() => "", (error) => error), onChanged: (value) => context.read().add(SignInEvent.emailChanged(value)), diff --git a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart index 931ccff516..06d4db6da2 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart @@ -139,7 +139,7 @@ class PasswordTextField extends StatelessWidget { style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), hintText: LocaleKeys.signUp_passwordHint.tr(), normalBorderColor: theme.shader4, - highlightBorderColor: theme.red, + errorBorderColor: theme.red, cursorColor: theme.main1, errorText: context.read().state.passwordError.fold(() => "", (error) => error), onChanged: (value) => context.read().add(SignUpEvent.passwordChanged(value)), @@ -167,7 +167,7 @@ class RepeatPasswordTextField extends StatelessWidget { style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), hintText: LocaleKeys.signUp_repeatPasswordHint.tr(), normalBorderColor: theme.shader4, - highlightBorderColor: theme.red, + errorBorderColor: theme.red, cursorColor: theme.main1, errorText: context.read().state.repeatPasswordError.fold(() => "", (error) => error), onChanged: (value) => context.read().add(SignUpEvent.repeatPasswordChanged(value)), @@ -192,7 +192,7 @@ class EmailTextField extends StatelessWidget { hintText: LocaleKeys.signUp_emailHint.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), normalBorderColor: theme.shader4, - highlightBorderColor: theme.red, + errorBorderColor: theme.red, cursorColor: theme.main1, errorText: context.read().state.emailError.fold(() => "", (error) => error), onChanged: (value) => context.read().add(SignUpEvent.emailChanged(value)), diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index 44cf86e5d2..79b4d2cf52 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/column_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/column_bloc.dart deleted file mode 100644 index 39badc922a..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/column_bloc.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; -import 'column_service.dart'; -import 'data.dart'; - -part 'column_bloc.freezed.dart'; - -class ColumnBloc extends Bloc { - final ColumnService service; - final GridColumnData data; - - ColumnBloc({required this.data, required this.service}) : super(ColumnState.initial(data.fields)) { - on( - (event, emit) async { - await event.map( - initial: (_InitialColumn value) async {}, - createColumn: (_CreateColumn value) {}, - ); - }, - ); - } - - @override - Future close() async { - return super.close(); - } -} - -@freezed -abstract class ColumnEvent with _$ColumnEvent { - const factory ColumnEvent.initial() = _InitialColumn; - const factory ColumnEvent.createColumn() = _CreateColumn; -} - -@freezed -abstract class ColumnState with _$ColumnState { - const factory ColumnState({required List fields}) = _ColumnState; - - factory ColumnState.initial(List fields) => ColumnState(fields: fields); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/column_service.dart b/frontend/app_flowy/lib/workspace/application/grid/column_service.dart deleted file mode 100644 index c074dcf616..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/column_service.dart +++ /dev/null @@ -1 +0,0 @@ -class ColumnService {} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart new file mode 100644 index 0000000000..2d4aea16da --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart @@ -0,0 +1,58 @@ +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; + +part 'field_edit_bloc.freezed.dart'; + +class FieldEditBloc extends Bloc { + final FieldService service; + + FieldEditBloc({required Field field, required this.service}) : super(FieldEditState.initial(field)) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) {}, + createField: (_CreateField value) {}, + updateFieldName: (_UpdateFieldName value) { + // + }, + hideField: (_HideField value) {}, + deleteField: (_DeleteField value) {}, + insertField: (_InsertField value) {}, + duplicateField: (_DuplicateField value) {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class FieldEditEvent with _$FieldEditEvent { + const factory FieldEditEvent.initial() = _InitialField; + const factory FieldEditEvent.createField() = _CreateField; + const factory FieldEditEvent.updateFieldName(String name) = _UpdateFieldName; + const factory FieldEditEvent.hideField() = _HideField; + const factory FieldEditEvent.duplicateField() = _DuplicateField; + const factory FieldEditEvent.insertField({required bool onLeft}) = _InsertField; + const factory FieldEditEvent.deleteField() = _DeleteField; +} + +@freezed +class FieldEditState with _$FieldEditState { + const factory FieldEditState({ + required Field field, + required String errorText, + }) = _FieldEditState; + + factory FieldEditState.initial(Field field) => FieldEditState( + field: field, + errorText: '', + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart new file mode 100644 index 0000000000..48d4aa21bd --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -0,0 +1 @@ +class FieldService {} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart new file mode 100644 index 0000000000..fd22d7a505 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -0,0 +1,42 @@ +import 'package:app_flowy/workspace/application/grid/data.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; + +part 'grid_header_bloc.freezed.dart'; + +class GridHeaderBloc extends Bloc { + final FieldService service; + final GridColumnData data; + + GridHeaderBloc({required this.data, required this.service}) : super(GridHeaderState.initial(data.fields)) { + on( + (event, emit) async { + await event.map( + initial: (_InitialHeader value) async {}, + createField: (_CreateField value) {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class GridHeaderEvent with _$GridHeaderEvent { + const factory GridHeaderEvent.initial() = _InitialHeader; + const factory GridHeaderEvent.createField() = _CreateField; +} + +@freezed +class GridHeaderState with _$GridHeaderState { + const factory GridHeaderState({required List fields}) = _GridHeaderState; + + factory GridHeaderState.initial(List fields) => GridHeaderState(fields: fields); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index d28df04c62..3190ced75d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -1,10 +1,11 @@ export 'grid_bloc.dart'; -export 'row_bloc.dart'; -export 'row_service.dart'; +export 'row/row_bloc.dart'; +export 'row/row_service.dart'; export 'grid_service.dart'; export 'data.dart'; -export 'column_service.dart'; -export 'column_bloc.dart'; +export 'field/field_service.dart'; +export 'field/grid_header_bloc.dart'; +export 'field/field_edit_bloc.dart'; export 'cell_bloc/text_cell_bloc.dart'; export 'cell_bloc/number_cell_bloc.dart'; export 'cell_bloc/selection_cell_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart similarity index 97% rename from frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 67fcc5cbc2..a30bea39ee 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -1,9 +1,9 @@ +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'grid_service.dart'; import 'row_listener.dart'; import 'row_service.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/application/grid/row_listener.dart rename to frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/application/grid/row_service.dart rename to frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 013ae3fb1c..6819a9a40e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -3,7 +3,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'grid_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; class RowService { final GridRowData rowData; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart index 0daca272b6..e94507ab52 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart @@ -21,6 +21,11 @@ class GridSize { vertical: GridSize.cellContentPadding, ); + static EdgeInsets get fieldContentInsets => EdgeInsets.symmetric( + horizontal: GridSize.cellContentPadding, + vertical: GridSize.cellContentPadding, + ); + static EdgeInsets get footerContentInsets => EdgeInsets.fromLTRB( 0, GridSize.headerContainerPadding, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart index 187a81c1bc..7aa412589e 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart index eec381914a..2f067ab1fa 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart index 5d9f452c78..5d69783fc5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/cell_bloc/date_cell_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart index ea3f70fed3..0402b85b12 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/cell_bloc/number_cell_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart index 937c5d84ab..d3a9e88c2e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart @@ -1,8 +1,6 @@ import 'dart:async'; - import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/cell_bloc/text_cell_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/row_service.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index 8b13789179..531d83a1f3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -1 +1,208 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +class FieldEditor extends StatelessWidget { + final Field field; + const FieldEditor({required this.field, Key? key}) : super(key: key); + + static void show(BuildContext context, Field field) { + final editor = FieldEditor(field: field); + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer(child: editor), + identifier: editor.identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomWithLeftAligned, + style: FlowyOverlayStyle(blur: false), + ); + } + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocProvider( + create: (context) => getIt(param1: field)..add(const FieldEditEvent.initial()), + child: Container( + color: theme.surface, + constraints: BoxConstraints.loose(const Size(300, 200)), + child: SingleChildScrollView( + child: Column(children: [ + const FieldNameTextField(), + // FieldTypeSwitcher(), + const VSpace(10), + FieldOperationList( + onTap: () { + FlowyOverlay.of(context).remove(identifier()); + }, + ), + ]), + ), + ), + ); + } + + String identifier() { + return toString(); + } +} + +class FieldNameTextField extends StatelessWidget { + const FieldNameTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocBuilder( + buildWhen: ((previous, current) => previous.field.name == current.field.name), + builder: (context, state) { + return RoundedInputField( + height: 36, + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + initialValue: state.field.name, + normalBorderColor: theme.shader4, + errorBorderColor: theme.red, + focusBorderColor: theme.main1, + cursorColor: theme.main1, + errorText: state.errorText, + onChanged: (value) { + context.read().add(FieldEditEvent.updateFieldName(value)); + }, + ); + }, + ); + } +} + +class FieldTypeSwitcher extends StatelessWidget { + const FieldTypeSwitcher({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return FlowyButton( + text: FlowyText.medium(context.read().state.field.name, fontSize: 12), + hoverColor: theme.hover, + onTap: () {}, + leftIcon: svg("editor/details", color: theme.iconColor), + ); + } +} + +class FieldOperationList extends StatelessWidget { + final VoidCallback onTap; + const FieldOperationList({required this.onTap, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final children = FieldAction.values + .map((action) => FieldActionItem( + action: action, + onTap: onTap, + )) + .toList(); + return GridView( + // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html + shrinkWrap: true, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 4.0, + mainAxisSpacing: 8, + ), + children: children, + ); + } +} + +class FieldActionItem extends StatelessWidget { + final VoidCallback onTap; + final FieldAction action; + const FieldActionItem({required this.action, required this.onTap, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyButton( + text: FlowyText.medium(action.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + action.run(context); + onTap(); + }, + leftIcon: svg(action.iconName(), color: theme.iconColor), + ); + } +} + +enum FieldAction { + hide, + insertLeft, + duplicate, + insertRight, + delete, +} + +extension _FieldActionExtension on FieldAction { + String iconName() { + switch (this) { + case FieldAction.hide: + return 'grid/hide'; + case FieldAction.insertLeft: + return 'grid/left'; + case FieldAction.insertRight: + return 'grid/right'; + case FieldAction.duplicate: + return 'grid/duplicate'; + case FieldAction.delete: + return 'grid/delete'; + } + } + + String title() { + switch (this) { + case FieldAction.hide: + return LocaleKeys.grid_field_hide.tr(); + case FieldAction.insertLeft: + return LocaleKeys.grid_field_insertLeft.tr(); + case FieldAction.insertRight: + return LocaleKeys.grid_field_insertRight.tr(); + case FieldAction.duplicate: + return LocaleKeys.grid_field_duplicate.tr(); + case FieldAction.delete: + return LocaleKeys.grid_field_delete.tr(); + } + } + + void run(BuildContext context) { + final bloc = context.read(); + + switch (this) { + case FieldAction.hide: + bloc.add(const FieldEditEvent.hideField()); + break; + case FieldAction.insertLeft: + bloc.add(const FieldEditEvent.insertField(onLeft: true)); + break; + case FieldAction.insertRight: + bloc.add(const FieldEditEvent.insertField(onLeft: false)); + break; + case FieldAction.duplicate: + bloc.add(const FieldEditEvent.duplicateField()); + break; + case FieldAction.delete: + bloc.add(const FieldEditEvent.deleteField()); + break; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index a9fb91bb00..40f6a3e3b0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/column_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -44,8 +44,8 @@ class GridHeader extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return BlocProvider( - create: (context) => getIt(param1: fields)..add(const ColumnEvent.initial()), - child: BlocBuilder( + create: (context) => getIt(param1: fields)..add(const GridHeaderEvent.initial()), + child: BlocBuilder( builder: (context, state) { final headers = state.fields .map( @@ -111,7 +111,7 @@ class CreateColumnButton extends StatelessWidget { return FlowyButton( text: const FlowyText.medium('New column', fontSize: 12), hoverColor: theme.hover, - onTap: () => context.read().add(const ColumnEvent.createColumn()), + onTap: () => context.read().add(const GridHeaderEvent.createField()), leftIcon: svg("home/add"), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index 4e870ae27d..fa8a3692c5 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/widgets/pop_up_window.dart'; + import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -8,6 +8,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'field_editor.dart'; + class HeaderCell extends StatelessWidget { final Field field; const HeaderCell(this.field, {Key? key}) : super(key: key); @@ -16,44 +18,17 @@ class HeaderCell extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return FlowyButton( - text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(field.name, fontSize: 12)), + text: Padding( + padding: GridSize.cellContentInsets, + child: FlowyText.medium(field.name, fontSize: 12), + ), hoverColor: theme.hover, - onTap: () { - FlowyPoppuWindow.show( - context, - size: Size(300, 100), - child: CusTextField(), - ); - - // StyledDialog( - // child: SingleChildScrollView( - // child: Container( - // color: Colors.red, - // child: TextField(), - // ), - // ), - // ).show(context); - }, + onTap: () => FieldEditor.show(context, field), rightIcon: svg("editor/details", color: theme.iconColor), ); } } -class CusTextField extends StatelessWidget { - const CusTextField({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return Container( - color: theme.bg3, - child: TextField( - decoration: InputDecoration(hintText: 'Please enter a text'), - onSubmitted: print, - )); - } -} - class HeaderCellContainer extends StatelessWidget { final HeaderCell child; final double width; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart index bea342747b..1803257672 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_window.dart @@ -22,10 +22,7 @@ class FlowyPoppuWindow extends StatelessWidget { }) async { final window = await getWindowInfo(); FlowyOverlay.of(context).insertWithRect( - widget: SizedBox.fromSize( - size: size, - child: FlowyPoppuWindow(child: child), - ), + widget: FlowyPoppuWindow(child: child), identifier: 'FlowyPoppuWindow', anchorPosition: Offset(-size.width / 2.0, -size.height / 2.0), anchorSize: window.frame.size, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 11ec524ed4..26760dc411 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -5,6 +5,8 @@ import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart'; import 'package:flutter/material.dart'; import 'dart:ui'; +export './overlay_container.dart'; + /// Specifies how overlay are anchored to the SourceWidget enum AnchorDirection { // Corner aligned with a corner of the SourceWidget diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart index b83c454322..6c0a4019d1 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart @@ -35,36 +35,29 @@ class ListOverlay extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = context.watch(); const padding = EdgeInsets.symmetric(horizontal: 6, vertical: 6); double totalHeight = height + padding.vertical; if (footer != null) { totalHeight = totalHeight + footer!.height + footer!.padding.vertical; } - return Material( - type: MaterialType.transparency, - child: Container( - decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.1)), - constraints: BoxConstraints.tight(Size(width, totalHeight)), - child: Padding( - padding: padding, - child: Column( - children: [ - ListView.builder( - shrinkWrap: true, - itemBuilder: itemBuilder, - itemCount: itemCount, - controller: controller, - ), - if (footer != null) - Padding( - padding: footer!.padding, - child: footer!.widget, - ), - ], + return OverlayContainer( + constraints: BoxConstraints.tight(Size(width, totalHeight)), + padding: padding, + child: Column( + children: [ + ListView.builder( + shrinkWrap: true, + itemBuilder: itemBuilder, + itemCount: itemCount, + controller: controller, ), - ), + if (footer != null) + Padding( + padding: footer!.padding, + child: footer!.widget, + ), + ], ), ); } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart new file mode 100644 index 0000000000..bee123d248 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart @@ -0,0 +1,30 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/decoration.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class OverlayContainer extends StatelessWidget { + final Widget child; + final BoxConstraints? constraints; + final EdgeInsets padding; + const OverlayContainer({ + required this.child, + this.constraints, + this.padding = const EdgeInsets.all(12), + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Material( + type: MaterialType.transparency, + child: Container( + padding: padding, + decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.1)), + constraints: constraints, + child: child, + ), + ); + } +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart index a85867e456..b19578fe54 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flowy_infra/time/duration.dart'; typedef HoverBuilder = Widget Function(BuildContext context, bool onHover); - typedef IsOnSelected = bool Function(); class FlowyHover extends StatefulWidget { @@ -29,23 +28,20 @@ class _FlowyHoverState extends State { Widget build(BuildContext context) { return MouseRegion( cursor: SystemMouseCursors.click, - onEnter: (p) => setOnHover(true), - onExit: (p) => setOnHover(false), + onEnter: (p) => setState(() => _onHover = true), + onExit: (p) => setState(() => _onHover = false), child: render(), ); } - void setOnHover(bool value) => setState(() => _onHover = value); - Widget render() { var showHover = _onHover; - - if (showHover == false && widget.isOnSelected != null) { + if (!showHover && widget.isOnSelected != null) { showHover = widget.isOnSelected!(); } if (showHover) { - return FlowyHoverBackground( + return FlowyHoverContainer( config: widget.config, child: widget.builder(context, _onHover), ); @@ -68,12 +64,11 @@ class HoverDisplayConfig { required this.hoverColor}); } -class FlowyHoverBackground extends StatelessWidget { +class FlowyHoverContainer extends StatelessWidget { final HoverDisplayConfig config; - final Widget child; - const FlowyHoverBackground({ + const FlowyHoverContainer({ Key? key, required this.child, required this.config, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart index e6e9684854..0cd2265cce 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart @@ -1,85 +1,105 @@ import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; -import 'package:flowy_infra_ui/widget/text_field_container.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra/time/duration.dart'; -// ignore: must_be_immutable class RoundedInputField extends StatefulWidget { final String? hintText; - final IconData? icon; final bool obscureText; final Widget? obscureIcon; final Widget? obscureHideIcon; final Color normalBorderColor; - final Color highlightBorderColor; + final Color errorBorderColor; final Color cursorColor; + final Color? focusBorderColor; final String errorText; final TextStyle style; final ValueChanged? onChanged; final String? initialValue; - late bool enableObscure; - var _text = ""; + final EdgeInsets margin; + final EdgeInsets padding; + final EdgeInsets contentPadding; + final double height; - RoundedInputField({ + const RoundedInputField({ Key? key, this.hintText, this.errorText = "", this.initialValue, - this.icon, this.obscureText = false, this.obscureIcon, this.obscureHideIcon, this.onChanged, this.normalBorderColor = Colors.transparent, - this.highlightBorderColor = Colors.transparent, + this.errorBorderColor = Colors.transparent, + this.focusBorderColor, this.cursorColor = Colors.black, this.style = const TextStyle(fontSize: 20, fontWeight: FontWeight.w500), - }) : super(key: key) { - enableObscure = obscureText; - } + this.margin = EdgeInsets.zero, + this.padding = EdgeInsets.zero, + this.contentPadding = const EdgeInsets.symmetric(horizontal: 10), + this.height = 48, + }) : super(key: key); @override State createState() => _RoundedInputFieldState(); } class _RoundedInputFieldState extends State { + String inputText = ""; + bool obscuteText = false; + + @override + void initState() { + obscuteText = widget.obscureText; + super.initState(); + } + @override Widget build(BuildContext context) { - final Icon? newIcon = widget.icon == null - ? null - : Icon( - widget.icon!, - color: const Color(0xFF6F35A5), - ); - var borderColor = widget.normalBorderColor; + var focusBorderColor = widget.focusBorderColor ?? borderColor; + if (widget.errorText.isNotEmpty) { - borderColor = widget.highlightBorderColor; + borderColor = widget.errorBorderColor; + focusBorderColor = borderColor; } List children = [ - TextFieldContainer( - height: 48, - borderRadius: Corners.s10Border, - borderColor: borderColor, + Container( + margin: widget.margin, + padding: widget.padding, + height: widget.height, child: TextFormField( initialValue: widget.initialValue, onChanged: (value) { - widget._text = value; + inputText = value; if (widget.onChanged != null) { widget.onChanged!(value); } setState(() {}); }, cursorColor: widget.cursorColor, - obscureText: widget.enableObscure, + obscureText: obscuteText, decoration: InputDecoration( - icon: newIcon, + contentPadding: widget.contentPadding, hintText: widget.hintText, hintStyle: TextStyle(color: widget.normalBorderColor), - border: InputBorder.none, - suffixIcon: suffixIcon(), + border: OutlineInputBorder( + borderSide: BorderSide( + color: borderColor, + width: 1.0, + ), + borderRadius: Corners.s10Border, + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: focusBorderColor, + width: 1.0, + ), + borderRadius: Corners.s10Border, + ), + suffixIcon: obscureIcon(), ), ), ), @@ -100,39 +120,32 @@ class _RoundedInputFieldState extends State { return AnimatedSize( duration: .4.seconds, curve: Curves.easeInOut, - child: Column( - children: children, - ), + child: Column(children: children), ); } - Widget? suffixIcon() { + Widget? obscureIcon() { if (widget.obscureText == false) { return null; } - if (widget._text.isEmpty) { - return SizedBox.fromSize(size: const Size.square(16)); + const double iconWidth = 16; + if (inputText.isEmpty) { + return SizedBox.fromSize(size: const Size.square(iconWidth)); } + assert(widget.obscureIcon != null && widget.obscureHideIcon != null); Widget? icon; - if (widget.obscureText == true) { - assert(widget.obscureIcon != null && widget.obscureHideIcon != null); - if (widget.enableObscure) { - icon = widget.obscureIcon!; - } else { - icon = widget.obscureHideIcon!; - } - } - - if (icon == null) { - return null; + if (obscuteText) { + icon = widget.obscureIcon!; + } else { + icon = widget.obscureHideIcon!; } return RoundedImageButton( - size: 16, + size: iconWidth, press: () { - widget.enableObscure = !widget.enableObscure; + obscuteText = !obscuteText; setState(() {}); }, child: icon, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/text_field_container.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/text_field_container.dart deleted file mode 100644 index 7c1bf131a1..0000000000 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/text_field_container.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -class TextFieldContainer extends StatelessWidget { - final Widget child; - final BorderRadius borderRadius; - final Color borderColor; - final double? height; - final double? width; - const TextFieldContainer({ - Key? key, - required this.child, - this.borderRadius = BorderRadius.zero, - this.borderColor = Colors.white, - this.height, - this.width, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.symmetric(vertical: 10), - padding: const EdgeInsets.symmetric(horizontal: 15), - height: height, - width: width, - decoration: BoxDecoration( - border: Border.all(color: borderColor), - color: Colors.white, - borderRadius: borderRadius, - ), - child: Align(alignment: Alignment.center, child: child), - ); - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('child', child)); - } -} diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index 41ee902083..61b69b45f1 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -111,6 +111,7 @@ flutter: - assets/images/ - assets/images/home/ - assets/images/editor/ + - assets/images/grid/ - assets/translations/ # - images/a_dot_ham.jpeg From 694963a47de1ea1cfc77cd4302524d7aaa828268 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 23 Mar 2022 22:10:31 +0800 Subject: [PATCH 05/47] chore: add update field and create field handler --- .../lib/startup/home_deps_resolver.dart | 6 +- .../workspace/application/app/app_bloc.dart | 2 +- .../application/app/app_listener.dart | 2 +- .../grid/field/grid_header_bloc.dart | 6 +- .../workspace/application/grid/grid_bloc.dart | 66 +++- .../application/grid/grid_block_service.dart | 49 +-- .../application/grid/grid_listenr.dart | 49 ++- .../application/trash/trash_bloc.dart | 2 +- .../application/trash/trash_listener.dart | 2 +- .../plugins/grid/src/grid_page.dart | 34 +- .../grid/src/widgets/header/header.dart | 49 +-- .../grid/src/widgets/header/header_cell.dart | 27 +- .../dart_event/flowy-grid/dart_event.dart | 34 ++ .../flowy-error-code/code.pbenum.dart | 14 +- .../flowy-error-code/code.pbjson.dart | 12 +- .../flowy-grid-data-model/grid.pb.dart | 104 +++++ .../flowy-grid-data-model/grid.pbjson.dart | 16 + .../flowy-grid-data-model/meta.pb.dart | 128 ++++--- .../flowy-grid-data-model/meta.pbjson.dart | 21 +- .../flowy-grid/checkbox_description.pb.dart | 26 +- .../checkbox_description.pbjson.dart | 10 +- .../flowy-grid/checkbox_type_option.pb.dart | 58 +++ .../checkbox_type_option.pbenum.dart | 7 + .../checkbox_type_option.pbjson.dart | 20 + .../checkbox_type_option.pbserver.dart | 9 + .../flowy-grid/dart_notification.pbenum.dart | 8 +- .../flowy-grid/dart_notification.pbjson.dart | 6 +- .../flowy-grid/date_type_option.pb.dart | 76 ++++ .../flowy-grid/date_type_option.pbenum.dart | 45 +++ .../flowy-grid/date_type_option.pbjson.dart | 45 +++ .../flowy-grid/date_type_option.pbserver.dart | 9 + .../protobuf/flowy-grid/event_map.pbenum.dart | 10 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 10 +- .../flowy-grid/number_type_option.pb.dart | 118 ++++++ .../flowy-grid/number_type_option.pbenum.dart | 30 ++ .../flowy-grid/number_type_option.pbjson.dart | 37 ++ .../number_type_option.pbserver.dart | 9 + .../lib/protobuf/flowy-grid/protobuf.dart | 8 +- .../flowy-grid/selection_type_option.pb.dart | 196 ++++++++++ .../selection_type_option.pbenum.dart | 7 + .../selection_type_option.pbjson.dart | 44 +++ .../selection_type_option.pbserver.dart | 9 + .../flowy-grid/text_description.pb.dart | 26 +- .../flowy-grid/text_description.pbjson.dart | 10 +- frontend/rust-lib/flowy-grid/Flowy.toml | 2 +- .../flowy-grid/src/dart_notification.rs | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 54 ++- frontend/rust-lib/flowy-grid/src/event_map.rs | 14 +- frontend/rust-lib/flowy-grid/src/macros.rs | 2 +- ...description.rs => checkbox_type_option.rs} | 42 +- .../src/protobuf/model/dart_notification.rs | 20 +- ...ate_description.rs => date_type_option.rs} | 50 +-- .../src/protobuf/model/event_map.rs | 27 +- .../flowy-grid/src/protobuf/model/mod.rs | 16 +- ...r_description.rs => number_type_option.rs} | 58 +-- ...escription.rs => selection_type_option.rs} | 96 ++--- .../src/protobuf/model/text_description.rs | 42 +- ...ption.proto => checkbox_type_option.proto} | 2 +- .../protobuf/proto/dart_notification.proto | 4 +- ...scription.proto => date_type_option.proto} | 2 +- .../src/protobuf/proto/event_map.proto | 8 +- ...ription.proto => number_type_option.proto} | 2 +- ...tion.proto => selection_type_option.proto} | 4 +- .../src/protobuf/proto/text_description.proto | 2 +- .../src/services/block_meta_editor.rs | 9 +- .../src/services/cell/builder/mod.rs | 137 ------- .../src/services/cell/description/mod.rs | 11 - .../flowy-grid/src/services/cell/mod.rs | 5 - .../src/services/field/field_builder.rs | 2 +- .../flowy-grid/src/services/field/mod.rs | 2 + .../type_options/checkbox_type_option.rs} | 30 +- .../type_options/date_type_option.rs} | 40 +- .../src/services/field/type_options/mod.rs | 11 + .../type_options/number_type_option.rs} | 180 +++++---- .../type_options/selection_type_option.rs} | 55 ++- .../type_options}/text_description.rs | 20 +- .../flowy-grid/src/services/grid_editor.rs | 13 +- .../rust-lib/flowy-grid/src/services/mod.rs | 1 - .../src/services/row/cell_data_serde.rs | 26 +- frontend/rust-lib/flowy-grid/src/util.rs | 1 - .../flowy-grid/tests/grid/grid_test.rs | 59 ++- .../rust-lib/flowy-grid/tests/grid/script.rs | 74 +++- shared-lib/flowy-error-code/src/code.rs | 18 +- .../src/protobuf/model/code.rs | 35 +- .../src/protobuf/proto/code.proto | 10 +- .../src/entities/grid.rs | 21 + .../src/entities/meta.rs | 21 +- .../flowy-grid-data-model/src/parser/grid.rs | 82 ---- .../src/parser/grid_params.rs | 116 ++++++ .../flowy-grid-data-model/src/parser/id.rs | 18 - .../src/parser/id_parser.rs | 22 ++ .../flowy-grid-data-model/src/parser/mod.rs | 8 +- .../src/protobuf/model/grid.rs | 361 +++++++++++++++++- .../src/protobuf/model/meta.rs | 217 ++++++----- .../src/protobuf/proto/grid.proto | 6 + .../src/protobuf/proto/meta.proto | 17 +- .../src/client_grid/grid_meta_pad.rs | 51 ++- 97 files changed, 2554 insertions(+), 1032 deletions(-) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbserver.dart rename frontend/rust-lib/flowy-grid/src/protobuf/model/{checkbox_description.rs => checkbox_type_option.rs} (82%) rename frontend/rust-lib/flowy-grid/src/protobuf/model/{date_description.rs => date_type_option.rs} (87%) rename frontend/rust-lib/flowy-grid/src/protobuf/model/{number_description.rs => number_type_option.rs} (88%) rename frontend/rust-lib/flowy-grid/src/protobuf/model/{selection_description.rs => selection_type_option.rs} (87%) rename frontend/rust-lib/flowy-grid/src/protobuf/proto/{checkbox_description.proto => checkbox_type_option.proto} (61%) rename frontend/rust-lib/flowy-grid/src/protobuf/proto/{date_description.proto => date_type_option.proto} (89%) rename frontend/rust-lib/flowy-grid/src/protobuf/proto/{number_description.proto => number_type_option.proto} (88%) rename frontend/rust-lib/flowy-grid/src/protobuf/proto/{selection_description.proto => selection_type_option.proto} (78%) delete mode 100644 frontend/rust-lib/flowy-grid/src/services/cell/builder/mod.rs delete mode 100644 frontend/rust-lib/flowy-grid/src/services/cell/description/mod.rs delete mode 100644 frontend/rust-lib/flowy-grid/src/services/cell/mod.rs rename frontend/rust-lib/flowy-grid/src/services/{cell/description/checkbox_description.rs => field/type_options/checkbox_type_option.rs} (69%) rename frontend/rust-lib/flowy-grid/src/services/{cell/description/date_description.rs => field/type_options/date_type_option.rs} (87%) create mode 100644 frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs rename frontend/rust-lib/flowy-grid/src/services/{cell/description/number_description.rs => field/type_options/number_type_option.rs} (86%) rename frontend/rust-lib/flowy-grid/src/services/{cell/description/selection_description.rs => field/type_options/selection_type_option.rs} (71%) rename frontend/rust-lib/flowy-grid/src/services/{cell/description => field/type_options}/text_description.rs (60%) delete mode 100644 shared-lib/flowy-grid-data-model/src/parser/grid.rs create mode 100644 shared-lib/flowy-grid-data-model/src/parser/grid_params.rs delete mode 100644 shared-lib/flowy-grid-data-model/src/parser/id.rs create mode 100644 shared-lib/flowy-grid-data-model/src/parser/id_parser.rs diff --git a/frontend/app_flowy/lib/startup/home_deps_resolver.dart b/frontend/app_flowy/lib/startup/home_deps_resolver.dart index 688c53ad2a..5c4fc6267f 100644 --- a/frontend/app_flowy/lib/startup/home_deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/home_deps_resolver.dart @@ -101,9 +101,9 @@ class HomeDepsResolver { ), ); - getIt.registerFactoryParam, void>( - (data, _) => GridHeaderBloc( - data: GridColumnData(fields: data), + getIt.registerFactoryParam>( + (gridId, fields) => GridHeaderBloc( + data: GridColumnData(fields: fields), service: FieldService(), ), ); diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index 5175fe2396..73192436bf 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -19,7 +19,7 @@ class AppBloc extends Bloc { AppBloc({required this.app, required this.service, required this.listener}) : super(AppState.initial(app)) { on((event, emit) async { await event.map(initial: (e) async { - listener.startListening( + listener.start( viewsChanged: _handleViewsChanged, appUpdated: (app) => add(AppEvent.appDidUpdate(app)), ); diff --git a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart index 8f0ff7cb23..3d9bbbc65c 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart @@ -24,7 +24,7 @@ class AppListener { required this.appId, }); - void startListening({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) { + void start({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) { _viewsChanged = viewsChanged; _updated = appUpdated; _parser = FolderNotificationParser(id: appId, callback: _bservableCallback); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart index fd22d7a505..f4c7459337 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -9,9 +9,11 @@ part 'grid_header_bloc.freezed.dart'; class GridHeaderBloc extends Bloc { final FieldService service; - final GridColumnData data; - GridHeaderBloc({required this.data, required this.service}) : super(GridHeaderState.initial(data.fields)) { + GridHeaderBloc({ + required GridColumnData data, + required this.service, + }) : super(GridHeaderState.initial(data.fields)) { on( (event, emit) async { await event.map( 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 fd2fefbac5..63a2a19ec7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -19,13 +19,13 @@ class GridBloc extends Bloc { late GridBlockService _blockService; GridBloc({required this.view, required this.service}) : super(GridState.initial()) { - _gridListener = GridListener(); + _gridListener = GridListener(gridId: view.id); on( (event, emit) async { await event.map( initial: (InitialGrid value) async { - await _loadGrid(emit); + await _initGrid(emit); }, createRow: (_CreateRow value) { service.createRow(gridId: view.id); @@ -36,6 +36,9 @@ class GridBloc extends Bloc { rowsDidUpdate: (_RowsDidUpdate value) { emit(state.copyWith(rows: value.rows)); }, + fieldsDidUpdate: (_FieldsDidUpdate value) { + emit(state.copyWith(fields: value.fields)); + }, ); }, ); @@ -48,26 +51,20 @@ class GridBloc extends Bloc { return super.close(); } - Future _initGridBlockService(Grid grid, List fields) async { - _blockService = GridBlockService( - gridId: grid.id, - fields: fields, - blockOrders: grid.blockOrders, - ); - - _blockService.rowsUpdateNotifier.addPublishListener((result) { + Future _initGrid(Emitter emit) async { + _gridListener.fieldsUpdateNotifier.addPublishListener((result) { result.fold( - (rows) => add(GridEvent.rowsDidUpdate(rows)), - (err) => Log.error('$err'), + (fields) => add(GridEvent.fieldsDidUpdate(fields)), + (err) => Log.error(err), ); }); - _gridListener.start(); + + await _loadGrid(emit); } Future _loadGrid(Emitter emit) async { final result = await service.openGrid(gridId: view.id); - return Future( () => result.fold( (grid) async => await _loadFields(grid, emit), @@ -81,10 +78,10 @@ class GridBloc extends Bloc { return Future( () => result.fold( (fields) { - _initGridBlockService(grid, fields.items); + _initGridBlockService(grid); emit(state.copyWith( grid: Some(grid), - fields: Some(fields.items), + fields: fields.items, loadingState: GridLoadingState.finish(left(unit)), )); }, @@ -92,6 +89,38 @@ class GridBloc extends Bloc { ), ); } + + Future _initGridBlockService(Grid grid) async { + _blockService = GridBlockService( + gridId: grid.id, + blockOrders: grid.blockOrders, + ); + + _blockService.blocksUpdateNotifier.addPublishListener((result) { + result.fold( + (blockMap) => add(GridEvent.rowsDidUpdate(_buildRows(blockMap))), + (err) => Log.error('$err'), + ); + }); + + _gridListener.start(); + } + + List _buildRows(GridBlockMap blockMap) { + List rows = []; + blockMap.forEach((_, GridBlock gridBlock) { + rows.addAll(gridBlock.rowOrders.map( + (rowOrder) => GridRowData( + gridId: view.id, + fields: state.fields, + blockId: gridBlock.id, + rowId: rowOrder.rowId, + height: rowOrder.height.toDouble(), + ), + )); + }); + return rows; + } } @freezed @@ -102,20 +131,21 @@ abstract class GridEvent with _$GridEvent { const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; const factory GridEvent.rowsDidUpdate(List rows) = _RowsDidUpdate; + const factory GridEvent.fieldsDidUpdate(List fields) = _FieldsDidUpdate; } @freezed abstract class GridState with _$GridState { const factory GridState({ required GridLoadingState loadingState, - required Option> fields, + required List fields, required List rows, required Option grid, }) = _GridState; factory GridState.initial() => GridState( loadingState: const _Loading(), - fields: none(), + fields: [], rows: [], grid: none(), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart index f84278399c..151b587d16 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart @@ -11,51 +11,34 @@ import 'package:flowy_infra/notifier.dart'; import 'dart:async'; import 'dart:typed_data'; import 'package:app_flowy/core/notification_helper.dart'; -import 'grid_service.dart'; -typedef RowsUpdateNotifierValue = Either, FlowyError>; +typedef GridBlockMap = LinkedHashMap; +typedef BlocksUpdateNotifierValue = Either; class GridBlockService { String gridId; - List fields; - LinkedHashMap blockMap = LinkedHashMap(); + GridBlockMap blockMap = GridBlockMap(); late GridBlockListener _blockListener; - PublishNotifier rowsUpdateNotifier = PublishNotifier(); + PublishNotifier blocksUpdateNotifier = PublishNotifier(); - GridBlockService({required this.gridId, required this.fields, required List blockOrders}) { - _loadGridBlocks(blockOrders: blockOrders); + GridBlockService({required this.gridId, required List blockOrders}) { + _loadGridBlocks(blockOrders); _blockListener = GridBlockListener(gridId: gridId); - _blockListener.rowsUpdateNotifier.addPublishListener((result) { + _blockListener.blockUpdateNotifier.addPublishListener((result) { result.fold( - (blockId) => _loadGridBlocks(blockOrders: [GridBlockOrder.create()..blockId = blockId.value]), + (blockOrder) => _loadGridBlocks(blockOrder), (err) => Log.error(err), ); }); _blockListener.start(); } - List buildRows() { - List rows = []; - blockMap.forEach((_, GridBlock gridBlock) { - rows.addAll(gridBlock.rowOrders.map( - (rowOrder) => GridRowData( - gridId: gridId, - fields: fields, - blockId: gridBlock.id, - rowId: rowOrder.rowId, - height: rowOrder.height.toDouble(), - ), - )); - }); - return rows; - } - Future stop() async { await _blockListener.stop(); } - void _loadGridBlocks({required List blockOrders}) { + void _loadGridBlocks(List blockOrders) { final payload = QueryGridBlocksPayload.create() ..gridId = gridId ..blockOrders.addAll(blockOrders); @@ -66,9 +49,9 @@ class GridBlockService { for (final gridBlock in repeatedBlocks.items) { blockMap[gridBlock.id] = gridBlock; } - rowsUpdateNotifier.value = left(buildRows()); + blocksUpdateNotifier.value = left(blockMap); }, - (err) => rowsUpdateNotifier.value = right(err), + (err) => blocksUpdateNotifier.value = right(err), ); }); } @@ -76,7 +59,7 @@ class GridBlockService { class GridBlockListener { final String gridId; - PublishNotifier> rowsUpdateNotifier = PublishNotifier(comparable: null); + PublishNotifier, FlowyError>> blockUpdateNotifier = PublishNotifier(comparable: null); StreamSubscription? _subscription; late GridNotificationParser _parser; @@ -95,10 +78,10 @@ class GridBlockListener { void _handleObservableType(GridNotification ty, Either result) { switch (ty) { - case GridNotification.BlockDidUpdateRow: + case GridNotification.DidUpdateRow: result.fold( - (payload) => rowsUpdateNotifier.value = left(GridBlockId.fromBuffer(payload)), - (error) => rowsUpdateNotifier.value = right(error), + (payload) => blockUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), + (error) => blockUpdateNotifier.value = right(error), ); break; @@ -109,6 +92,6 @@ class GridBlockListener { Future stop() async { await _subscription?.cancel(); - rowsUpdateNotifier.dispose(); + blockUpdateNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart index 55e29d915c..e0423d7757 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart @@ -1,4 +1,49 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +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/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'; + +// typedef RowsUpdateNotifierValue = Either, FlowyError>; + class GridListener { - void start() {} - Future stop() async {} + final String gridId; + PublishNotifier, FlowyError>> fieldsUpdateNotifier = PublishNotifier(comparable: null); + 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.DidUpdateRow: + result.fold( + (payload) => fieldsUpdateNotifier.value = left(GridBlockId.fromBuffer(payload)), + (error) => fieldsUpdateNotifier.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + await _subscription?.cancel(); + fieldsUpdateNotifier.dispose(); + } } diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart index 8bef2e41fd..e6b61af3e2 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -14,7 +14,7 @@ class TrashBloc extends Bloc { TrashBloc({required this.service, required this.listener}) : super(TrashState.init()) { on((event, emit) async { await event.map(initial: (e) async { - listener.startListening(trashUpdated: _listenTrashUpdated); + listener.start(trashUpdated: _listenTrashUpdated); final result = await service.readTrash(); emit(result.fold( (object) => state.copyWith(objects: object.items, successOrFailure: left(unit)), diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart index 6a95de958e..dd0b1f58aa 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart @@ -15,7 +15,7 @@ class TrashListener { TrashUpdatedCallback? _trashUpdated; late FolderNotificationParser _parser; - void startListening({TrashUpdatedCallback? trashUpdated}) { + void start({TrashUpdatedCallback? trashUpdated}) { _trashUpdated = trashUpdated; _parser = FolderNotificationParser(callback: _bservableCallback); _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); 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 1d6bc07891..1b79a7a0b4 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 @@ -83,17 +83,20 @@ class _FlowyGridState extends State { @override Widget build(BuildContext context) { + final gridId = context.read().view.id; + return BlocBuilder( buildWhen: (previous, current) => previous.fields != current.fields, builder: (context, state) { - return state.fields.fold( - () => const Center(child: CircularProgressIndicator.adaptive()), - (fields) => _wrapScrollbar(fields, [ - _buildHeader(fields), - _buildRows(context), - const GridFooter(), - ]), - ); + if (state.fields.isEmpty) { + return const Center(child: CircularProgressIndicator.adaptive()); + } + + return _wrapScrollbar(state.fields, [ + _buildHeader(gridId, state.fields), + _buildRows(context), + const GridFooter(), + ]); }, ); } @@ -108,19 +111,22 @@ class _FlowyGridState extends State { axis: Axis.horizontal, child: SizedBox( width: GridLayout.headerWidth(fields), - child: CustomScrollView( - physics: StyledScrollPhysics(), - controller: _scrollController.verticalController, - slivers: [...children], + child: ScrollConfiguration( + behavior: const ScrollBehavior().copyWith(scrollbars: false), + child: CustomScrollView( + physics: StyledScrollPhysics(), + controller: _scrollController.verticalController, + slivers: [...children], + ), ), ), ), ).padding(right: 0, top: GridSize.headerHeight, bottom: GridSize.scrollBarSize); } - Widget _buildHeader(List fields) { + Widget _buildHeader(String gridId, List fields) { return SliverPersistentHeader( - delegate: GridHeaderDelegate(fields), + delegate: GridHeaderDelegate(gridId: gridId, fields: fields), floating: true, pinned: true, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index 40f6a3e3b0..f465e43843 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -12,13 +12,14 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'header_cell.dart'; class GridHeaderDelegate extends SliverPersistentHeaderDelegate { + final String gridId; final List fields; - GridHeaderDelegate(this.fields); + GridHeaderDelegate({required this.gridId, required this.fields}); @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return GridHeader(fields: fields); + return GridHeader(gridId: gridId, fields: fields); } @override @@ -38,36 +39,26 @@ class GridHeaderDelegate extends SliverPersistentHeaderDelegate { class GridHeader extends StatelessWidget { final List fields; - const GridHeader({required this.fields, Key? key}) : super(key: key); + final String gridId; + const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); return BlocProvider( - create: (context) => getIt(param1: fields)..add(const GridHeaderEvent.initial()), + create: (context) => getIt(param1: gridId, param2: fields)..add(const GridHeaderEvent.initial()), child: BlocBuilder( - builder: (context, state) { - final headers = state.fields - .map( - (field) => HeaderCellContainer( - width: field.width.toDouble(), - child: HeaderCell(field), - ), - ) - .toList(); - - return Container( - color: theme.surface, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const _HeaderLeading(), - ...headers, - const _HeaderTrailing(), - ], - ), - ); - }, + builder: (context, state) => Container( + color: theme.surface, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const _HeaderLeading(), + ...state.fields.map((field) => HeaderCell(field)), + const _HeaderTrailing(), + ], + ), + ), ), ); } @@ -97,13 +88,13 @@ class _HeaderTrailing extends StatelessWidget { border: Border(top: borderSide, bottom: borderSide), ), padding: GridSize.headerContentInsets, - child: const CreateColumnButton(), + child: const CreateFieldButton(), ); } } -class CreateColumnButton extends StatelessWidget { - const CreateColumnButton({Key? key}) : super(key: key); +class CreateFieldButton extends StatelessWidget { + const CreateFieldButton({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index fa8a3692c5..472c32d8f5 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -17,34 +17,21 @@ class HeaderCell extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); - return FlowyButton( - text: Padding( - padding: GridSize.cellContentInsets, - child: FlowyText.medium(field.name, fontSize: 12), - ), + final button = FlowyButton( hoverColor: theme.hover, onTap: () => FieldEditor.show(context, field), rightIcon: svg("editor/details", color: theme.iconColor), + text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(field.name, fontSize: 12)), ); - } -} -class HeaderCellContainer extends StatelessWidget { - final HeaderCell child; - final double width; - const HeaderCellContainer({Key? key, required this.child, required this.width}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); final borderSide = BorderSide(color: theme.shader4, width: 0.4); + final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); + return Container( - width: width, - decoration: BoxDecoration( - border: Border(top: borderSide, right: borderSide, bottom: borderSide), - ), + width: field.width.toDouble(), + decoration: decoration, padding: GridSize.headerContentInsets, - child: child, + child: button, ); } } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index c13b12e687..80b965177c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -52,6 +52,40 @@ class GridEventGetFields { } } +class GridEventUpdateField { + FieldChangeset request; + GridEventUpdateField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.UpdateField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + +class GridEventCreateField { + CreateFieldPayload request; + GridEventCreateField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.CreateField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateRow { CreateRowPayload request; GridEventCreateRow(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart index 5e5da6665d..d7119ad727 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -42,10 +42,12 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode UserIdInvalid = ErrorCode._(311, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); static const ErrorCode UserNotExist = ErrorCode._(312, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist'); static const ErrorCode TextTooLong = ErrorCode._(400, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TextTooLong'); - static const ErrorCode BlockIdIsEmpty = ErrorCode._(401, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockIdIsEmpty'); - static const ErrorCode RowIdIsEmpty = ErrorCode._(402, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty'); - static const ErrorCode GridIdIsEmpty = ErrorCode._(403, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridIdIsEmpty'); - static const ErrorCode InvalidData = ErrorCode._(404, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData'); + static const ErrorCode GridIdIsEmpty = ErrorCode._(410, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridIdIsEmpty'); + static const ErrorCode BlockIdIsEmpty = ErrorCode._(420, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockIdIsEmpty'); + static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty'); + static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty'); + static const ErrorCode TypeOptionIsEmpty = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionIsEmpty'); + static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData'); static const $core.List values = [ Internal, @@ -80,9 +82,11 @@ class ErrorCode extends $pb.ProtobufEnum { UserIdInvalid, UserNotExist, TextTooLong, + GridIdIsEmpty, BlockIdIsEmpty, RowIdIsEmpty, - GridIdIsEmpty, + FieldIdIsEmpty, + TypeOptionIsEmpty, InvalidData, ]; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart index 7c18eb68e2..41815194f2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -44,12 +44,14 @@ const ErrorCode$json = const { const {'1': 'UserIdInvalid', '2': 311}, const {'1': 'UserNotExist', '2': 312}, const {'1': 'TextTooLong', '2': 400}, - const {'1': 'BlockIdIsEmpty', '2': 401}, - const {'1': 'RowIdIsEmpty', '2': 402}, - const {'1': 'GridIdIsEmpty', '2': 403}, - const {'1': 'InvalidData', '2': 404}, + const {'1': 'GridIdIsEmpty', '2': 410}, + const {'1': 'BlockIdIsEmpty', '2': 420}, + const {'1': 'RowIdIsEmpty', '2': 430}, + const {'1': 'FieldIdIsEmpty', '2': 440}, + const {'1': 'TypeOptionIsEmpty', '2': 441}, + const {'1': 'InvalidData', '2': 500}, ], }; /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxITCg5CbG9ja0lkSXNFbXB0eRCRAxIRCgxSb3dJZElzRW1wdHkQkgMSEgoNR3JpZElkSXNFbXB0eRCTAxIQCgtJbnZhbGlkRGF0YRCUAw=='); +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFUeXBlT3B0aW9uSXNFbXB0eRC5AxIQCgtJbnZhbGlkRGF0YRD0Aw=='); 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 4462ce8b10..ce247ef7d6 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 @@ -979,6 +979,110 @@ class CreateRowPayload extends $pb.GeneratedMessage { void clearStartRowId() => clearField(2); } +enum CreateFieldPayload_OneOfStartFieldId { + startFieldId, + notSet +} + +class CreateFieldPayload extends $pb.GeneratedMessage { + static const $core.Map<$core.int, CreateFieldPayload_OneOfStartFieldId> _CreateFieldPayload_OneOfStartFieldIdByTag = { + 4 : CreateFieldPayload_OneOfStartFieldId.startFieldId, + 0 : CreateFieldPayload_OneOfStartFieldId.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateFieldPayload', createEmptyInstance: create) + ..oo(0, [4]) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'field', subBuilder: Field.create) + ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY) + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'startFieldId') + ..hasRequiredFields = false + ; + + CreateFieldPayload._() : super(); + factory CreateFieldPayload({ + $core.String? gridId, + Field? field_2, + $core.List<$core.int>? typeOptionData, + $core.String? startFieldId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (field_2 != null) { + _result.field_2 = field_2; + } + if (typeOptionData != null) { + _result.typeOptionData = typeOptionData; + } + if (startFieldId != null) { + _result.startFieldId = startFieldId; + } + return _result; + } + factory CreateFieldPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateFieldPayload.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') + CreateFieldPayload clone() => CreateFieldPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CreateFieldPayload copyWith(void Function(CreateFieldPayload) updates) => super.copyWith((message) => updates(message as CreateFieldPayload)) as CreateFieldPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateFieldPayload create() => CreateFieldPayload._(); + CreateFieldPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CreateFieldPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateFieldPayload? _defaultInstance; + + CreateFieldPayload_OneOfStartFieldId whichOneOfStartFieldId() => _CreateFieldPayload_OneOfStartFieldIdByTag[$_whichOneof(0)]!; + void clearOneOfStartFieldId() => clearField($_whichOneof(0)); + + @$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) + Field get field_2 => $_getN(1); + @$pb.TagNumber(2) + set field_2(Field v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasField_2() => $_has(1); + @$pb.TagNumber(2) + void clearField_2() => clearField(2); + @$pb.TagNumber(2) + Field ensureField_2() => $_ensure(1); + + @$pb.TagNumber(3) + $core.List<$core.int> get typeOptionData => $_getN(2); + @$pb.TagNumber(3) + set typeOptionData($core.List<$core.int> v) { $_setBytes(2, v); } + @$pb.TagNumber(3) + $core.bool hasTypeOptionData() => $_has(2); + @$pb.TagNumber(3) + void clearTypeOptionData() => clearField(3); + + @$pb.TagNumber(4) + $core.String get startFieldId => $_getSZ(3); + @$pb.TagNumber(4) + set startFieldId($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasStartFieldId() => $_has(3); + @$pb.TagNumber(4) + void clearStartFieldId() => clearField(4); +} + class QueryFieldPayload extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryFieldPayload', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') 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 cde3112874..adb25af959 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 @@ -207,6 +207,22 @@ const CreateRowPayload$json = const { /// Descriptor for `CreateRowPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List createRowPayloadDescriptor = $convert.base64Decode('ChBDcmVhdGVSb3dQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIiCgxzdGFydF9yb3dfaWQYAiABKAlIAFIKc3RhcnRSb3dJZEIVChNvbmVfb2Zfc3RhcnRfcm93X2lk'); +@$core.Deprecated('Use createFieldPayloadDescriptor instead') +const CreateFieldPayload$json = const { + '1': 'CreateFieldPayload', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field', '3': 2, '4': 1, '5': 11, '6': '.Field', '10': 'field'}, + const {'1': 'type_option_data', '3': 3, '4': 1, '5': 12, '10': 'typeOptionData'}, + const {'1': 'start_field_id', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'startFieldId'}, + ], + '8': const [ + const {'1': 'one_of_start_field_id'}, + ], +}; + +/// Descriptor for `CreateFieldPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createFieldPayloadDescriptor = $convert.base64Decode('ChJDcmVhdGVGaWVsZFBheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhwKBWZpZWxkGAIgASgLMgYuRmllbGRSBWZpZWxkEigKEHR5cGVfb3B0aW9uX2RhdGEYAyABKAxSDnR5cGVPcHRpb25EYXRhEiYKDnN0YXJ0X2ZpZWxkX2lkGAQgASgJSABSDHN0YXJ0RmllbGRJZEIXChVvbmVfb2Zfc3RhcnRfZmllbGRfaWQ='); @$core.Deprecated('Use queryFieldPayloadDescriptor instead') const QueryFieldPayload$json = const { '1': 'QueryFieldPayload', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index 4bbeae52a5..24f3409349 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -215,7 +215,7 @@ class FieldMeta extends $pb.GeneratedMessage { ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions') + ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOption') ..hasRequiredFields = false ; @@ -228,7 +228,7 @@ class FieldMeta extends $pb.GeneratedMessage { $core.bool? frozen, $core.bool? visibility, $core.int? width, - $core.String? typeOptions, + $core.String? typeOption, }) { final _result = create(); if (id != null) { @@ -252,8 +252,8 @@ class FieldMeta extends $pb.GeneratedMessage { if (width != null) { _result.width = width; } - if (typeOptions != null) { - _result.typeOptions = typeOptions; + if (typeOption != null) { + _result.typeOption = typeOption; } return _result; } @@ -342,13 +342,13 @@ class FieldMeta extends $pb.GeneratedMessage { void clearWidth() => clearField(7); @$pb.TagNumber(8) - $core.String get typeOptions => $_getSZ(7); + $core.String get typeOption => $_getSZ(7); @$pb.TagNumber(8) - set typeOptions($core.String v) { $_setString(7, v); } + set typeOption($core.String v) { $_setString(7, v); } @$pb.TagNumber(8) - $core.bool hasTypeOptions() => $_has(7); + $core.bool hasTypeOption() => $_has(7); @$pb.TagNumber(8) - void clearTypeOptions() => clearField(8); + void clearTypeOption() => clearField(8); } enum FieldChangeset_OneOfName { @@ -388,55 +388,57 @@ enum FieldChangeset_OneOfTypeOptions { class FieldChangeset extends $pb.GeneratedMessage { static const $core.Map<$core.int, FieldChangeset_OneOfName> _FieldChangeset_OneOfNameByTag = { - 2 : FieldChangeset_OneOfName.name, + 3 : FieldChangeset_OneOfName.name, 0 : FieldChangeset_OneOfName.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfDesc> _FieldChangeset_OneOfDescByTag = { - 3 : FieldChangeset_OneOfDesc.desc, + 4 : FieldChangeset_OneOfDesc.desc, 0 : FieldChangeset_OneOfDesc.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfFieldType> _FieldChangeset_OneOfFieldTypeByTag = { - 4 : FieldChangeset_OneOfFieldType.fieldType, + 5 : FieldChangeset_OneOfFieldType.fieldType, 0 : FieldChangeset_OneOfFieldType.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfFrozen> _FieldChangeset_OneOfFrozenByTag = { - 5 : FieldChangeset_OneOfFrozen.frozen, + 6 : FieldChangeset_OneOfFrozen.frozen, 0 : FieldChangeset_OneOfFrozen.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfVisibility> _FieldChangeset_OneOfVisibilityByTag = { - 6 : FieldChangeset_OneOfVisibility.visibility, + 7 : FieldChangeset_OneOfVisibility.visibility, 0 : FieldChangeset_OneOfVisibility.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfWidth> _FieldChangeset_OneOfWidthByTag = { - 7 : FieldChangeset_OneOfWidth.width, + 8 : FieldChangeset_OneOfWidth.width, 0 : FieldChangeset_OneOfWidth.notSet }; static const $core.Map<$core.int, FieldChangeset_OneOfTypeOptions> _FieldChangeset_OneOfTypeOptionsByTag = { - 8 : FieldChangeset_OneOfTypeOptions.typeOptions, + 9 : FieldChangeset_OneOfTypeOptions.typeOptions, 0 : FieldChangeset_OneOfTypeOptions.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangeset', createEmptyInstance: create) - ..oo(0, [2]) - ..oo(1, [3]) - ..oo(2, [4]) - ..oo(3, [5]) - ..oo(4, [6]) - ..oo(5, [7]) - ..oo(6, [8]) + ..oo(0, [3]) + ..oo(1, [4]) + ..oo(2, [5]) + ..oo(3, [6]) + ..oo(4, [7]) + ..oo(5, [8]) + ..oo(6, [9]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') - ..e(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') - ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') - ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: FieldType.RichText, valueOf: FieldType.valueOf, enumValues: FieldType.values) + ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') + ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') + ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) + ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions') ..hasRequiredFields = false ; FieldChangeset._() : super(); factory FieldChangeset({ $core.String? fieldId, + $core.String? gridId, $core.String? name, $core.String? desc, FieldType? fieldType, @@ -449,6 +451,9 @@ class FieldChangeset extends $pb.GeneratedMessage { if (fieldId != null) { _result.fieldId = fieldId; } + if (gridId != null) { + _result.gridId = gridId; + } if (name != null) { _result.name = name; } @@ -524,67 +529,76 @@ class FieldChangeset extends $pb.GeneratedMessage { void clearFieldId() => clearField(1); @$pb.TagNumber(2) - $core.String get name => $_getSZ(1); + $core.String get gridId => $_getSZ(1); @$pb.TagNumber(2) - set name($core.String v) { $_setString(1, v); } + set gridId($core.String v) { $_setString(1, v); } @$pb.TagNumber(2) - $core.bool hasName() => $_has(1); + $core.bool hasGridId() => $_has(1); @$pb.TagNumber(2) - void clearName() => clearField(2); + void clearGridId() => clearField(2); @$pb.TagNumber(3) - $core.String get desc => $_getSZ(2); + $core.String get name => $_getSZ(2); @$pb.TagNumber(3) - set desc($core.String v) { $_setString(2, v); } + set name($core.String v) { $_setString(2, v); } @$pb.TagNumber(3) - $core.bool hasDesc() => $_has(2); + $core.bool hasName() => $_has(2); @$pb.TagNumber(3) - void clearDesc() => clearField(3); + void clearName() => clearField(3); @$pb.TagNumber(4) - FieldType get fieldType => $_getN(3); + $core.String get desc => $_getSZ(3); @$pb.TagNumber(4) - set fieldType(FieldType v) { setField(4, v); } + set desc($core.String v) { $_setString(3, v); } @$pb.TagNumber(4) - $core.bool hasFieldType() => $_has(3); + $core.bool hasDesc() => $_has(3); @$pb.TagNumber(4) - void clearFieldType() => clearField(4); + void clearDesc() => clearField(4); @$pb.TagNumber(5) - $core.bool get frozen => $_getBF(4); + FieldType get fieldType => $_getN(4); @$pb.TagNumber(5) - set frozen($core.bool v) { $_setBool(4, v); } + set fieldType(FieldType v) { setField(5, v); } @$pb.TagNumber(5) - $core.bool hasFrozen() => $_has(4); + $core.bool hasFieldType() => $_has(4); @$pb.TagNumber(5) - void clearFrozen() => clearField(5); + void clearFieldType() => clearField(5); @$pb.TagNumber(6) - $core.bool get visibility => $_getBF(5); + $core.bool get frozen => $_getBF(5); @$pb.TagNumber(6) - set visibility($core.bool v) { $_setBool(5, v); } + set frozen($core.bool v) { $_setBool(5, v); } @$pb.TagNumber(6) - $core.bool hasVisibility() => $_has(5); + $core.bool hasFrozen() => $_has(5); @$pb.TagNumber(6) - void clearVisibility() => clearField(6); + void clearFrozen() => clearField(6); @$pb.TagNumber(7) - $core.int get width => $_getIZ(6); + $core.bool get visibility => $_getBF(6); @$pb.TagNumber(7) - set width($core.int v) { $_setSignedInt32(6, v); } + set visibility($core.bool v) { $_setBool(6, v); } @$pb.TagNumber(7) - $core.bool hasWidth() => $_has(6); + $core.bool hasVisibility() => $_has(6); @$pb.TagNumber(7) - void clearWidth() => clearField(7); + void clearVisibility() => clearField(7); @$pb.TagNumber(8) - $core.String get typeOptions => $_getSZ(7); + $core.int get width => $_getIZ(7); @$pb.TagNumber(8) - set typeOptions($core.String v) { $_setString(7, v); } + set width($core.int v) { $_setSignedInt32(7, v); } @$pb.TagNumber(8) - $core.bool hasTypeOptions() => $_has(7); + $core.bool hasWidth() => $_has(7); @$pb.TagNumber(8) - void clearTypeOptions() => clearField(8); + void clearWidth() => clearField(8); + + @$pb.TagNumber(9) + $core.String get typeOptions => $_getSZ(8); + @$pb.TagNumber(9) + set typeOptions($core.String v) { $_setString(8, v); } + @$pb.TagNumber(9) + $core.bool hasTypeOptions() => $_has(8); + @$pb.TagNumber(9) + void clearTypeOptions() => clearField(9); } class AnyData extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index d20b9da3f5..cf69a051b1 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -69,24 +69,25 @@ const FieldMeta$json = const { const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'}, const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'}, const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'}, - const {'1': 'type_options', '3': 8, '4': 1, '5': 9, '10': 'typeOptions'}, + const {'1': 'type_option', '3': 8, '4': 1, '5': 9, '10': 'typeOption'}, ], }; /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSIQoMdHlwZV9vcHRpb25zGAggASgJUgt0eXBlT3B0aW9ucw=='); +final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSHwoLdHlwZV9vcHRpb24YCCABKAlSCnR5cGVPcHRpb24='); @$core.Deprecated('Use fieldChangesetDescriptor instead') const FieldChangeset$json = const { '1': 'FieldChangeset', '2': const [ const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'name', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'name'}, - const {'1': 'desc', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'desc'}, - const {'1': 'field_type', '3': 4, '4': 1, '5': 14, '6': '.FieldType', '9': 2, '10': 'fieldType'}, - const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '9': 3, '10': 'frozen'}, - const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '9': 4, '10': 'visibility'}, - const {'1': 'width', '3': 7, '4': 1, '5': 5, '9': 5, '10': 'width'}, - const {'1': 'type_options', '3': 8, '4': 1, '5': 9, '9': 6, '10': 'typeOptions'}, + const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'name', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'name'}, + const {'1': 'desc', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'desc'}, + const {'1': 'field_type', '3': 5, '4': 1, '5': 14, '6': '.FieldType', '9': 2, '10': 'fieldType'}, + const {'1': 'frozen', '3': 6, '4': 1, '5': 8, '9': 3, '10': 'frozen'}, + const {'1': 'visibility', '3': 7, '4': 1, '5': 8, '9': 4, '10': 'visibility'}, + const {'1': 'width', '3': 8, '4': 1, '5': 5, '9': 5, '10': 'width'}, + const {'1': 'type_options', '3': 9, '4': 1, '5': 9, '9': 6, '10': 'typeOptions'}, ], '8': const [ const {'1': 'one_of_name'}, @@ -100,7 +101,7 @@ const FieldChangeset$json = const { }; /// Descriptor for `FieldChangeset`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIUCgRuYW1lGAIgASgJSABSBG5hbWUSFAoEZGVzYxgDIAEoCUgBUgRkZXNjEisKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVIAlIJZmllbGRUeXBlEhgKBmZyb3plbhgFIAEoCEgDUgZmcm96ZW4SIAoKdmlzaWJpbGl0eRgGIAEoCEgEUgp2aXNpYmlsaXR5EhYKBXdpZHRoGAcgASgFSAVSBXdpZHRoEiMKDHR5cGVfb3B0aW9ucxgIIAEoCUgGUgt0eXBlT3B0aW9uc0INCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0ITChFvbmVfb2ZfZmllbGRfdHlwZUIPCg1vbmVfb2ZfZnJvemVuQhMKEW9uZV9vZl92aXNpYmlsaXR5Qg4KDG9uZV9vZl93aWR0aEIVChNvbmVfb2ZfdHlwZV9vcHRpb25z'); +final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIXCgdncmlkX2lkGAIgASgJUgZncmlkSWQSFAoEbmFtZRgDIAEoCUgAUgRuYW1lEhQKBGRlc2MYBCABKAlIAVIEZGVzYxIrCgpmaWVsZF90eXBlGAUgASgOMgouRmllbGRUeXBlSAJSCWZpZWxkVHlwZRIYCgZmcm96ZW4YBiABKAhIA1IGZnJvemVuEiAKCnZpc2liaWxpdHkYByABKAhIBFIKdmlzaWJpbGl0eRIWCgV3aWR0aBgIIAEoBUgFUgV3aWR0aBIjCgx0eXBlX29wdGlvbnMYCSABKAlIBlILdHlwZU9wdGlvbnNCDQoLb25lX29mX25hbWVCDQoLb25lX29mX2Rlc2NCEwoRb25lX29mX2ZpZWxkX3R5cGVCDwoNb25lX29mX2Zyb3plbkITChFvbmVfb2ZfdmlzaWJpbGl0eUIOCgxvbmVfb2Zfd2lkdGhCFQoTb25lX29mX3R5cGVfb3B0aW9ucw=='); @$core.Deprecated('Use anyDataDescriptor instead') const AnyData$json = const { '1': 'AnyData', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart index 8481b81985..04b2ae6e81 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart @@ -9,14 +9,14 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class CheckboxDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxDescription', createEmptyInstance: create) +class CheckboxTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxTypeOption', createEmptyInstance: create) ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected') ..hasRequiredFields = false ; - CheckboxDescription._() : super(); - factory CheckboxDescription({ + CheckboxTypeOption._() : super(); + factory CheckboxTypeOption({ $core.bool? isSelected, }) { final _result = create(); @@ -25,26 +25,26 @@ class CheckboxDescription extends $pb.GeneratedMessage { } return _result; } - factory CheckboxDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CheckboxDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory CheckboxTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CheckboxTypeOption.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') - CheckboxDescription clone() => CheckboxDescription()..mergeFromMessage(this); + CheckboxTypeOption clone() => CheckboxTypeOption()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CheckboxDescription copyWith(void Function(CheckboxDescription) updates) => super.copyWith((message) => updates(message as CheckboxDescription)) as CheckboxDescription; // ignore: deprecated_member_use + CheckboxTypeOption copyWith(void Function(CheckboxTypeOption) updates) => super.copyWith((message) => updates(message as CheckboxTypeOption)) as CheckboxTypeOption; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static CheckboxDescription create() => CheckboxDescription._(); - CheckboxDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static CheckboxTypeOption create() => CheckboxTypeOption._(); + CheckboxTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static CheckboxDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CheckboxDescription? _defaultInstance; + static CheckboxTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CheckboxTypeOption? _defaultInstance; @$pb.TagNumber(1) $core.bool get isSelected => $_getBF(0); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart index 6295b27033..0569b0665a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart @@ -8,13 +8,13 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use checkboxDescriptionDescriptor instead') -const CheckboxDescription$json = const { - '1': 'CheckboxDescription', +@$core.Deprecated('Use checkboxTypeOptionDescriptor instead') +const CheckboxTypeOption$json = const { + '1': 'CheckboxTypeOption', '2': const [ const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'}, ], }; -/// Descriptor for `CheckboxDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List checkboxDescriptionDescriptor = $convert.base64Decode('ChNDaGVja2JveERlc2NyaXB0aW9uEh8KC2lzX3NlbGVjdGVkGAEgASgIUgppc1NlbGVjdGVk'); +/// Descriptor for `CheckboxTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List checkboxTypeOptionDescriptor = $convert.base64Decode('ChJDaGVja2JveFR5cGVPcHRpb24SHwoLaXNfc2VsZWN0ZWQYASABKAhSCmlzU2VsZWN0ZWQ='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pb.dart new file mode 100644 index 0000000000..fb907766cf --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pb.dart @@ -0,0 +1,58 @@ +/// +// Generated code. Do not modify. +// source: checkbox_type_option.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:protobuf/protobuf.dart' as $pb; + +class CheckboxTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxTypeOption', createEmptyInstance: create) + ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected') + ..hasRequiredFields = false + ; + + CheckboxTypeOption._() : super(); + factory CheckboxTypeOption({ + $core.bool? isSelected, + }) { + final _result = create(); + if (isSelected != null) { + _result.isSelected = isSelected; + } + return _result; + } + factory CheckboxTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CheckboxTypeOption.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') + CheckboxTypeOption clone() => CheckboxTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CheckboxTypeOption copyWith(void Function(CheckboxTypeOption) updates) => super.copyWith((message) => updates(message as CheckboxTypeOption)) as CheckboxTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CheckboxTypeOption create() => CheckboxTypeOption._(); + CheckboxTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CheckboxTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CheckboxTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + $core.bool get isSelected => $_getBF(0); + @$pb.TagNumber(1) + set isSelected($core.bool v) { $_setBool(0, v); } + @$pb.TagNumber(1) + $core.bool hasIsSelected() => $_has(0); + @$pb.TagNumber(1) + void clearIsSelected() => clearField(1); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbenum.dart new file mode 100644 index 0000000000..7c03d6985e --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: checkbox_type_option.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 + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbjson.dart new file mode 100644 index 0000000000..33c4627985 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbjson.dart @@ -0,0 +1,20 @@ +/// +// Generated code. Do not modify. +// source: checkbox_type_option.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 checkboxTypeOptionDescriptor instead') +const CheckboxTypeOption$json = const { + '1': 'CheckboxTypeOption', + '2': const [ + const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'}, + ], +}; + +/// Descriptor for `CheckboxTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List checkboxTypeOptionDescriptor = $convert.base64Decode('ChJDaGVja2JveFR5cGVPcHRpb24SHwoLaXNfc2VsZWN0ZWQYASABKAhSCmlzU2VsZWN0ZWQ='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbserver.dart new file mode 100644 index 0000000000..5424623115 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_type_option.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: checkbox_type_option.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 'checkbox_type_option.pb.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 index 27985d016c..c000793a5e 100644 --- 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 @@ -12,16 +12,16 @@ 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 GridDidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateBlock'); - static const GridNotification BlockDidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockDidUpdateRow'); + static const GridNotification DidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); - static const GridNotification GridDidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateFields'); + static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); static const $core.List values = [ Unknown, GridDidCreateBlock, - BlockDidUpdateRow, + DidUpdateRow, GridDidUpdateCells, - GridDidUpdateFields, + DidUpdateFields, ]; static final $core.Map<$core.int, GridNotification> _byValue = $pb.ProtobufEnum.initByValue(values); 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 index 0eebf85cc6..5dc1fbc1a5 100644 --- 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 @@ -14,11 +14,11 @@ const GridNotification$json = const { '2': const [ const {'1': 'Unknown', '2': 0}, const {'1': 'GridDidCreateBlock', '2': 11}, - const {'1': 'BlockDidUpdateRow', '2': 20}, + const {'1': 'DidUpdateRow', '2': 20}, const {'1': 'GridDidUpdateCells', '2': 30}, - const {'1': 'GridDidUpdateFields', '2': 40}, + const {'1': 'DidUpdateFields', '2': 40}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIVChFCbG9ja0RpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhcKE0dyaWREaWRVcGRhdGVGaWVsZHMQKA=='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIQCgxEaWRVcGRhdGVSb3cQFBIWChJHcmlkRGlkVXBkYXRlQ2VsbHMQHhITCg9EaWRVcGRhdGVGaWVsZHMQKA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart new file mode 100644 index 0000000000..85c5e55111 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart @@ -0,0 +1,76 @@ +/// +// Generated code. Do not modify. +// source: date_type_option.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:protobuf/protobuf.dart' as $pb; + +import 'date_type_option.pbenum.dart'; + +export 'date_type_option.pbenum.dart'; + +class DateTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateTypeOption', createEmptyInstance: create) + ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dateFormat', $pb.PbFieldType.OE, defaultOrMaker: DateFormat.Local, valueOf: DateFormat.valueOf, enumValues: DateFormat.values) + ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeFormat', $pb.PbFieldType.OE, defaultOrMaker: TimeFormat.TwelveHour, valueOf: TimeFormat.valueOf, enumValues: TimeFormat.values) + ..hasRequiredFields = false + ; + + DateTypeOption._() : super(); + factory DateTypeOption({ + DateFormat? dateFormat, + TimeFormat? timeFormat, + }) { + final _result = create(); + if (dateFormat != null) { + _result.dateFormat = dateFormat; + } + if (timeFormat != null) { + _result.timeFormat = timeFormat; + } + return _result; + } + factory DateTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DateTypeOption.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') + DateTypeOption clone() => DateTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + DateTypeOption copyWith(void Function(DateTypeOption) updates) => super.copyWith((message) => updates(message as DateTypeOption)) as DateTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static DateTypeOption create() => DateTypeOption._(); + DateTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static DateTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static DateTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + DateFormat get dateFormat => $_getN(0); + @$pb.TagNumber(1) + set dateFormat(DateFormat v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasDateFormat() => $_has(0); + @$pb.TagNumber(1) + void clearDateFormat() => clearField(1); + + @$pb.TagNumber(2) + TimeFormat get timeFormat => $_getN(1); + @$pb.TagNumber(2) + set timeFormat(TimeFormat v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasTimeFormat() => $_has(1); + @$pb.TagNumber(2) + void clearTimeFormat() => clearField(2); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbenum.dart new file mode 100644 index 0000000000..63255cb1ab --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbenum.dart @@ -0,0 +1,45 @@ +/// +// Generated code. Do not modify. +// source: date_type_option.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 DateFormat extends $pb.ProtobufEnum { + static const DateFormat Local = DateFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); + static const DateFormat US = DateFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'US'); + static const DateFormat ISO = DateFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ISO'); + static const DateFormat Friendly = DateFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Friendly'); + + static const $core.List values = [ + Local, + US, + ISO, + Friendly, + ]; + + static final $core.Map<$core.int, DateFormat> _byValue = $pb.ProtobufEnum.initByValue(values); + static DateFormat? valueOf($core.int value) => _byValue[value]; + + const DateFormat._($core.int v, $core.String n) : super(v, n); +} + +class TimeFormat extends $pb.ProtobufEnum { + static const TimeFormat TwelveHour = TimeFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwelveHour'); + static const TimeFormat TwentyFourHour = TimeFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwentyFourHour'); + + static const $core.List values = [ + TwelveHour, + TwentyFourHour, + ]; + + static final $core.Map<$core.int, TimeFormat> _byValue = $pb.ProtobufEnum.initByValue(values); + static TimeFormat? valueOf($core.int value) => _byValue[value]; + + const TimeFormat._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart new file mode 100644 index 0000000000..9acf67241b --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart @@ -0,0 +1,45 @@ +/// +// Generated code. Do not modify. +// source: date_type_option.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 dateFormatDescriptor instead') +const DateFormat$json = const { + '1': 'DateFormat', + '2': const [ + const {'1': 'Local', '2': 0}, + const {'1': 'US', '2': 1}, + const {'1': 'ISO', '2': 2}, + const {'1': 'Friendly', '2': 3}, + ], +}; + +/// Descriptor for `DateFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List dateFormatDescriptor = $convert.base64Decode('CgpEYXRlRm9ybWF0EgkKBUxvY2FsEAASBgoCVVMQARIHCgNJU08QAhIMCghGcmllbmRseRAD'); +@$core.Deprecated('Use timeFormatDescriptor instead') +const TimeFormat$json = const { + '1': 'TimeFormat', + '2': const [ + const {'1': 'TwelveHour', '2': 0}, + const {'1': 'TwentyFourHour', '2': 1}, + ], +}; + +/// Descriptor for `TimeFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List timeFormatDescriptor = $convert.base64Decode('CgpUaW1lRm9ybWF0Eg4KClR3ZWx2ZUhvdXIQABISCg5Ud2VudHlGb3VySG91chAB'); +@$core.Deprecated('Use dateTypeOptionDescriptor instead') +const DateTypeOption$json = const { + '1': 'DateTypeOption', + '2': const [ + const {'1': 'date_format', '3': 1, '4': 1, '5': 14, '6': '.DateFormat', '10': 'dateFormat'}, + const {'1': 'time_format', '3': 2, '4': 1, '5': 14, '6': '.TimeFormat', '10': 'timeFormat'}, + ], +}; + +/// Descriptor for `DateTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List dateTypeOptionDescriptor = $convert.base64Decode('Cg5EYXRlVHlwZU9wdGlvbhIsCgtkYXRlX2Zvcm1hdBgBIAEoDjILLkRhdGVGb3JtYXRSCmRhdGVGb3JtYXQSLAoLdGltZV9mb3JtYXQYAiABKA4yCy5UaW1lRm9ybWF0Ugp0aW1lRm9ybWF0'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbserver.dart new file mode 100644 index 0000000000..b95719d206 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: date_type_option.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 'date_type_option.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 91a3861076..4488ba1a3d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -13,14 +13,18 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent GetGridData = GridEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetGridData'); static const GridEvent GetGridBlocks = GridEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetGridBlocks'); static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields'); - static const GridEvent CreateRow = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); - static const GridEvent GetRow = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); - static const GridEvent UpdateCell = GridEvent._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); + static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); + static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); + static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); + static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); + static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); static const $core.List values = [ GetGridData, GetGridBlocks, GetFields, + UpdateField, + CreateField, CreateRow, GetRow, UpdateCell, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index c203b10c75..c70007eaaa 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -15,11 +15,13 @@ const GridEvent$json = const { const {'1': 'GetGridData', '2': 0}, const {'1': 'GetGridBlocks', '2': 1}, const {'1': 'GetFields', '2': 10}, - const {'1': 'CreateRow', '2': 11}, - const {'1': 'GetRow', '2': 12}, - const {'1': 'UpdateCell', '2': 20}, + const {'1': 'UpdateField', '2': 11}, + const {'1': 'CreateField', '2': 12}, + const {'1': 'CreateRow', '2': 21}, + const {'1': 'GetRow', '2': 22}, + const {'1': 'UpdateCell', '2': 30}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDQoJQ3JlYXRlUm93EAsSCgoGR2V0Um93EAwSDgoKVXBkYXRlQ2VsbBAU'); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart new file mode 100644 index 0000000000..54f4d9546f --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart @@ -0,0 +1,118 @@ +/// +// Generated code. Do not modify. +// source: number_type_option.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:protobuf/protobuf.dart' as $pb; + +import 'number_type_option.pbenum.dart'; + +export 'number_type_option.pbenum.dart'; + +class NumberTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberTypeOption', createEmptyInstance: create) + ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: NumberFormat.Number, valueOf: NumberFormat.valueOf, enumValues: NumberFormat.values) + ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3) + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol') + ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive') + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..hasRequiredFields = false + ; + + NumberTypeOption._() : super(); + factory NumberTypeOption({ + NumberFormat? format, + $core.int? scale, + $core.String? symbol, + $core.bool? signPositive, + $core.String? name, + }) { + final _result = create(); + if (format != null) { + _result.format = format; + } + if (scale != null) { + _result.scale = scale; + } + if (symbol != null) { + _result.symbol = symbol; + } + if (signPositive != null) { + _result.signPositive = signPositive; + } + if (name != null) { + _result.name = name; + } + return _result; + } + factory NumberTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NumberTypeOption.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') + NumberTypeOption clone() => NumberTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + NumberTypeOption copyWith(void Function(NumberTypeOption) updates) => super.copyWith((message) => updates(message as NumberTypeOption)) as NumberTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static NumberTypeOption create() => NumberTypeOption._(); + NumberTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static NumberTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static NumberTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + NumberFormat get format => $_getN(0); + @$pb.TagNumber(1) + set format(NumberFormat v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasFormat() => $_has(0); + @$pb.TagNumber(1) + void clearFormat() => clearField(1); + + @$pb.TagNumber(2) + $core.int get scale => $_getIZ(1); + @$pb.TagNumber(2) + set scale($core.int v) { $_setUnsignedInt32(1, v); } + @$pb.TagNumber(2) + $core.bool hasScale() => $_has(1); + @$pb.TagNumber(2) + void clearScale() => clearField(2); + + @$pb.TagNumber(3) + $core.String get symbol => $_getSZ(2); + @$pb.TagNumber(3) + set symbol($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasSymbol() => $_has(2); + @$pb.TagNumber(3) + void clearSymbol() => clearField(3); + + @$pb.TagNumber(4) + $core.bool get signPositive => $_getBF(3); + @$pb.TagNumber(4) + set signPositive($core.bool v) { $_setBool(3, v); } + @$pb.TagNumber(4) + $core.bool hasSignPositive() => $_has(3); + @$pb.TagNumber(4) + void clearSignPositive() => clearField(4); + + @$pb.TagNumber(5) + $core.String get name => $_getSZ(4); + @$pb.TagNumber(5) + set name($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasName() => $_has(4); + @$pb.TagNumber(5) + void clearName() => clearField(5); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart new file mode 100644 index 0000000000..5e486443c6 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart @@ -0,0 +1,30 @@ +/// +// Generated code. Do not modify. +// source: number_type_option.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 NumberFormat extends $pb.ProtobufEnum { + static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number'); + static const NumberFormat USD = NumberFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD'); + static const NumberFormat CNY = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY'); + static const NumberFormat EUR = NumberFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR'); + + static const $core.List values = [ + Number, + USD, + CNY, + EUR, + ]; + + static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values); + static NumberFormat? valueOf($core.int value) => _byValue[value]; + + const NumberFormat._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart new file mode 100644 index 0000000000..d3c593d40e --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart @@ -0,0 +1,37 @@ +/// +// Generated code. Do not modify. +// source: number_type_option.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 numberFormatDescriptor instead') +const NumberFormat$json = const { + '1': 'NumberFormat', + '2': const [ + const {'1': 'Number', '2': 0}, + const {'1': 'USD', '2': 1}, + const {'1': 'CNY', '2': 2}, + const {'1': 'EUR', '2': 3}, + ], +}; + +/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESBwoDQ05ZEAISBwoDRVVSEAM='); +@$core.Deprecated('Use numberTypeOptionDescriptor instead') +const NumberTypeOption$json = const { + '1': 'NumberTypeOption', + '2': const [ + const {'1': 'format', '3': 1, '4': 1, '5': 14, '6': '.NumberFormat', '10': 'format'}, + const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'}, + const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'}, + const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'}, + const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'}, + ], +}; + +/// Descriptor for `NumberTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List numberTypeOptionDescriptor = $convert.base64Decode('ChBOdW1iZXJUeXBlT3B0aW9uEiUKBmZvcm1hdBgBIAEoDjINLk51bWJlckZvcm1hdFIGZm9ybWF0EhQKBXNjYWxlGAIgASgNUgVzY2FsZRIWCgZzeW1ib2wYAyABKAlSBnN5bWJvbBIjCg1zaWduX3Bvc2l0aXZlGAQgASgIUgxzaWduUG9zaXRpdmUSEgoEbmFtZRgFIAEoCVIEbmFtZQ=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbserver.dart new file mode 100644 index 0000000000..107c3a1d86 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: number_type_option.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 'number_type_option.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 daefe6a170..8f0a7e7d48 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,8 +1,8 @@ // Auto-generated, do not edit -export './date_description.pb.dart'; +export './number_type_option.pb.dart'; export './text_description.pb.dart'; export './dart_notification.pb.dart'; -export './checkbox_description.pb.dart'; -export './selection_description.pb.dart'; +export './selection_type_option.pb.dart'; +export './checkbox_type_option.pb.dart'; export './event_map.pb.dart'; -export './number_description.pb.dart'; +export './date_type_option.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart new file mode 100644 index 0000000000..f2222d82b8 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart @@ -0,0 +1,196 @@ +/// +// Generated code. Do not modify. +// source: selection_type_option.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:protobuf/protobuf.dart' as $pb; + +class SingleSelectTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelectTypeOption', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) + ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') + ..hasRequiredFields = false + ; + + SingleSelectTypeOption._() : super(); + factory SingleSelectTypeOption({ + $core.Iterable? options, + $core.bool? disableColor, + }) { + final _result = create(); + if (options != null) { + _result.options.addAll(options); + } + if (disableColor != null) { + _result.disableColor = disableColor; + } + return _result; + } + factory SingleSelectTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SingleSelectTypeOption.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') + SingleSelectTypeOption clone() => SingleSelectTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SingleSelectTypeOption copyWith(void Function(SingleSelectTypeOption) updates) => super.copyWith((message) => updates(message as SingleSelectTypeOption)) as SingleSelectTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SingleSelectTypeOption create() => SingleSelectTypeOption._(); + SingleSelectTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SingleSelectTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SingleSelectTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get options => $_getList(0); + + @$pb.TagNumber(2) + $core.bool get disableColor => $_getBF(1); + @$pb.TagNumber(2) + set disableColor($core.bool v) { $_setBool(1, v); } + @$pb.TagNumber(2) + $core.bool hasDisableColor() => $_has(1); + @$pb.TagNumber(2) + void clearDisableColor() => clearField(2); +} + +class MultiSelectTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiSelectTypeOption', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) + ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') + ..hasRequiredFields = false + ; + + MultiSelectTypeOption._() : super(); + factory MultiSelectTypeOption({ + $core.Iterable? options, + $core.bool? disableColor, + }) { + final _result = create(); + if (options != null) { + _result.options.addAll(options); + } + if (disableColor != null) { + _result.disableColor = disableColor; + } + return _result; + } + factory MultiSelectTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory MultiSelectTypeOption.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') + MultiSelectTypeOption clone() => MultiSelectTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + MultiSelectTypeOption copyWith(void Function(MultiSelectTypeOption) updates) => super.copyWith((message) => updates(message as MultiSelectTypeOption)) as MultiSelectTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static MultiSelectTypeOption create() => MultiSelectTypeOption._(); + MultiSelectTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static MultiSelectTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static MultiSelectTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get options => $_getList(0); + + @$pb.TagNumber(2) + $core.bool get disableColor => $_getBF(1); + @$pb.TagNumber(2) + set disableColor($core.bool v) { $_setBool(1, v); } + @$pb.TagNumber(2) + $core.bool hasDisableColor() => $_has(1); + @$pb.TagNumber(2) + void clearDisableColor() => clearField(2); +} + +class SelectOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', 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') ? '' : 'color') + ..hasRequiredFields = false + ; + + SelectOption._() : super(); + factory SelectOption({ + $core.String? id, + $core.String? name, + $core.String? color, + }) { + final _result = create(); + if (id != null) { + _result.id = id; + } + if (name != null) { + _result.name = name; + } + if (color != null) { + _result.color = color; + } + return _result; + } + factory SelectOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectOption.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') + SelectOption clone() => SelectOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectOption copyWith(void Function(SelectOption) updates) => super.copyWith((message) => updates(message as SelectOption)) as SelectOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SelectOption create() => SelectOption._(); + SelectOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectOption? _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 color => $_getSZ(2); + @$pb.TagNumber(3) + set color($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasColor() => $_has(2); + @$pb.TagNumber(3) + void clearColor() => clearField(3); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart new file mode 100644 index 0000000000..9a52c17f7d --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: selection_type_option.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 + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart new file mode 100644 index 0000000000..fdfc6833b0 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart @@ -0,0 +1,44 @@ +/// +// Generated code. Do not modify. +// source: selection_type_option.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 singleSelectTypeOptionDescriptor instead') +const SingleSelectTypeOption$json = const { + '1': 'SingleSelectTypeOption', + '2': const [ + const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, + const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, + ], +}; + +/// Descriptor for `SingleSelectTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List singleSelectTypeOptionDescriptor = $convert.base64Decode('ChZTaW5nbGVTZWxlY3RUeXBlT3B0aW9uEicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSIwoNZGlzYWJsZV9jb2xvchgCIAEoCFIMZGlzYWJsZUNvbG9y'); +@$core.Deprecated('Use multiSelectTypeOptionDescriptor instead') +const MultiSelectTypeOption$json = const { + '1': 'MultiSelectTypeOption', + '2': const [ + const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, + const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, + ], +}; + +/// Descriptor for `MultiSelectTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List multiSelectTypeOptionDescriptor = $convert.base64Decode('ChVNdWx0aVNlbGVjdFR5cGVPcHRpb24SJwoHb3B0aW9ucxgBIAMoCzINLlNlbGVjdE9wdGlvblIHb3B0aW9ucxIjCg1kaXNhYmxlX2NvbG9yGAIgASgIUgxkaXNhYmxlQ29sb3I='); +@$core.Deprecated('Use selectOptionDescriptor instead') +const SelectOption$json = const { + '1': 'SelectOption', + '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': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'}, + ], +}; + +/// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbserver.dart new file mode 100644 index 0000000000..2e9ff7c00b --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: selection_type_option.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 'selection_type_option.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pb.dart index 9434b2fc90..c8f930be1b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pb.dart @@ -9,14 +9,14 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class RichTextDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextDescription', createEmptyInstance: create) +class RichTextTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextTypeOption', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format') ..hasRequiredFields = false ; - RichTextDescription._() : super(); - factory RichTextDescription({ + RichTextTypeOption._() : super(); + factory RichTextTypeOption({ $core.String? format, }) { final _result = create(); @@ -25,26 +25,26 @@ class RichTextDescription extends $pb.GeneratedMessage { } return _result; } - factory RichTextDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory RichTextDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory RichTextTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RichTextTypeOption.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') - RichTextDescription clone() => RichTextDescription()..mergeFromMessage(this); + RichTextTypeOption clone() => RichTextTypeOption()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - RichTextDescription copyWith(void Function(RichTextDescription) updates) => super.copyWith((message) => updates(message as RichTextDescription)) as RichTextDescription; // ignore: deprecated_member_use + RichTextTypeOption copyWith(void Function(RichTextTypeOption) updates) => super.copyWith((message) => updates(message as RichTextTypeOption)) as RichTextTypeOption; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static RichTextDescription create() => RichTextDescription._(); - RichTextDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static RichTextTypeOption create() => RichTextTypeOption._(); + RichTextTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static RichTextDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static RichTextDescription? _defaultInstance; + static RichTextTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static RichTextTypeOption? _defaultInstance; @$pb.TagNumber(1) $core.String get format => $_getSZ(0); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pbjson.dart index fdf2098d47..ebe805501b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_description.pbjson.dart @@ -8,13 +8,13 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use richTextDescriptionDescriptor instead') -const RichTextDescription$json = const { - '1': 'RichTextDescription', +@$core.Deprecated('Use richTextTypeOptionDescriptor instead') +const RichTextTypeOption$json = const { + '1': 'RichTextTypeOption', '2': const [ const {'1': 'format', '3': 1, '4': 1, '5': 9, '10': 'format'}, ], }; -/// Descriptor for `RichTextDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List richTextDescriptionDescriptor = $convert.base64Decode('ChNSaWNoVGV4dERlc2NyaXB0aW9uEhYKBmZvcm1hdBgBIAEoCVIGZm9ybWF0'); +/// Descriptor for `RichTextTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List richTextTypeOptionDescriptor = $convert.base64Decode('ChJSaWNoVGV4dFR5cGVPcHRpb24SFgoGZm9ybWF0GAEgASgJUgZmb3JtYXQ='); diff --git a/frontend/rust-lib/flowy-grid/Flowy.toml b/frontend/rust-lib/flowy-grid/Flowy.toml index b310e3fcd7..d0b6c8dec5 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", "src/dart_notification.rs"] +proto_crates = ["src/event_map.rs", "src/services/field/type_options", "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 index 927b71d957..34c972a9bb 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -8,10 +8,10 @@ pub enum GridNotification { GridDidCreateBlock = 11, - BlockDidUpdateRow = 20, + DidUpdateRow = 20, GridDidUpdateCells = 30, - GridDidUpdateFields = 40, + DidUpdateFields = 40, } impl std::default::Default for GridNotification { diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 73aed6da43..59e3aa2a39 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,10 +1,12 @@ use crate::manager::GridManager; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{ - CellMetaChangeset, CreateRowPayload, Field, Grid, GridId, QueryFieldPayload, QueryGridBlocksPayload, - QueryRowPayload, RepeatedField, RepeatedGridBlock, Row, + CellMetaChangeset, CreateFieldPayload, CreateRowPayload, Field, FieldChangeset, Grid, GridId, QueryFieldPayload, + QueryGridBlocksPayload, QueryRowPayload, RepeatedField, RepeatedGridBlock, Row, +}; +use flowy_grid_data_model::parser::{ + CreateFieldParams, CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams, }; -use flowy_grid_data_model::parser::{CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams}; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; @@ -35,6 +37,40 @@ pub(crate) async fn get_grid_blocks_handler( data_result(repeated_grid_block) } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn get_fields_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: QueryFieldParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let field_metas = editor.get_field_metas(Some(params.field_orders)).await?; + let repeated_field: RepeatedField = field_metas.into_iter().map(Field::from).collect::>().into(); + data_result(repeated_field) +} + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn update_field_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let changeset: FieldChangeset = data.into_inner(); + let editor = manager.get_grid_editor(&changeset.grid_id)?; + let _ = editor.update_field(changeset).await?; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn create_field_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let params: CreateFieldParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.create_field(params).await?; + Ok(()) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_row_handler( data: Data, @@ -48,18 +84,6 @@ pub(crate) async fn get_row_handler( } } -#[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn get_fields_handler( - data: Data, - manager: AppData>, -) -> DataResult { - let params: QueryFieldParams = data.into_inner().try_into()?; - let editor = manager.get_grid_editor(¶ms.grid_id)?; - let field_metas = editor.get_field_metas(Some(params.field_orders)).await?; - let repeated_field: RepeatedField = field_metas.into_iter().map(Field::from).collect::>().into(); - data_result(repeated_field) -} - #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn create_row_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 03b27f4c70..944c58d13b 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -11,6 +11,8 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetGridData, get_grid_data_handler) .event(GridEvent::GetGridBlocks, get_grid_blocks_handler) .event(GridEvent::GetFields, get_fields_handler) + .event(GridEvent::UpdateField, update_field_handler) + .event(GridEvent::CreateField, create_field_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) .event(GridEvent::UpdateCell, update_cell_handler); @@ -30,12 +32,18 @@ pub enum GridEvent { #[event(input = "QueryFieldPayload", output = "RepeatedField")] GetFields = 10, + #[event(input = "FieldChangeset")] + UpdateField = 11, + + #[event(input = "CreateFieldPayload")] + CreateField = 12, + #[event(input = "CreateRowPayload", output = "Row")] - CreateRow = 11, + CreateRow = 21, #[event(input = "QueryRowPayload", output = "Row")] - GetRow = 12, + GetRow = 22, #[event(input = "CellMetaChangeset")] - UpdateCell = 20, + UpdateCell = 30, } diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index d7a5fc8bf8..b4a9cf1531 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -11,7 +11,7 @@ macro_rules! impl_from_field_type_option { ($target: ident) => { impl std::convert::From<&FieldMeta> for $target { fn from(field_meta: &FieldMeta) -> $target { - match serde_json::from_str(&field_meta.type_options) { + match serde_json::from_str(&field_meta.type_option) { Ok(obj) => obj, Err(err) => { tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_type_option.rs similarity index 82% rename from frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_description.rs rename to frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_type_option.rs index 276617efbd..95612e4765 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/checkbox_type_option.rs @@ -17,14 +17,14 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `checkbox_description.proto` +//! Generated file from `checkbox_type_option.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct CheckboxDescription { +pub struct CheckboxTypeOption { // message fields pub is_selected: bool, // special fields @@ -32,14 +32,14 @@ pub struct CheckboxDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a CheckboxDescription { - fn default() -> &'a CheckboxDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a CheckboxTypeOption { + fn default() -> &'a CheckboxTypeOption { + ::default_instance() } } -impl CheckboxDescription { - pub fn new() -> CheckboxDescription { +impl CheckboxTypeOption { + pub fn new() -> CheckboxTypeOption { ::std::default::Default::default() } @@ -59,7 +59,7 @@ impl CheckboxDescription { } } -impl ::protobuf::Message for CheckboxDescription { +impl ::protobuf::Message for CheckboxTypeOption { fn is_initialized(&self) -> bool { true } @@ -129,8 +129,8 @@ impl ::protobuf::Message for CheckboxDescription { Self::descriptor_static() } - fn new() -> CheckboxDescription { - CheckboxDescription::new() + fn new() -> CheckboxTypeOption { + CheckboxTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -139,44 +139,44 @@ impl ::protobuf::Message for CheckboxDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( "is_selected", - |m: &CheckboxDescription| { &m.is_selected }, - |m: &mut CheckboxDescription| { &mut m.is_selected }, + |m: &CheckboxTypeOption| { &m.is_selected }, + |m: &mut CheckboxTypeOption| { &mut m.is_selected }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CheckboxDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CheckboxTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static CheckboxDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CheckboxDescription::new) + fn default_instance() -> &'static CheckboxTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CheckboxTypeOption::new) } } -impl ::protobuf::Clear for CheckboxDescription { +impl ::protobuf::Clear for CheckboxTypeOption { fn clear(&mut self) { self.is_selected = false; self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for CheckboxDescription { +impl ::std::fmt::Debug for CheckboxTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for CheckboxDescription { +impl ::protobuf::reflect::ProtobufValue for CheckboxTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x1acheckbox_description.proto\"6\n\x13CheckboxDescription\x12\x1f\n\ + \n\x1acheckbox_type_option.proto\"5\n\x12CheckboxTypeOption\x12\x1f\n\ \x0bis_selected\x18\x01\x20\x01(\x08R\nisSelectedb\x06proto3\ "; 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 index 4562b238c0..0dd067b3d5 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -27,9 +27,9 @@ pub enum GridNotification { Unknown = 0, GridDidCreateBlock = 11, - BlockDidUpdateRow = 20, + DidUpdateRow = 20, GridDidUpdateCells = 30, - GridDidUpdateFields = 40, + DidUpdateFields = 40, } impl ::protobuf::ProtobufEnum for GridNotification { @@ -41,9 +41,9 @@ impl ::protobuf::ProtobufEnum for GridNotification { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), 11 => ::std::option::Option::Some(GridNotification::GridDidCreateBlock), - 20 => ::std::option::Option::Some(GridNotification::BlockDidUpdateRow), + 20 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), - 40 => ::std::option::Option::Some(GridNotification::GridDidUpdateFields), + 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), _ => ::std::option::Option::None } } @@ -52,9 +52,9 @@ impl ::protobuf::ProtobufEnum for GridNotification { static values: &'static [GridNotification] = &[ GridNotification::Unknown, GridNotification::GridDidCreateBlock, - GridNotification::BlockDidUpdateRow, + GridNotification::DidUpdateRow, GridNotification::GridDidUpdateCells, - GridNotification::GridDidUpdateFields, + GridNotification::DidUpdateFields, ]; values } @@ -83,10 +83,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x7f\n\x10GridNotification\x12\x0b\n\x07Un\ - known\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x15\n\x11BlockDi\ - dUpdateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x17\n\x13\ - GridDidUpdateFields\x10(b\x06proto3\ + \n\x17dart_notification.proto*v\n\x10GridNotification\x12\x0b\n\x07Unkno\ + wn\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUpdateR\ + ow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDidUpdat\ + eFields\x10(b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/date_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/date_type_option.rs similarity index 87% rename from frontend/rust-lib/flowy-grid/src/protobuf/model/date_description.rs rename to frontend/rust-lib/flowy-grid/src/protobuf/model/date_type_option.rs index 05b2bc6a0f..5287fa32d6 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/date_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/date_type_option.rs @@ -17,14 +17,14 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `date_description.proto` +//! Generated file from `date_type_option.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct DateDescription { +pub struct DateTypeOption { // message fields pub date_format: DateFormat, pub time_format: TimeFormat, @@ -33,14 +33,14 @@ pub struct DateDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a DateDescription { - fn default() -> &'a DateDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a DateTypeOption { + fn default() -> &'a DateTypeOption { + ::default_instance() } } -impl DateDescription { - pub fn new() -> DateDescription { +impl DateTypeOption { + pub fn new() -> DateTypeOption { ::std::default::Default::default() } @@ -75,7 +75,7 @@ impl DateDescription { } } -impl ::protobuf::Message for DateDescription { +impl ::protobuf::Message for DateTypeOption { fn is_initialized(&self) -> bool { true } @@ -150,8 +150,8 @@ impl ::protobuf::Message for DateDescription { Self::descriptor_static() } - fn new() -> DateDescription { - DateDescription::new() + fn new() -> DateTypeOption { + DateTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -160,29 +160,29 @@ impl ::protobuf::Message for DateDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "date_format", - |m: &DateDescription| { &m.date_format }, - |m: &mut DateDescription| { &mut m.date_format }, + |m: &DateTypeOption| { &m.date_format }, + |m: &mut DateTypeOption| { &mut m.date_format }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "time_format", - |m: &DateDescription| { &m.time_format }, - |m: &mut DateDescription| { &mut m.time_format }, + |m: &DateTypeOption| { &m.time_format }, + |m: &mut DateTypeOption| { &mut m.time_format }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "DateDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "DateTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static DateDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(DateDescription::new) + fn default_instance() -> &'static DateTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(DateTypeOption::new) } } -impl ::protobuf::Clear for DateDescription { +impl ::protobuf::Clear for DateTypeOption { fn clear(&mut self) { self.date_format = DateFormat::Local; self.time_format = TimeFormat::TwelveHour; @@ -190,13 +190,13 @@ impl ::protobuf::Clear for DateDescription { } } -impl ::std::fmt::Debug for DateDescription { +impl ::std::fmt::Debug for DateTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for DateDescription { +impl ::protobuf::reflect::ProtobufValue for DateTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -309,9 +309,9 @@ impl ::protobuf::reflect::ProtobufValue for TimeFormat { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x16date_description.proto\"m\n\x0fDateDescription\x12,\n\x0bdate_form\ - at\x18\x01\x20\x01(\x0e2\x0b.DateFormatR\ndateFormat\x12,\n\x0btime_form\ - at\x18\x02\x20\x01(\x0e2\x0b.TimeFormatR\ntimeFormat*6\n\nDateFormat\x12\ + \n\x16date_type_option.proto\"l\n\x0eDateTypeOption\x12,\n\x0bdate_forma\ + t\x18\x01\x20\x01(\x0e2\x0b.DateFormatR\ndateFormat\x12,\n\x0btime_forma\ + t\x18\x02\x20\x01(\x0e2\x0b.TimeFormatR\ntimeFormat*6\n\nDateFormat\x12\ \t\n\x05Local\x10\0\x12\x06\n\x02US\x10\x01\x12\x07\n\x03ISO\x10\x02\x12\ \x0c\n\x08Friendly\x10\x03*0\n\nTimeFormat\x12\x0e\n\nTwelveHour\x10\0\ \x12\x12\n\x0eTwentyFourHour\x10\x01b\x06proto3\ diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 9feb87fec5..0ba8fdebc4 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -28,9 +28,11 @@ pub enum GridEvent { GetGridData = 0, GetGridBlocks = 1, GetFields = 10, - CreateRow = 11, - GetRow = 12, - UpdateCell = 20, + UpdateField = 11, + CreateField = 12, + CreateRow = 21, + GetRow = 22, + UpdateCell = 30, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -43,9 +45,11 @@ impl ::protobuf::ProtobufEnum for GridEvent { 0 => ::std::option::Option::Some(GridEvent::GetGridData), 1 => ::std::option::Option::Some(GridEvent::GetGridBlocks), 10 => ::std::option::Option::Some(GridEvent::GetFields), - 11 => ::std::option::Option::Some(GridEvent::CreateRow), - 12 => ::std::option::Option::Some(GridEvent::GetRow), - 20 => ::std::option::Option::Some(GridEvent::UpdateCell), + 11 => ::std::option::Option::Some(GridEvent::UpdateField), + 12 => ::std::option::Option::Some(GridEvent::CreateField), + 21 => ::std::option::Option::Some(GridEvent::CreateRow), + 22 => ::std::option::Option::Some(GridEvent::GetRow), + 30 => ::std::option::Option::Some(GridEvent::UpdateCell), _ => ::std::option::Option::None } } @@ -55,6 +59,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::GetGridData, GridEvent::GetGridBlocks, GridEvent::GetFields, + GridEvent::UpdateField, + GridEvent::CreateField, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, @@ -86,10 +92,11 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*i\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\0\x12\ - \x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\r\n\tCreateRo\ - w\x10\x0b\x12\n\n\x06GetRow\x10\x0c\x12\x0e\n\nUpdateCell\x10\x14b\x06pr\ - oto3\ + \n\x0fevent_map.proto*\x8b\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ + \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\r\n\tCreate\ + Row\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06\ + proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 a616a281d6..2e768a115b 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs @@ -1,8 +1,8 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit -mod date_description; -pub use date_description::*; +mod number_type_option; +pub use number_type_option::*; mod text_description; pub use text_description::*; @@ -10,14 +10,14 @@ pub use text_description::*; mod dart_notification; pub use dart_notification::*; -mod checkbox_description; -pub use checkbox_description::*; +mod selection_type_option; +pub use selection_type_option::*; -mod selection_description; -pub use selection_description::*; +mod checkbox_type_option; +pub use checkbox_type_option::*; mod event_map; pub use event_map::*; -mod number_description; -pub use number_description::*; +mod date_type_option; +pub use date_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/number_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/number_type_option.rs similarity index 88% rename from frontend/rust-lib/flowy-grid/src/protobuf/model/number_description.rs rename to frontend/rust-lib/flowy-grid/src/protobuf/model/number_type_option.rs index 2137ea2be1..8fd65bc20b 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/number_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/number_type_option.rs @@ -17,14 +17,14 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `number_description.proto` +//! Generated file from `number_type_option.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct NumberDescription { +pub struct NumberTypeOption { // message fields pub format: NumberFormat, pub scale: u32, @@ -36,14 +36,14 @@ pub struct NumberDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a NumberDescription { - fn default() -> &'a NumberDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a NumberTypeOption { + fn default() -> &'a NumberTypeOption { + ::default_instance() } } -impl NumberDescription { - pub fn new() -> NumberDescription { +impl NumberTypeOption { + pub fn new() -> NumberTypeOption { ::std::default::Default::default() } @@ -145,7 +145,7 @@ impl NumberDescription { } } -impl ::protobuf::Message for NumberDescription { +impl ::protobuf::Message for NumberTypeOption { fn is_initialized(&self) -> bool { true } @@ -255,8 +255,8 @@ impl ::protobuf::Message for NumberDescription { Self::descriptor_static() } - fn new() -> NumberDescription { - NumberDescription::new() + fn new() -> NumberTypeOption { + NumberTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -265,44 +265,44 @@ impl ::protobuf::Message for NumberDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "format", - |m: &NumberDescription| { &m.format }, - |m: &mut NumberDescription| { &mut m.format }, + |m: &NumberTypeOption| { &m.format }, + |m: &mut NumberTypeOption| { &mut m.format }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>( "scale", - |m: &NumberDescription| { &m.scale }, - |m: &mut NumberDescription| { &mut m.scale }, + |m: &NumberTypeOption| { &m.scale }, + |m: &mut NumberTypeOption| { &mut m.scale }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "symbol", - |m: &NumberDescription| { &m.symbol }, - |m: &mut NumberDescription| { &mut m.symbol }, + |m: &NumberTypeOption| { &m.symbol }, + |m: &mut NumberTypeOption| { &mut m.symbol }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( "sign_positive", - |m: &NumberDescription| { &m.sign_positive }, - |m: &mut NumberDescription| { &mut m.sign_positive }, + |m: &NumberTypeOption| { &m.sign_positive }, + |m: &mut NumberTypeOption| { &mut m.sign_positive }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "name", - |m: &NumberDescription| { &m.name }, - |m: &mut NumberDescription| { &mut m.name }, + |m: &NumberTypeOption| { &m.name }, + |m: &mut NumberTypeOption| { &mut m.name }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "NumberDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "NumberTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static NumberDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(NumberDescription::new) + fn default_instance() -> &'static NumberTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(NumberTypeOption::new) } } -impl ::protobuf::Clear for NumberDescription { +impl ::protobuf::Clear for NumberTypeOption { fn clear(&mut self) { self.format = NumberFormat::Number; self.scale = 0; @@ -313,13 +313,13 @@ impl ::protobuf::Clear for NumberDescription { } } -impl ::std::fmt::Debug for NumberDescription { +impl ::std::fmt::Debug for NumberTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for NumberDescription { +impl ::protobuf::reflect::ProtobufValue for NumberTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -382,7 +382,7 @@ impl ::protobuf::reflect::ProtobufValue for NumberFormat { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x18number_description.proto\"\xa1\x01\n\x11NumberDescription\x12%\n\ + \n\x18number_type_option.proto\"\xa0\x01\n\x10NumberTypeOption\x12%\n\ \x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06format\x12\x14\n\x05\ scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\ \tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositiv\ diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs similarity index 87% rename from frontend/rust-lib/flowy-grid/src/protobuf/model/selection_description.rs rename to frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs index 9feda09402..6d12dbc81f 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs @@ -17,14 +17,14 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `selection_description.proto` +//! Generated file from `selection_type_option.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct SingleSelectDescription { +pub struct SingleSelectTypeOption { // message fields pub options: ::protobuf::RepeatedField, pub disable_color: bool, @@ -33,14 +33,14 @@ pub struct SingleSelectDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a SingleSelectDescription { - fn default() -> &'a SingleSelectDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a SingleSelectTypeOption { + fn default() -> &'a SingleSelectTypeOption { + ::default_instance() } } -impl SingleSelectDescription { - pub fn new() -> SingleSelectDescription { +impl SingleSelectTypeOption { + pub fn new() -> SingleSelectTypeOption { ::std::default::Default::default() } @@ -85,7 +85,7 @@ impl SingleSelectDescription { } } -impl ::protobuf::Message for SingleSelectDescription { +impl ::protobuf::Message for SingleSelectTypeOption { fn is_initialized(&self) -> bool { for v in &self.options { if !v.is_initialized() { @@ -172,8 +172,8 @@ impl ::protobuf::Message for SingleSelectDescription { Self::descriptor_static() } - fn new() -> SingleSelectDescription { - SingleSelectDescription::new() + fn new() -> SingleSelectTypeOption { + SingleSelectTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -182,29 +182,29 @@ impl ::protobuf::Message for SingleSelectDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "options", - |m: &SingleSelectDescription| { &m.options }, - |m: &mut SingleSelectDescription| { &mut m.options }, + |m: &SingleSelectTypeOption| { &m.options }, + |m: &mut SingleSelectTypeOption| { &mut m.options }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( "disable_color", - |m: &SingleSelectDescription| { &m.disable_color }, - |m: &mut SingleSelectDescription| { &mut m.disable_color }, + |m: &SingleSelectTypeOption| { &m.disable_color }, + |m: &mut SingleSelectTypeOption| { &mut m.disable_color }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "SingleSelectDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SingleSelectTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static SingleSelectDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(SingleSelectDescription::new) + fn default_instance() -> &'static SingleSelectTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SingleSelectTypeOption::new) } } -impl ::protobuf::Clear for SingleSelectDescription { +impl ::protobuf::Clear for SingleSelectTypeOption { fn clear(&mut self) { self.options.clear(); self.disable_color = false; @@ -212,20 +212,20 @@ impl ::protobuf::Clear for SingleSelectDescription { } } -impl ::std::fmt::Debug for SingleSelectDescription { +impl ::std::fmt::Debug for SingleSelectTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for SingleSelectDescription { +impl ::protobuf::reflect::ProtobufValue for SingleSelectTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } #[derive(PartialEq,Clone,Default)] -pub struct MultiSelectDescription { +pub struct MultiSelectTypeOption { // message fields pub options: ::protobuf::RepeatedField, pub disable_color: bool, @@ -234,14 +234,14 @@ pub struct MultiSelectDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a MultiSelectDescription { - fn default() -> &'a MultiSelectDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a MultiSelectTypeOption { + fn default() -> &'a MultiSelectTypeOption { + ::default_instance() } } -impl MultiSelectDescription { - pub fn new() -> MultiSelectDescription { +impl MultiSelectTypeOption { + pub fn new() -> MultiSelectTypeOption { ::std::default::Default::default() } @@ -286,7 +286,7 @@ impl MultiSelectDescription { } } -impl ::protobuf::Message for MultiSelectDescription { +impl ::protobuf::Message for MultiSelectTypeOption { fn is_initialized(&self) -> bool { for v in &self.options { if !v.is_initialized() { @@ -373,8 +373,8 @@ impl ::protobuf::Message for MultiSelectDescription { Self::descriptor_static() } - fn new() -> MultiSelectDescription { - MultiSelectDescription::new() + fn new() -> MultiSelectTypeOption { + MultiSelectTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -383,29 +383,29 @@ impl ::protobuf::Message for MultiSelectDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "options", - |m: &MultiSelectDescription| { &m.options }, - |m: &mut MultiSelectDescription| { &mut m.options }, + |m: &MultiSelectTypeOption| { &m.options }, + |m: &mut MultiSelectTypeOption| { &mut m.options }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( "disable_color", - |m: &MultiSelectDescription| { &m.disable_color }, - |m: &mut MultiSelectDescription| { &mut m.disable_color }, + |m: &MultiSelectTypeOption| { &m.disable_color }, + |m: &mut MultiSelectTypeOption| { &mut m.disable_color }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "MultiSelectDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "MultiSelectTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static MultiSelectDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(MultiSelectDescription::new) + fn default_instance() -> &'static MultiSelectTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(MultiSelectTypeOption::new) } } -impl ::protobuf::Clear for MultiSelectDescription { +impl ::protobuf::Clear for MultiSelectTypeOption { fn clear(&mut self) { self.options.clear(); self.disable_color = false; @@ -413,13 +413,13 @@ impl ::protobuf::Clear for MultiSelectDescription { } } -impl ::std::fmt::Debug for MultiSelectDescription { +impl ::std::fmt::Debug for MultiSelectTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for MultiSelectDescription { +impl ::protobuf::reflect::ProtobufValue for MultiSelectTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -669,12 +669,12 @@ impl ::protobuf::reflect::ProtobufValue for SelectOption { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x1bselection_description.proto\"g\n\x17SingleSelectDescription\x12'\n\ + \n\x1bselection_type_option.proto\"f\n\x16SingleSelectTypeOption\x12'\n\ \x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x12#\n\rdis\ - able_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"f\n\x16MultiSelectDesc\ - ription\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07optio\ - ns\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"H\n\x0cS\ - electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ + able_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"e\n\x15MultiSelectType\ + Option\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07option\ + s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"H\n\x0cSe\ + lectOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ \x18\x02\x20\x01(\tR\x04name\x12\x14\n\x05color\x18\x03\x20\x01(\tR\x05c\ olorb\x06proto3\ "; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs index ca2d720e14..2bedb36f63 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs @@ -24,7 +24,7 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; #[derive(PartialEq,Clone,Default)] -pub struct RichTextDescription { +pub struct RichTextTypeOption { // message fields pub format: ::std::string::String, // special fields @@ -32,14 +32,14 @@ pub struct RichTextDescription { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a RichTextDescription { - fn default() -> &'a RichTextDescription { - ::default_instance() +impl<'a> ::std::default::Default for &'a RichTextTypeOption { + fn default() -> &'a RichTextTypeOption { + ::default_instance() } } -impl RichTextDescription { - pub fn new() -> RichTextDescription { +impl RichTextTypeOption { + pub fn new() -> RichTextTypeOption { ::std::default::Default::default() } @@ -70,7 +70,7 @@ impl RichTextDescription { } } -impl ::protobuf::Message for RichTextDescription { +impl ::protobuf::Message for RichTextTypeOption { fn is_initialized(&self) -> bool { true } @@ -136,8 +136,8 @@ impl ::protobuf::Message for RichTextDescription { Self::descriptor_static() } - fn new() -> RichTextDescription { - RichTextDescription::new() + fn new() -> RichTextTypeOption { + RichTextTypeOption::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -146,45 +146,45 @@ impl ::protobuf::Message for RichTextDescription { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "format", - |m: &RichTextDescription| { &m.format }, - |m: &mut RichTextDescription| { &mut m.format }, + |m: &RichTextTypeOption| { &m.format }, + |m: &mut RichTextTypeOption| { &mut m.format }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "RichTextDescription", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "RichTextTypeOption", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static RichTextDescription { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(RichTextDescription::new) + fn default_instance() -> &'static RichTextTypeOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(RichTextTypeOption::new) } } -impl ::protobuf::Clear for RichTextDescription { +impl ::protobuf::Clear for RichTextTypeOption { fn clear(&mut self) { self.format.clear(); self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for RichTextDescription { +impl ::std::fmt::Debug for RichTextTypeOption { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for RichTextDescription { +impl ::protobuf::reflect::ProtobufValue for RichTextTypeOption { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x16text_description.proto\"-\n\x13RichTextDescription\x12\x16\n\x06fo\ - rmat\x18\x01\x20\x01(\tR\x06formatb\x06proto3\ + \n\x16text_description.proto\",\n\x12RichTextTypeOption\x12\x16\n\x06for\ + mat\x18\x01\x20\x01(\tR\x06formatb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_type_option.proto similarity index 61% rename from frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_description.proto rename to frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_type_option.proto index 7c14ebc075..df721337c7 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_description.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/checkbox_type_option.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -message CheckboxDescription { +message CheckboxTypeOption { bool is_selected = 1; } 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 index be25f80f3b..da1d193b21 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -3,7 +3,7 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; GridDidCreateBlock = 11; - BlockDidUpdateRow = 20; + DidUpdateRow = 20; GridDidUpdateCells = 30; - GridDidUpdateFields = 40; + DidUpdateFields = 40; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/date_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/date_type_option.proto similarity index 89% rename from frontend/rust-lib/flowy-grid/src/protobuf/proto/date_description.proto rename to frontend/rust-lib/flowy-grid/src/protobuf/proto/date_type_option.proto index 9fe4c4acfd..be42570348 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/date_description.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/date_type_option.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -message DateDescription { +message DateTypeOption { DateFormat date_format = 1; TimeFormat time_format = 2; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 6c39e618f5..9a2177b6f4 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -4,7 +4,9 @@ enum GridEvent { GetGridData = 0; GetGridBlocks = 1; GetFields = 10; - CreateRow = 11; - GetRow = 12; - UpdateCell = 20; + UpdateField = 11; + CreateField = 12; + CreateRow = 21; + GetRow = 22; + UpdateCell = 30; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/number_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/number_type_option.proto similarity index 88% rename from frontend/rust-lib/flowy-grid/src/protobuf/proto/number_description.proto rename to frontend/rust-lib/flowy-grid/src/protobuf/proto/number_type_option.proto index 760f6623c4..8057b0c4a6 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/number_description.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/number_type_option.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -message NumberDescription { +message NumberTypeOption { NumberFormat format = 1; uint32 scale = 2; string symbol = 3; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto similarity index 78% rename from frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_description.proto rename to frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto index 7f3ee25661..9fdfc34e9b 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_description.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto @@ -1,10 +1,10 @@ syntax = "proto3"; -message SingleSelectDescription { +message SingleSelectTypeOption { repeated SelectOption options = 1; bool disable_color = 2; } -message MultiSelectDescription { +message MultiSelectTypeOption { repeated SelectOption options = 1; bool disable_color = 2; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto index c4ee8f8de6..67cfb438ea 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -message RichTextDescription { +message RichTextTypeOption { string format = 1; } 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 4a73ccd1b1..d6289dc958 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 @@ -6,7 +6,8 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - FieldMeta, GridBlockId, GridBlockMeta, GridBlockMetaChangeset, RepeatedCell, RowMeta, RowMetaChangeset, RowOrder, + FieldMeta, GridBlockId, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, + RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{ @@ -186,9 +187,9 @@ impl GridBlockMetaEditorManager { } async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { - let block_id: GridBlockId = block_id.into(); - send_dart_notification(&self.grid_id, GridNotification::BlockDidUpdateRow) - .payload(block_id) + let block_order: GridBlockOrder = block_id.into(); + send_dart_notification(&self.grid_id, GridNotification::DidUpdateRow) + .payload(block_order) .send(); Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/builder/mod.rs b/frontend/rust-lib/flowy-grid/src/services/cell/builder/mod.rs deleted file mode 100644 index 6812d2c39d..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/cell/builder/mod.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::services::cell::*; -use crate::services::field::TypeOptionsBuilder; -use flowy_grid_data_model::entities::FieldType; - -// Text -#[derive(Default)] -pub struct RichTextTypeOptionsBuilder(RichTextDescription); - -impl TypeOptionsBuilder for RichTextTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} - -// Number -#[derive(Default)] -pub struct NumberTypeOptionsBuilder(NumberDescription); - -impl NumberTypeOptionsBuilder { - pub fn name(mut self, name: &str) -> Self { - self.0.name = name.to_string(); - self - } - - pub fn set_format(mut self, format: NumberFormat) -> Self { - self.0.set_format(format); - self - } - - pub fn scale(mut self, scale: u32) -> Self { - self.0.scale = scale; - self - } - - pub fn positive(mut self, positive: bool) -> Self { - self.0.sign_positive = positive; - self - } -} - -impl TypeOptionsBuilder for NumberTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} - -// Date -#[derive(Default)] -pub struct DateTypeOptionsBuilder(DateDescription); -impl DateTypeOptionsBuilder { - pub fn date_format(mut self, date_format: DateFormat) -> Self { - self.0.date_format = date_format; - self - } - - pub fn time_format(mut self, time_format: TimeFormat) -> Self { - self.0.time_format = time_format; - self - } -} -impl TypeOptionsBuilder for DateTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} - -// Single Select -#[derive(Default)] -pub struct SingleSelectTypeOptionsBuilder(SingleSelectDescription); - -impl SingleSelectTypeOptionsBuilder { - pub fn option(mut self, opt: SelectOption) -> Self { - self.0.options.push(opt); - self - } -} -impl TypeOptionsBuilder for SingleSelectTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} - -// Multi Select -#[derive(Default)] -pub struct MultiSelectTypeOptionsBuilder(MultiSelectDescription); - -impl MultiSelectTypeOptionsBuilder { - pub fn option(mut self, opt: SelectOption) -> Self { - self.0.options.push(opt); - self - } -} - -impl TypeOptionsBuilder for MultiSelectTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} - -// Checkbox -#[derive(Default)] -pub struct CheckboxTypeOptionsBuilder(CheckboxDescription); -impl CheckboxTypeOptionsBuilder { - pub fn set_selected(mut self, is_selected: bool) -> Self { - self.0.is_selected = is_selected; - self - } -} -impl TypeOptionsBuilder for CheckboxTypeOptionsBuilder { - fn field_type(&self) -> FieldType { - self.0.field_type() - } - - fn build(&self) -> String { - self.0.clone().into() - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/mod.rs b/frontend/rust-lib/flowy-grid/src/services/cell/description/mod.rs deleted file mode 100644 index faadd45f8c..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod checkbox_description; -mod date_description; -mod number_description; -mod selection_description; -mod text_description; - -pub use checkbox_description::*; -pub use date_description::*; -pub use number_description::*; -pub use selection_description::*; -pub use text_description::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs b/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs deleted file mode 100644 index 0c28db7789..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod builder; -mod description; - -pub use builder::*; -pub use description::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 15f5b805d9..14206f9254 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -48,7 +48,7 @@ impl FieldBuilder { assert_eq!(self.field_meta.field_type, self.type_options_builder.field_type()); let type_options = self.type_options_builder.build(); - self.field_meta.type_options = type_options; + self.field_meta.type_option = type_options; self.field_meta } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs index 50d069cf9b..61b5889e68 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs @@ -1,3 +1,5 @@ mod field_builder; +mod type_options; pub use field_builder::*; +pub use type_options::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/checkbox_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs similarity index 69% rename from frontend/rust-lib/flowy-grid/src/services/cell/description/checkbox_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 87bd7f848c..da6d057c03 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/checkbox_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,18 +1,38 @@ use crate::impl_from_and_to_type_option; +use crate::services::field::TypeOptionsBuilder; use crate::services::row::CellDataSerde; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; +#[derive(Default)] +pub struct CheckboxTypeOptionsBuilder(CheckboxTypeOption); +impl CheckboxTypeOptionsBuilder { + pub fn set_selected(mut self, is_selected: bool) -> Self { + self.0.is_selected = is_selected; + self + } +} + +impl TypeOptionsBuilder for CheckboxTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] -pub struct CheckboxDescription { +pub struct CheckboxTypeOption { #[pb(index = 1)] pub is_selected: bool, } -impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox); +impl_from_and_to_type_option!(CheckboxTypeOption, FieldType::Checkbox); -impl CellDataSerde for CheckboxDescription { +impl CellDataSerde for CheckboxTypeOption { fn deserialize_cell_data(&self, data: String) -> String { data } @@ -41,12 +61,12 @@ fn string_to_bool(bool_str: &str) -> bool { #[cfg(test)] mod tests { - use crate::services::cell::CheckboxDescription; + use crate::services::cell::CheckboxTypeOption; use crate::services::row::CellDataSerde; #[test] fn checkout_box_description_test() { - let description = CheckboxDescription::default(); + let description = CheckboxTypeOption::default(); assert_eq!(description.serialize_cell_data("true").unwrap(), "1".to_owned()); assert_eq!(description.serialize_cell_data("1").unwrap(), "1".to_owned()); assert_eq!(description.serialize_cell_data("yes").unwrap(), "1".to_owned()); diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/date_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs similarity index 87% rename from frontend/rust-lib/flowy-grid/src/services/cell/description/date_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 0ad2e3f6a9..8c8fec6a86 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/date_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -8,20 +8,21 @@ use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; +use crate::services::field::TypeOptionsBuilder; use strum_macros::EnumIter; // Date #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] -pub struct DateDescription { +pub struct DateTypeOption { #[pb(index = 1)] pub date_format: DateFormat, #[pb(index = 2)] pub time_format: TimeFormat, } -impl_from_and_to_type_option!(DateDescription, FieldType::DateTime); +impl_from_and_to_type_option!(DateTypeOption, FieldType::DateTime); -impl DateDescription { +impl DateTypeOption { #[allow(dead_code)] fn today_from_timestamp(&self, timestamp: i64) -> String { let native = chrono::NaiveDateTime::from_timestamp(timestamp, 0); @@ -38,7 +39,7 @@ impl DateDescription { } } -impl CellDataSerde for DateDescription { +impl CellDataSerde for DateTypeOption { fn deserialize_cell_data(&self, data: String) -> String { match data.parse::() { Ok(timestamp) => { @@ -61,6 +62,29 @@ impl CellDataSerde for DateDescription { } } +#[derive(Default)] +pub struct DateTypeOptionsBuilder(DateTypeOption); +impl DateTypeOptionsBuilder { + pub fn date_format(mut self, date_format: DateFormat) -> Self { + self.0.date_format = date_format; + self + } + + pub fn time_format(mut self, time_format: TimeFormat) -> Self { + self.0.time_format = time_format; + self + } +} +impl TypeOptionsBuilder for DateTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + #[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] pub enum DateFormat { Local = 0, @@ -145,13 +169,13 @@ impl std::default::Default for TimeFormat { #[cfg(test)] mod tests { - use crate::services::cell::{DateDescription, DateFormat, TimeFormat}; + use crate::services::cell::{DateFormat, DateTypeOption, TimeFormat}; use crate::services::row::CellDataSerde; use strum::IntoEnumIterator; #[test] fn date_description_date_format_test() { - let mut description = DateDescription::default(); + let mut description = DateTypeOption::default(); let _timestamp = 1647251762; for date_format in DateFormat::iter() { @@ -203,7 +227,7 @@ mod tests { #[test] fn date_description_time_format_test() { - let mut description = DateDescription::default(); + let mut description = DateTypeOption::default(); for time_format in TimeFormat::iter() { description.time_format = time_format; match time_format { @@ -234,7 +258,7 @@ mod tests { #[test] #[should_panic] fn date_description_invalid_data_test() { - let description = DateDescription::default(); + let description = DateTypeOption::default(); description.serialize_cell_data("he").unwrap(); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs new file mode 100644 index 0000000000..51d06fff19 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs @@ -0,0 +1,11 @@ +mod checkbox_type_option; +mod date_type_option; +mod number_type_option; +mod selection_type_option; +mod text_description; + +pub use checkbox_type_option::*; +pub use date_type_option::*; +pub use number_type_option::*; +pub use selection_type_option::*; +pub use text_description::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/number_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs similarity index 86% rename from frontend/rust-lib/flowy-grid/src/services/cell/description/number_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index c3468786df..64783cda2b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/number_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -9,6 +9,7 @@ use rust_decimal::Decimal; use rusty_money::iso::{Currency, CNY, EUR, USD}; use serde::{Deserialize, Serialize}; +use crate::services::field::TypeOptionsBuilder; use std::str::FromStr; use strum::IntoEnumIterator; use strum_macros::EnumIter; @@ -17,6 +18,108 @@ lazy_static! { static ref STRIP_SYMBOL: Vec = make_strip_symbol(); } +#[derive(Default)] +pub struct NumberTypeOptionsBuilder(NumberTypeOption); + +impl NumberTypeOptionsBuilder { + pub fn name(mut self, name: &str) -> Self { + self.0.name = name.to_string(); + self + } + + pub fn set_format(mut self, format: NumberFormat) -> Self { + self.0.set_format(format); + self + } + + pub fn scale(mut self, scale: u32) -> Self { + self.0.scale = scale; + self + } + + pub fn positive(mut self, positive: bool) -> Self { + self.0.sign_positive = positive; + self + } +} + +impl TypeOptionsBuilder for NumberTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + +// Number +#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)] +pub struct NumberTypeOption { + #[pb(index = 1)] + pub format: NumberFormat, + + #[pb(index = 2)] + pub scale: u32, + + #[pb(index = 3)] + pub symbol: String, + + #[pb(index = 4)] + pub sign_positive: bool, + + #[pb(index = 5)] + pub name: String, +} +impl_from_and_to_type_option!(NumberTypeOption, FieldType::Number); + +impl std::default::Default for NumberTypeOption { + fn default() -> Self { + let format = NumberFormat::default(); + let symbol = format.symbol(); + NumberTypeOption { + format, + scale: 0, + symbol, + sign_positive: true, + name: "Number".to_string(), + } + } +} + +impl NumberTypeOption { + pub fn set_format(&mut self, format: NumberFormat) { + self.format = format; + self.symbol = format.symbol(); + } + + fn decimal_from_str(&self, s: &str) -> Decimal { + let mut decimal = Decimal::from_str(s).unwrap_or_else(|_| Decimal::zero()); + match decimal.set_scale(self.scale) { + Ok(_) => {} + Err(e) => { + tracing::error!("Set decimal scale failed: {:?}", e); + } + } + decimal.set_sign_positive(self.sign_positive); + decimal + } + + fn money_from_str(&self, s: &str, currency: &'static Currency) -> String { + let decimal = self.decimal_from_str(s); + let money = rusty_money::Money::from_decimal(decimal, currency); + money.to_string() + } + + fn strip_symbol(&self, s: &str) -> String { + let mut s = String::from(s); + if !s.chars().all(char::is_numeric) { + s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string())); + } + s + } +} + #[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] pub enum NumberFormat { Number = 0, @@ -52,74 +155,7 @@ impl NumberFormat { } } -// Number -#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)] -pub struct NumberDescription { - #[pb(index = 1)] - pub format: NumberFormat, - - #[pb(index = 2)] - pub scale: u32, - - #[pb(index = 3)] - pub symbol: String, - - #[pb(index = 4)] - pub sign_positive: bool, - - #[pb(index = 5)] - pub name: String, -} -impl_from_and_to_type_option!(NumberDescription, FieldType::Number); - -impl std::default::Default for NumberDescription { - fn default() -> Self { - let format = NumberFormat::default(); - let symbol = format.symbol(); - NumberDescription { - format, - scale: 0, - symbol, - sign_positive: true, - name: "Number".to_string(), - } - } -} - -impl NumberDescription { - pub fn set_format(&mut self, format: NumberFormat) { - self.format = format; - self.symbol = format.symbol(); - } - - fn decimal_from_str(&self, s: &str) -> Decimal { - let mut decimal = Decimal::from_str(s).unwrap_or_else(|_| Decimal::zero()); - match decimal.set_scale(self.scale) { - Ok(_) => {} - Err(e) => { - tracing::error!("Set decimal scale failed: {:?}", e); - } - } - decimal.set_sign_positive(self.sign_positive); - decimal - } - - fn money_from_str(&self, s: &str, currency: &'static Currency) -> String { - let decimal = self.decimal_from_str(s); - let money = rusty_money::Money::from_decimal(decimal, currency); - money.to_string() - } - - fn strip_symbol(&self, s: &str) -> String { - let mut s = String::from(s); - if !s.chars().all(char::is_numeric) { - s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string())); - } - s - } -} - -impl CellDataSerde for NumberDescription { +impl CellDataSerde for NumberTypeOption { fn deserialize_cell_data(&self, data: String) -> String { match self.format { NumberFormat::Number => data, @@ -149,13 +185,13 @@ fn make_strip_symbol() -> Vec { #[cfg(test)] mod tests { - use crate::services::cell::{NumberDescription, NumberFormat}; + use crate::services::cell::{NumberFormat, NumberTypeOption}; use crate::services::row::CellDataSerde; use strum::IntoEnumIterator; #[test] fn number_description_test() { - let mut description = NumberDescription::default(); + let mut description = NumberTypeOption::default(); assert_eq!(description.serialize_cell_data("Â¥18,443").unwrap(), "18443".to_owned()); assert_eq!(description.serialize_cell_data("$18,443").unwrap(), "18443".to_owned()); assert_eq!(description.serialize_cell_data("€18.443").unwrap(), "18443".to_owned()); @@ -193,7 +229,7 @@ mod tests { #[test] fn number_description_scale_test() { - let mut description = NumberDescription { + let mut description = NumberTypeOption { scale: 1, ..Default::default() }; @@ -231,7 +267,7 @@ mod tests { #[test] fn number_description_sign_test() { - let mut description = NumberDescription { + let mut description = NumberTypeOption { sign_positive: false, ..Default::default() }; diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/selection_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs similarity index 71% rename from frontend/rust-lib/flowy-grid/src/services/cell/description/selection_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 75a2d9feb2..af5e58119f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/selection_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,4 +1,5 @@ use crate::impl_from_and_to_type_option; +use crate::services::field::TypeOptionsBuilder; use crate::services::row::CellDataSerde; use crate::services::util::*; use flowy_derive::ProtoBuf; @@ -12,16 +13,16 @@ pub const SELECTION_IDS_SEPARATOR: &str = ","; // Single select #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] -pub struct SingleSelectDescription { +pub struct SingleSelectTypeOption { #[pb(index = 1)] pub options: Vec, #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect); +impl_from_and_to_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); -impl CellDataSerde for SingleSelectDescription { +impl CellDataSerde for SingleSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { data } @@ -31,17 +32,36 @@ impl CellDataSerde for SingleSelectDescription { } } +#[derive(Default)] +pub struct SingleSelectTypeOptionsBuilder(SingleSelectTypeOption); + +impl SingleSelectTypeOptionsBuilder { + pub fn option(mut self, opt: SelectOption) -> Self { + self.0.options.push(opt); + self + } +} +impl TypeOptionsBuilder for SingleSelectTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + // Multiple select #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] -pub struct MultiSelectDescription { +pub struct MultiSelectTypeOption { #[pb(index = 1)] pub options: Vec, #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect); -impl CellDataSerde for MultiSelectDescription { +impl_from_and_to_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl CellDataSerde for MultiSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { data } @@ -51,6 +71,25 @@ impl CellDataSerde for MultiSelectDescription { } } +#[derive(Default)] +pub struct MultiSelectTypeOptionsBuilder(MultiSelectTypeOption); +impl MultiSelectTypeOptionsBuilder { + pub fn option(mut self, opt: SelectOption) -> Self { + self.0.options.push(opt); + self + } +} + +impl TypeOptionsBuilder for MultiSelectTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + fn single_select_option_id_from_data(data: String) -> FlowyResult { let select_option_ids = select_option_ids(data)?; if select_option_ids.is_empty() { @@ -112,13 +151,13 @@ impl SelectOption { #[cfg(test)] mod tests { - use crate::services::cell::{MultiSelectDescription, SingleSelectDescription}; + use crate::services::cell::{MultiSelectDescription, SingleSelectTypeOption}; use crate::services::row::CellDataSerde; #[test] #[should_panic] fn selection_description_test() { - let description = SingleSelectDescription::default(); + let description = SingleSelectTypeOption::default(); assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1".to_owned()); let description = MultiSelectDescription::default(); diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/description/text_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs similarity index 60% rename from frontend/rust-lib/flowy-grid/src/services/cell/description/text_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs index 539b82402c..9b6b988fc0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/description/text_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs @@ -1,19 +1,33 @@ use crate::impl_from_and_to_type_option; use crate::services::row::CellDataSerde; +use crate::services::field::TypeOptionsBuilder; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; +#[derive(Default)] +pub struct RichTextTypeOptionsBuilder(RichTextTypeOption); + +impl TypeOptionsBuilder for RichTextTypeOptionsBuilder { + fn field_type(&self) -> FieldType { + self.0.field_type() + } + + fn build(&self) -> String { + self.0.clone().into() + } +} + #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] -pub struct RichTextDescription { +pub struct RichTextTypeOption { #[pb(index = 1)] pub format: String, } -impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText); +impl_from_and_to_type_option!(RichTextTypeOption, FieldType::RichText); -impl CellDataSerde for RichTextDescription { +impl CellDataSerde for RichTextTypeOption { fn deserialize_cell_data(&self, data: String) -> String { data } 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 7bcbe39830..80768c5251 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -16,6 +16,7 @@ use crate::services::row::{ make_grid_block_from_block_metas, make_grid_blocks, make_row_meta_from_context, make_rows_from_row_metas, serialize_cell_data, CreateRowMetaBuilder, CreateRowMetaPayload, GridBlockMetaData, }; +use flowy_grid_data_model::parser::CreateFieldParams; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; @@ -54,23 +55,25 @@ impl ClientGridEditor { })) } - pub async fn create_field(&self, field_meta: FieldMeta) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.create_field(field_meta)?)).await?; + pub async fn create_field(&self, params: CreateFieldParams) -> FlowyResult<()> { + let _ = self.modify(|grid| Ok(grid.create_field(params)?)).await?; let _ = self.notify_did_update_fields().await?; Ok(()) } - pub async fn contain_field(&self, field_meta: &FieldMeta) -> bool { - self.pad.read().await.contain_field(&field_meta.id) + pub async fn contain_field(&self, field_id: &str) -> bool { + self.pad.read().await.contain_field(field_id) } pub async fn update_field(&self, change: FieldChangeset) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.update_field(change)?)).await?; + let _ = self.notify_did_update_fields().await?; Ok(()) } pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?; + let _ = self.notify_did_update_fields().await?; Ok(()) } @@ -293,7 +296,7 @@ impl ClientGridEditor { 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) + send_dart_notification(&self.grid_id, GridNotification::DidUpdateFields) .payload(repeated_field) .send(); Ok(()) diff --git a/frontend/rust-lib/flowy-grid/src/services/mod.rs b/frontend/rust-lib/flowy-grid/src/services/mod.rs index f8b0422685..d3eb2d2857 100644 --- a/frontend/rust-lib/flowy-grid/src/services/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/mod.rs @@ -1,7 +1,6 @@ mod util; pub mod block_meta_editor; -pub mod cell; pub mod field; pub mod grid_editor; pub mod kv_persistence; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs index 148b5254ba..3d1c1939d7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs @@ -1,4 +1,4 @@ -use crate::services::cell::*; +use crate::services::field::*; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; @@ -10,23 +10,23 @@ pub trait CellDataSerde { #[allow(dead_code)] pub fn serialize_cell_data(data: &str, field: &FieldMeta) -> Result { match field.field_type { - FieldType::RichText => RichTextDescription::from(field).serialize_cell_data(data), - FieldType::Number => NumberDescription::from(field).serialize_cell_data(data), - FieldType::DateTime => DateDescription::from(field).serialize_cell_data(data), - FieldType::SingleSelect => SingleSelectDescription::from(field).serialize_cell_data(data), - FieldType::MultiSelect => MultiSelectDescription::from(field).serialize_cell_data(data), - FieldType::Checkbox => CheckboxDescription::from(field).serialize_cell_data(data), + FieldType::RichText => RichTextTypeOption::from(field).serialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field).serialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field).serialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field).serialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field).serialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field).serialize_cell_data(data), } } pub fn deserialize_cell_data(data: String, field: &FieldMeta) -> Result { let s = match field.field_type { - FieldType::RichText => RichTextDescription::from(field).deserialize_cell_data(data), - FieldType::Number => NumberDescription::from(field).deserialize_cell_data(data), - FieldType::DateTime => DateDescription::from(field).deserialize_cell_data(data), - FieldType::SingleSelect => SingleSelectDescription::from(field).deserialize_cell_data(data), - FieldType::MultiSelect => MultiSelectDescription::from(field).deserialize_cell_data(data), - FieldType::Checkbox => CheckboxDescription::from(field).deserialize_cell_data(data), + FieldType::RichText => RichTextTypeOption::from(field).deserialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field).deserialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field).deserialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field).deserialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field).deserialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field).deserialize_cell_data(data), }; Ok(s) } diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 1c10eb1726..9349854433 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -1,4 +1,3 @@ -use crate::services::cell::*; use crate::services::field::*; use flowy_grid_data_model::entities::{BuildGridContext, FieldType}; use flowy_sync::client_grid::GridBuilder; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index abc00d5fb2..803c2409a9 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -1,7 +1,9 @@ use crate::grid::script::EditorScript::*; use crate::grid::script::*; use chrono::NaiveDateTime; -use flowy_grid::services::cell::*; +use flowy_grid::services::field::{ + MultiSelectTypeOption, SelectOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, +}; use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataSerde, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ CellMetaChangeset, FieldChangeset, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, @@ -10,23 +12,22 @@ use flowy_grid_data_model::entities::{ #[tokio::test] async fn grid_create_field() { let mut test = GridEditorTest::new().await; - let text_field = create_text_field(); - let single_select_field = create_single_select_field(); - + let (text_field_params, text_field_meta) = create_text_field(&test.grid_id); + let (single_select_params, single_select_field) = create_single_select_field(&test.grid_id); let scripts = vec![ CreateField { - field_meta: text_field.clone(), + params: text_field_params, }, AssertFieldEqual { field_index: test.field_count, - field_meta: text_field, + field_meta: text_field_meta, }, ]; test.run_scripts(scripts).await; let scripts = vec![ CreateField { - field_meta: single_select_field.clone(), + params: single_select_params, }, AssertFieldEqual { field_index: test.field_count, @@ -39,16 +40,12 @@ async fn grid_create_field() { #[tokio::test] async fn grid_create_duplicate_field() { let mut test = GridEditorTest::new().await; - let text_field = create_text_field(); + let (params, _) = create_text_field(&test.grid_id); let field_count = test.field_count; let expected_field_count = field_count + 1; let scripts = vec![ - CreateField { - field_meta: text_field.clone(), - }, - CreateField { - field_meta: text_field.clone(), - }, + CreateField { params: params.clone() }, + CreateField { params }, AssertFieldCount(expected_field_count), ]; test.run_scripts(scripts).await; @@ -57,9 +54,10 @@ async fn grid_create_duplicate_field() { #[tokio::test] async fn grid_update_field_with_empty_change() { let mut test = GridEditorTest::new().await; - let single_select_field = create_single_select_field(); + let (params, field_meta) = create_single_select_field(&test.grid_id); let changeset = FieldChangeset { - field_id: single_select_field.id.clone(), + field_id: field_meta.id.clone(), + grid_id: test.grid_id.clone(), name: None, desc: None, field_type: None, @@ -70,13 +68,11 @@ async fn grid_update_field_with_empty_change() { }; let scripts = vec![ - CreateField { - field_meta: single_select_field.clone(), - }, + CreateField { params }, UpdateField { changeset }, AssertFieldEqual { field_index: test.field_count, - field_meta: single_select_field, + field_meta, }, ]; test.run_scripts(scripts).await; @@ -85,13 +81,14 @@ async fn grid_update_field_with_empty_change() { #[tokio::test] async fn grid_update_field() { let mut test = GridEditorTest::new().await; - let single_select_field = create_single_select_field(); + let (single_select_params, single_select_field) = create_single_select_field(&test.grid_id); let mut cloned_field = single_select_field.clone(); - let mut single_select_type_options = SingleSelectDescription::from(&single_select_field); + let mut single_select_type_options = SingleSelectTypeOption::from(&single_select_field); single_select_type_options.options.push(SelectOption::new("Unknown")); let changeset = FieldChangeset { field_id: single_select_field.id.clone(), + grid_id: test.grid_id.clone(), name: None, desc: None, field_type: None, @@ -103,11 +100,11 @@ async fn grid_update_field() { cloned_field.frozen = true; cloned_field.width = 1000; - cloned_field.type_options = single_select_type_options.into(); + cloned_field.type_option = single_select_type_options.into(); let scripts = vec![ CreateField { - field_meta: single_select_field.clone(), + params: single_select_params, }, UpdateField { changeset }, AssertFieldEqual { @@ -122,11 +119,9 @@ async fn grid_update_field() { async fn grid_delete_field() { let mut test = GridEditorTest::new().await; let expected_field_count = test.field_count; - let text_field = create_text_field(); + let (text_params, text_field) = create_text_field(&test.grid_id); let scripts = vec![ - CreateField { - field_meta: text_field.clone(), - }, + CreateField { params: text_params }, DeleteField { field_meta: text_field }, AssertFieldCount(expected_field_count), ]; @@ -258,13 +253,13 @@ async fn grid_row_add_cells_test() { builder.add_cell(&field.id, data).unwrap(); } FieldType::SingleSelect => { - let description = SingleSelectDescription::from(field); + let description = SingleSelectTypeOption::from(field); let options = description.options.first().unwrap(); let data = description.serialize_cell_data(&options.id).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::MultiSelect => { - let description = MultiSelectDescription::from(field); + let description = MultiSelectTypeOption::from(field); let options = description .options .iter() @@ -387,11 +382,11 @@ async fn grid_cell_update() { FieldType::Number => "123".to_string(), FieldType::DateTime => "123".to_string(), FieldType::SingleSelect => { - let description = SingleSelectDescription::from(field_meta); + let description = SingleSelectTypeOption::from(field_meta); description.options.first().unwrap().id.clone() } FieldType::MultiSelect => { - let description = MultiSelectDescription::from(field_meta); + let description = MultiSelectTypeOption::from(field_meta); description.options.first().unwrap().id.clone() } FieldType::Checkbox => "1".to_string(), diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 0da0a911f1..fa25ef3e78 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -1,18 +1,17 @@ use bytes::Bytes; -use flowy_sync::client_grid::GridBuilder; -use std::collections::HashMap; - -use flowy_grid::services::cell::*; use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, GridBlockMetaChangeset, - RowMeta, RowMetaChangeset, RowOrder, + BuildGridContext, CellMetaChangeset, CreateFieldPayload, Field, FieldChangeset, FieldMeta, FieldType, + GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, }; +use flowy_grid_data_model::parser::CreateFieldParams; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; +use flowy_sync::client_grid::GridBuilder; use flowy_test::helper::ViewTest; use flowy_test::FlowySDKTest; +use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; use strum::EnumCount; @@ -20,7 +19,7 @@ use tokio::time::sleep; pub enum EditorScript { CreateField { - field_meta: FieldMeta, + params: CreateFieldParams, }, UpdateField { changeset: FieldChangeset, @@ -121,11 +120,12 @@ impl GridEditorTest { let _cache = rev_manager.revision_cache().await; match script { - EditorScript::CreateField { field_meta } => { - if !self.editor.contain_field(&field_meta).await { + EditorScript::CreateField { params } => { + if !self.editor.contain_field(¶ms.field.id).await { self.field_count += 1; } - self.editor.create_field(field_meta).await.unwrap(); + + self.editor.create_field(params).await.unwrap(); self.field_metas = self.editor.get_field_metas(None).await.unwrap(); assert_eq!(self.field_count, self.field_metas.len()); } @@ -134,7 +134,7 @@ impl GridEditorTest { self.field_metas = self.editor.get_field_metas(None).await.unwrap(); } EditorScript::DeleteField { field_meta } => { - if self.editor.contain_field(&field_meta).await { + if self.editor.contain_field(&field_meta.id).await { self.field_count -= 1; } @@ -247,24 +247,64 @@ async fn get_row_metas(editor: &Arc) -> Vec> { .row_metas } -pub fn create_text_field() -> FieldMeta { - FieldBuilder::new(RichTextTypeOptionsBuilder::default()) +pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { + let field_meta = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) .name("Name") .visibility(true) .field_type(FieldType::RichText) - .build() + .build(); + + let cloned_field_meta = field_meta.clone(); + + let field = Field { + id: field_meta.id, + name: field_meta.name, + desc: field_meta.desc, + field_type: field_meta.field_type, + frozen: field_meta.frozen, + visibility: field_meta.visibility, + width: field_meta.width, + }; + + let params = CreateFieldParams { + grid_id: grid_id.to_owned(), + field, + type_option_data: field_meta.type_option.as_bytes().to_vec(), + start_field_id: None, + }; + (params, cloned_field_meta) } -pub fn create_single_select_field() -> FieldMeta { +pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { let single_select = SingleSelectTypeOptionsBuilder::default() .option(SelectOption::new("Done")) .option(SelectOption::new("Progress")); - FieldBuilder::new(single_select) + let field_meta = FieldBuilder::new(single_select) .name("Name") .visibility(true) .field_type(FieldType::SingleSelect) - .build() + .build(); + + let cloned_field_meta = field_meta.clone(); + + let field = Field { + id: field_meta.id, + name: field_meta.name, + desc: field_meta.desc, + field_type: field_meta.field_type, + frozen: field_meta.frozen, + visibility: field_meta.visibility, + width: field_meta.width, + }; + + let params = CreateFieldParams { + grid_id: grid_id.to_owned(), + field, + type_option_data: field_meta.type_option.as_bytes().to_vec(), + start_field_id: None, + }; + (params, cloned_field_meta) } fn make_template_1_grid() -> BuildGridContext { diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index bccc0fefd9..d3e5f2e909 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -88,14 +88,20 @@ pub enum ErrorCode { UserNotExist = 312, #[display(fmt = "Text is too long")] TextTooLong = 400, - #[display(fmt = "Grid block id is empty")] - BlockIdIsEmpty = 401, - #[display(fmt = "Row id is empty")] - RowIdIsEmpty = 402, + #[display(fmt = "Grid id is empty")] - GridIdIsEmpty = 403, + GridIdIsEmpty = 410, + #[display(fmt = "Grid block id is empty")] + BlockIdIsEmpty = 420, + #[display(fmt = "Row id is empty")] + RowIdIsEmpty = 430, + #[display(fmt = "Field id is empty")] + FieldIdIsEmpty = 440, + #[display(fmt = "Field's type option should not be empty")] + TypeOptionIsEmpty = 441, + #[display(fmt = "Invalid data")] - InvalidData = 404, + InvalidData = 500, } impl ErrorCode { diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs index 63a645ea6c..ffe8d5e0bc 100644 --- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -57,10 +57,12 @@ pub enum ErrorCode { UserIdInvalid = 311, UserNotExist = 312, TextTooLong = 400, - BlockIdIsEmpty = 401, - RowIdIsEmpty = 402, - GridIdIsEmpty = 403, - InvalidData = 404, + GridIdIsEmpty = 410, + BlockIdIsEmpty = 420, + RowIdIsEmpty = 430, + FieldIdIsEmpty = 440, + TypeOptionIsEmpty = 441, + InvalidData = 500, } impl ::protobuf::ProtobufEnum for ErrorCode { @@ -102,10 +104,12 @@ impl ::protobuf::ProtobufEnum for ErrorCode { 311 => ::std::option::Option::Some(ErrorCode::UserIdInvalid), 312 => ::std::option::Option::Some(ErrorCode::UserNotExist), 400 => ::std::option::Option::Some(ErrorCode::TextTooLong), - 401 => ::std::option::Option::Some(ErrorCode::BlockIdIsEmpty), - 402 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty), - 403 => ::std::option::Option::Some(ErrorCode::GridIdIsEmpty), - 404 => ::std::option::Option::Some(ErrorCode::InvalidData), + 410 => ::std::option::Option::Some(ErrorCode::GridIdIsEmpty), + 420 => ::std::option::Option::Some(ErrorCode::BlockIdIsEmpty), + 430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty), + 440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty), + 441 => ::std::option::Option::Some(ErrorCode::TypeOptionIsEmpty), + 500 => ::std::option::Option::Some(ErrorCode::InvalidData), _ => ::std::option::Option::None } } @@ -144,9 +148,11 @@ impl ::protobuf::ProtobufEnum for ErrorCode { ErrorCode::UserIdInvalid, ErrorCode::UserNotExist, ErrorCode::TextTooLong, + ErrorCode::GridIdIsEmpty, ErrorCode::BlockIdIsEmpty, ErrorCode::RowIdIsEmpty, - ErrorCode::GridIdIsEmpty, + ErrorCode::FieldIdIsEmpty, + ErrorCode::TypeOptionIsEmpty, ErrorCode::InvalidData, ]; values @@ -176,7 +182,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ncode.proto*\xb7\x06\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\ncode.proto*\xe4\x06\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\ \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\ @@ -193,10 +199,11 @@ static file_descriptor_proto_data: &'static [u8] = b"\ swordNotMatch\x10\xb3\x02\x12\x14\n\x0fUserNameTooLong\x10\xb4\x02\x12'\ \n\"UserNameContainForbiddenCharacters\x10\xb5\x02\x12\x14\n\x0fUserName\ IsEmpty\x10\xb6\x02\x12\x12\n\rUserIdInvalid\x10\xb7\x02\x12\x11\n\x0cUs\ - erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x13\n\ - \x0eBlockIdIsEmpty\x10\x91\x03\x12\x11\n\x0cRowIdIsEmpty\x10\x92\x03\x12\ - \x12\n\rGridIdIsEmpty\x10\x93\x03\x12\x10\n\x0bInvalidData\x10\x94\x03b\ - \x06proto3\ + erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\ + ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\ + \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\ + \x12\x16\n\x11TypeOptionIsEmpty\x10\xb9\x03\x12\x10\n\x0bInvalidData\x10\ + \xf4\x03b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto index f8b8acb8e6..1d3d6ed94c 100644 --- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto +++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto @@ -33,8 +33,10 @@ enum ErrorCode { UserIdInvalid = 311; UserNotExist = 312; TextTooLong = 400; - BlockIdIsEmpty = 401; - RowIdIsEmpty = 402; - GridIdIsEmpty = 403; - InvalidData = 404; + GridIdIsEmpty = 410; + BlockIdIsEmpty = 420; + RowIdIsEmpty = 430; + FieldIdIsEmpty = 440; + TypeOptionIsEmpty = 441; + InvalidData = 500; } 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 e9a80c4be3..c421dcac64 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -178,6 +178,12 @@ pub struct GridBlockOrder { pub block_id: String, } +impl std::convert::From<&str> for GridBlockOrder { + fn from(s: &str) -> Self { + GridBlockOrder { block_id: s.to_owned() } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct GridBlock { #[pb(index = 1)] @@ -284,6 +290,21 @@ pub struct CreateRowPayload { pub start_row_id: Option, } +#[derive(ProtoBuf, Default)] +pub struct CreateFieldPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field: Field, + + #[pb(index = 3)] + pub type_option_data: Vec, + + #[pb(index = 4, one_of)] + pub start_field_id: Option, +} + #[derive(ProtoBuf, Default)] pub struct QueryFieldPayload { #[pb(index = 1)] diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 9ba374169c..9bfc977838 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -98,7 +98,7 @@ pub struct FieldMeta { pub width: i32, #[pb(index = 8)] - pub type_options: String, + pub type_option: String, } impl FieldMeta { @@ -111,7 +111,7 @@ impl FieldMeta { frozen: false, visibility: true, width: DEFAULT_FIELD_WIDTH, - type_options: Default::default(), + type_option: Default::default(), } } } @@ -121,25 +121,28 @@ pub struct FieldChangeset { #[pb(index = 1)] pub field_id: String, - #[pb(index = 2, one_of)] - pub name: Option, + #[pb(index = 2)] + pub grid_id: String, #[pb(index = 3, one_of)] - pub desc: Option, + pub name: Option, #[pb(index = 4, one_of)] - pub field_type: Option, + pub desc: Option, #[pb(index = 5, one_of)] - pub frozen: Option, + pub field_type: Option, #[pb(index = 6, one_of)] - pub visibility: Option, + pub frozen: Option, #[pb(index = 7, one_of)] - pub width: Option, + pub visibility: Option, #[pb(index = 8, one_of)] + pub width: Option, + + #[pb(index = 9, one_of)] pub type_options: Option, } diff --git a/shared-lib/flowy-grid-data-model/src/parser/grid.rs b/shared-lib/flowy-grid-data-model/src/parser/grid.rs deleted file mode 100644 index 49a202cf70..0000000000 --- a/shared-lib/flowy-grid-data-model/src/parser/grid.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::entities::{ - CreateRowPayload, GridBlockOrder, QueryFieldPayload, QueryGridBlocksPayload, QueryRowPayload, RepeatedFieldOrder, -}; -use crate::parser::NonEmptyId; -use flowy_error_code::ErrorCode; - -#[derive(Default)] -pub struct CreateRowParams { - pub grid_id: String, - pub start_row_id: Option, -} - -impl TryInto for CreateRowPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NonEmptyId::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(CreateRowParams { - grid_id: grid_id.0, - start_row_id: self.start_row_id, - }) - } -} - -#[derive(Default)] -pub struct QueryFieldParams { - pub grid_id: String, - pub field_orders: RepeatedFieldOrder, -} - -impl TryInto for QueryFieldPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NonEmptyId::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(QueryFieldParams { - grid_id: grid_id.0, - field_orders: self.field_orders, - }) - } -} - -#[derive(Default)] -pub struct QueryGridBlocksParams { - pub grid_id: String, - pub block_orders: Vec, -} - -impl TryInto for QueryGridBlocksPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NonEmptyId::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(QueryGridBlocksParams { - grid_id: grid_id.0, - block_orders: self.block_orders, - }) - } -} - -#[derive(Default)] -pub struct QueryRowParams { - pub grid_id: String, - pub block_id: String, - pub row_id: String, -} - -impl TryInto for QueryRowPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NonEmptyId::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let block_id = NonEmptyId::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?; - let row_id = NonEmptyId::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - - Ok(QueryRowParams { - grid_id: grid_id.0, - block_id: block_id.0, - row_id: row_id.0, - }) - } -} diff --git a/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs b/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs new file mode 100644 index 0000000000..bfcb802c22 --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs @@ -0,0 +1,116 @@ +use crate::entities::{ + CreateFieldPayload, CreateRowPayload, Field, GridBlockOrder, QueryFieldPayload, QueryGridBlocksPayload, + QueryRowPayload, RepeatedFieldOrder, +}; +use crate::parser::NotEmptyUuid; +use flowy_error_code::ErrorCode; + +#[derive(Default)] +pub struct CreateRowParams { + pub grid_id: String, + pub start_row_id: Option, +} + +impl TryInto for CreateRowPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(CreateRowParams { + grid_id: grid_id.0, + start_row_id: self.start_row_id, + }) + } +} + +#[derive(Default)] +pub struct QueryFieldParams { + pub grid_id: String, + pub field_orders: RepeatedFieldOrder, +} + +impl TryInto for QueryFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(QueryFieldParams { + grid_id: grid_id.0, + field_orders: self.field_orders, + }) + } +} + +#[derive(Default)] +pub struct QueryGridBlocksParams { + pub grid_id: String, + pub block_orders: Vec, +} + +impl TryInto for QueryGridBlocksPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(QueryGridBlocksParams { + grid_id: grid_id.0, + block_orders: self.block_orders, + }) + } +} + +#[derive(Default)] +pub struct QueryRowParams { + pub grid_id: String, + pub block_id: String, + pub row_id: String, +} + +impl TryInto for QueryRowPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + + Ok(QueryRowParams { + grid_id: grid_id.0, + block_id: block_id.0, + row_id: row_id.0, + }) + } +} + +#[derive(Default, Clone)] +pub struct CreateFieldParams { + pub grid_id: String, + pub field: Field, + pub type_option_data: Vec, + pub start_field_id: Option, +} + +impl TryInto for CreateFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let _ = NotEmptyUuid::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + + let start_field_id = match self.start_field_id { + None => None, + Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), + }; + + if self.type_option_data.is_empty() { + return Err(ErrorCode::TypeOptionIsEmpty); + } + + Ok(CreateFieldParams { + grid_id: grid_id.0, + field: self.field, + type_option_data: self.type_option_data, + start_field_id, + }) + } +} diff --git a/shared-lib/flowy-grid-data-model/src/parser/id.rs b/shared-lib/flowy-grid-data-model/src/parser/id.rs deleted file mode 100644 index 5dbe65cf04..0000000000 --- a/shared-lib/flowy-grid-data-model/src/parser/id.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[derive(Debug)] -pub struct NonEmptyId(pub String); - -impl NonEmptyId { - pub fn parse(s: String) -> Result { - if s.trim().is_empty() { - return Err(()); - } - - Ok(Self(s)) - } -} - -impl AsRef for NonEmptyId { - fn as_ref(&self) -> &str { - &self.0 - } -} diff --git a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs b/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs new file mode 100644 index 0000000000..f2eb8423bb --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs @@ -0,0 +1,22 @@ +use uuid::Uuid; + +#[derive(Debug)] +pub struct NotEmptyUuid(pub String); + +impl NotEmptyUuid { + pub fn parse(s: String) -> Result { + debug_assert!(Uuid::parse_str(&s).is_ok()); + + if s.trim().is_empty() { + return Err(()); + } + + Ok(Self(s)) + } +} + +impl AsRef for NotEmptyUuid { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/shared-lib/flowy-grid-data-model/src/parser/mod.rs b/shared-lib/flowy-grid-data-model/src/parser/mod.rs index ec81801043..710464f814 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/mod.rs @@ -1,5 +1,5 @@ -mod grid; -mod id; +mod grid_params; +mod id_parser; -pub use grid::*; -pub use id::*; +pub use grid_params::*; +pub use id_parser::*; 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 f947f70851..5a8dced09b 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 @@ -3401,6 +3401,346 @@ impl ::protobuf::reflect::ProtobufValue for CreateRowPayload { } } +#[derive(PartialEq,Clone,Default)] +pub struct CreateFieldPayload { + // message fields + pub grid_id: ::std::string::String, + pub field: ::protobuf::SingularPtrField, + pub type_option_data: ::std::vec::Vec, + // message oneof groups + pub one_of_start_field_id: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CreateFieldPayload { + fn default() -> &'a CreateFieldPayload { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum CreateFieldPayload_oneof_one_of_start_field_id { + start_field_id(::std::string::String), +} + +impl CreateFieldPayload { + pub fn new() -> CreateFieldPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // .Field field = 2; + + + pub fn get_field(&self) -> &Field { + self.field.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_field(&mut self) { + self.field.clear(); + } + + pub fn has_field(&self) -> bool { + self.field.is_some() + } + + // Param is passed by value, moved + pub fn set_field(&mut self, v: Field) { + self.field = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field(&mut self) -> &mut Field { + if self.field.is_none() { + self.field.set_default(); + } + self.field.as_mut().unwrap() + } + + // Take field + pub fn take_field(&mut self) -> Field { + self.field.take().unwrap_or_else(|| Field::new()) + } + + // bytes type_option_data = 3; + + + pub fn get_type_option_data(&self) -> &[u8] { + &self.type_option_data + } + pub fn clear_type_option_data(&mut self) { + self.type_option_data.clear(); + } + + // Param is passed by value, moved + pub fn set_type_option_data(&mut self, v: ::std::vec::Vec) { + self.type_option_data = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_type_option_data(&mut self) -> &mut ::std::vec::Vec { + &mut self.type_option_data + } + + // Take field + pub fn take_type_option_data(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.type_option_data, ::std::vec::Vec::new()) + } + + // string start_field_id = 4; + + + pub fn get_start_field_id(&self) -> &str { + match self.one_of_start_field_id { + ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(ref v)) => v, + _ => "", + } + } + pub fn clear_start_field_id(&mut self) { + self.one_of_start_field_id = ::std::option::Option::None; + } + + pub fn has_start_field_id(&self) -> bool { + match self.one_of_start_field_id { + ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_start_field_id(&mut self, v: ::std::string::String) { + self.one_of_start_field_id = ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_start_field_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(_)) = self.one_of_start_field_id { + } else { + self.one_of_start_field_id = ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(::std::string::String::new())); + } + match self.one_of_start_field_id { + ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_start_field_id(&mut self) -> ::std::string::String { + if self.has_start_field_id() { + match self.one_of_start_field_id.take() { + ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } +} + +impl ::protobuf::Message for CreateFieldPayload { + fn is_initialized(&self) -> bool { + for v in &self.field { + 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_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.field)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.type_option_data)?; + }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_start_field_id = ::std::option::Option::Some(CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(is.read_string()?)); + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if let Some(ref v) = self.field.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if !self.type_option_data.is_empty() { + my_size += ::protobuf::rt::bytes_size(3, &self.type_option_data); + } + if let ::std::option::Option::Some(ref v) = self.one_of_start_field_id { + match v { + &CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(ref v) => { + my_size += ::protobuf::rt::string_size(4, &v); + }, + }; + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if let Some(ref v) = self.field.as_ref() { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if !self.type_option_data.is_empty() { + os.write_bytes(3, &self.type_option_data)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_start_field_id { + match v { + &CreateFieldPayload_oneof_one_of_start_field_id::start_field_id(ref v) => { + os.write_string(4, v)?; + }, + }; + } + 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() -> CreateFieldPayload { + CreateFieldPayload::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>( + "grid_id", + |m: &CreateFieldPayload| { &m.grid_id }, + |m: &mut CreateFieldPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "field", + |m: &CreateFieldPayload| { &m.field }, + |m: &mut CreateFieldPayload| { &mut m.field }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "type_option_data", + |m: &CreateFieldPayload| { &m.type_option_data }, + |m: &mut CreateFieldPayload| { &mut m.type_option_data }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "start_field_id", + CreateFieldPayload::has_start_field_id, + CreateFieldPayload::get_start_field_id, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateFieldPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CreateFieldPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateFieldPayload::new) + } +} + +impl ::protobuf::Clear for CreateFieldPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.field.clear(); + self.type_option_data.clear(); + self.one_of_start_field_id = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CreateFieldPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CreateFieldPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct QueryFieldPayload { // message fields @@ -4101,14 +4441,19 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x01(\tR\x05value\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\ - RowIdB\x15\n\x13one_of_start_row_id\"d\n\x11QueryFieldPayload\x12\x17\n\ - \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\ - \x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\ - locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\ - \x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\ - s\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ - ridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x15\n\x06\ - row_id\x18\x03\x20\x01(\tR\x05rowIdb\x06proto3\ + RowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\ + \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\ + \x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\ + \x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\ + \x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\ + \x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ + \x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\ + \x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\ + \x0f.GridBlockOrderR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\ + \x20\x01(\tR\x07blockId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\ + b\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/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index 2e27686c00..df2c87d586 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -727,7 +727,7 @@ pub struct FieldMeta { pub frozen: bool, pub visibility: bool, pub width: i32, - pub type_options: ::std::string::String, + pub type_option: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -882,30 +882,30 @@ impl FieldMeta { self.width = v; } - // string type_options = 8; + // string type_option = 8; - pub fn get_type_options(&self) -> &str { - &self.type_options + pub fn get_type_option(&self) -> &str { + &self.type_option } - pub fn clear_type_options(&mut self) { - self.type_options.clear(); + pub fn clear_type_option(&mut self) { + self.type_option.clear(); } // Param is passed by value, moved - pub fn set_type_options(&mut self, v: ::std::string::String) { - self.type_options = v; + pub fn set_type_option(&mut self, v: ::std::string::String) { + self.type_option = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_type_options(&mut self) -> &mut ::std::string::String { - &mut self.type_options + pub fn mut_type_option(&mut self) -> &mut ::std::string::String { + &mut self.type_option } // Take field - pub fn take_type_options(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.type_options, ::std::string::String::new()) + pub fn take_type_option(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.type_option, ::std::string::String::new()) } } @@ -952,7 +952,7 @@ impl ::protobuf::Message for FieldMeta { self.width = tmp; }, 8 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_options)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_option)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -987,8 +987,8 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint); } - if !self.type_options.is_empty() { - my_size += ::protobuf::rt::string_size(8, &self.type_options); + if !self.type_option.is_empty() { + my_size += ::protobuf::rt::string_size(8, &self.type_option); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1017,8 +1017,8 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { os.write_int32(7, self.width)?; } - if !self.type_options.is_empty() { - os.write_string(8, &self.type_options)?; + if !self.type_option.is_empty() { + os.write_string(8, &self.type_option)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1094,9 +1094,9 @@ impl ::protobuf::Message for FieldMeta { |m: &mut FieldMeta| { &mut m.width }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "type_options", - |m: &FieldMeta| { &m.type_options }, - |m: &mut FieldMeta| { &mut m.type_options }, + "type_option", + |m: &FieldMeta| { &m.type_option }, + |m: &mut FieldMeta| { &mut m.type_option }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "FieldMeta", @@ -1121,7 +1121,7 @@ impl ::protobuf::Clear for FieldMeta { self.frozen = false; self.visibility = false; self.width = 0; - self.type_options.clear(); + self.type_option.clear(); self.unknown_fields.clear(); } } @@ -1142,6 +1142,7 @@ impl ::protobuf::reflect::ProtobufValue for FieldMeta { pub struct FieldChangeset { // message fields pub field_id: ::std::string::String, + pub grid_id: ::std::string::String, // message oneof groups pub one_of_name: ::std::option::Option, pub one_of_desc: ::std::option::Option, @@ -1227,7 +1228,33 @@ impl FieldChangeset { ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) } - // string name = 2; + // string grid_id = 2; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string name = 3; pub fn get_name(&self) -> &str { @@ -1276,7 +1303,7 @@ impl FieldChangeset { } } - // string desc = 3; + // string desc = 4; pub fn get_desc(&self) -> &str { @@ -1325,7 +1352,7 @@ impl FieldChangeset { } } - // .FieldType field_type = 4; + // .FieldType field_type = 5; pub fn get_field_type(&self) -> FieldType { @@ -1350,7 +1377,7 @@ impl FieldChangeset { self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v)) } - // bool frozen = 5; + // bool frozen = 6; pub fn get_frozen(&self) -> bool { @@ -1375,7 +1402,7 @@ impl FieldChangeset { self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v)) } - // bool visibility = 6; + // bool visibility = 7; pub fn get_visibility(&self) -> bool { @@ -1400,7 +1427,7 @@ impl FieldChangeset { self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v)) } - // int32 width = 7; + // int32 width = 8; pub fn get_width(&self) -> i32 { @@ -1425,7 +1452,7 @@ impl FieldChangeset { self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v)) } - // string type_options = 8; + // string type_options = 9; pub fn get_type_options(&self) -> &str { @@ -1488,42 +1515,45 @@ impl ::protobuf::Message for FieldChangeset { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; }, 2 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(is.read_string()?)); + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; }, 3 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(is.read_string()?)); + self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(is.read_string()?)); }, 4 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(is.read_enum()?)); + self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(is.read_string()?)); }, 5 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(is.read_bool()?)); + self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(is.read_enum()?)); }, 6 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(is.read_bool()?)); + self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(is.read_bool()?)); }, 7 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(is.read_int32()?)); + self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(is.read_bool()?)); }, 8 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(is.read_int32()?)); + }, + 9 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } @@ -1544,24 +1574,27 @@ impl ::protobuf::Message for FieldChangeset { if !self.field_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.field_id); } + if !self.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.grid_id); + } if let ::std::option::Option::Some(ref v) = self.one_of_name { match v { &FieldChangeset_oneof_one_of_name::name(ref v) => { - my_size += ::protobuf::rt::string_size(2, &v); + my_size += ::protobuf::rt::string_size(3, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_desc { match v { &FieldChangeset_oneof_one_of_desc::desc(ref v) => { - my_size += ::protobuf::rt::string_size(3, &v); + my_size += ::protobuf::rt::string_size(4, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_field_type { match v { &FieldChangeset_oneof_one_of_field_type::field_type(v) => { - my_size += ::protobuf::rt::enum_size(4, v); + my_size += ::protobuf::rt::enum_size(5, v); }, }; } @@ -1582,14 +1615,14 @@ impl ::protobuf::Message for FieldChangeset { if let ::std::option::Option::Some(ref v) = self.one_of_width { match v { &FieldChangeset_oneof_one_of_width::width(v) => { - my_size += ::protobuf::rt::value_size(7, v, ::protobuf::wire_format::WireTypeVarint); + my_size += ::protobuf::rt::value_size(8, v, ::protobuf::wire_format::WireTypeVarint); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_type_options { match v { &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => { - my_size += ::protobuf::rt::string_size(8, &v); + my_size += ::protobuf::rt::string_size(9, &v); }, }; } @@ -1602,52 +1635,55 @@ impl ::protobuf::Message for FieldChangeset { if !self.field_id.is_empty() { os.write_string(1, &self.field_id)?; } + if !self.grid_id.is_empty() { + os.write_string(2, &self.grid_id)?; + } if let ::std::option::Option::Some(ref v) = self.one_of_name { match v { &FieldChangeset_oneof_one_of_name::name(ref v) => { - os.write_string(2, v)?; + os.write_string(3, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_desc { match v { &FieldChangeset_oneof_one_of_desc::desc(ref v) => { - os.write_string(3, v)?; + os.write_string(4, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_field_type { match v { &FieldChangeset_oneof_one_of_field_type::field_type(v) => { - os.write_enum(4, ::protobuf::ProtobufEnum::value(&v))?; + os.write_enum(5, ::protobuf::ProtobufEnum::value(&v))?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_frozen { match v { &FieldChangeset_oneof_one_of_frozen::frozen(v) => { - os.write_bool(5, v)?; + os.write_bool(6, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_visibility { match v { &FieldChangeset_oneof_one_of_visibility::visibility(v) => { - os.write_bool(6, v)?; + os.write_bool(7, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_width { match v { &FieldChangeset_oneof_one_of_width::width(v) => { - os.write_int32(7, v)?; + os.write_int32(8, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_type_options { match v { &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => { - os.write_string(8, v)?; + os.write_string(9, v)?; }, }; } @@ -1694,6 +1730,11 @@ impl ::protobuf::Message for FieldChangeset { |m: &FieldChangeset| { &m.field_id }, |m: &mut FieldChangeset| { &mut m.field_id }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "grid_id", + |m: &FieldChangeset| { &m.grid_id }, + |m: &mut FieldChangeset| { &mut m.grid_id }, + )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "name", FieldChangeset::has_name, @@ -1746,6 +1787,7 @@ impl ::protobuf::Message for FieldChangeset { impl ::protobuf::Clear for FieldChangeset { fn clear(&mut self) { self.field_id.clear(); + self.grid_id.clear(); self.one_of_name = ::std::option::Option::None; self.one_of_desc = ::std::option::Option::None; self.one_of_field_type = ::std::option::Option::None; @@ -3465,49 +3507,50 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"V\n\x12GridBlockMet\ aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\ - metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xdf\x01\n\tFieldM\ + metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xdd\x01\n\tFieldM\ eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12!\n\x0ctype_options\x18\x08\x20\x01(\tR\x0btypeOptions\"\xfd\x02\ + idth\x12\x1f\n\x0btype_option\x18\x08\x20\x01(\tR\ntypeOption\"\x96\x03\ \n\x0eFieldChangeset\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldI\ - d\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\ - \x03\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x04\x20\x01(\x0e2\n\ - .FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x05\x20\x01(\x08H\ - \x03R\x06frozen\x12\x20\n\nvisibility\x18\x06\x20\x01(\x08H\x04R\nvisibi\ - lity\x12\x16\n\x05width\x18\x07\x20\x01(\x05H\x05R\x05width\x12#\n\x0cty\ - pe_options\x18\x08\x20\x01(\tH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\ - \r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\ - \x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type\ - _options\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typ\ - eId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07Row\ - Meta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\ - \x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\ - \x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\ - \x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\ - \x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\ - \x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\ - \x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\ - \x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\ - \0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibili\ - ty\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.Ce\ - llByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\ - \x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\ - \x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one\ - _of_visibility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\t\ - R\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\ - \x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\ - \x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\ - \x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bf\ - ield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bbloc\ - k_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fb\ - lock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\rblockMetaD\ - ata*d\n\tFieldType\x12\x0c\n\x08RichText\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\ + d\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\x04name\ + \x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\ + \x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\ + \tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06frozen\x12\ + \x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\x05w\ + idth\x18\x08\x20\x01(\x05H\x05R\x05width\x12#\n\x0ctype_options\x18\t\ + \x20\x01(\tH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\r\n\x0bone_of_desc\ + B\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visi\ + bilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type_options\"8\n\x07AnyD\ + ata\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05valu\ + e\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\ + \x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07\ + blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.Cel\ + lByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05\ + R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\ + \n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\ + \x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\ + \xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\ + \x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\ + \n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_\ + field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rce\ + llByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\ + \x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05\ + value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\ + \x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\ + \x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\x11CellMetaChange\ + set\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_\ + id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\t\ + R\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bon\ + e_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bfield_metas\x18\x01\ + \x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bblock_metas\x18\x02\ + \x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fblock_meta_data\ + \x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\rblockMetaData*d\n\tField\ + Type\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08\ + DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSel\ + ect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\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 00dee86f6b..b1252fc72e 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 @@ -67,6 +67,12 @@ message CreateRowPayload { string grid_id = 1; oneof one_of_start_row_id { string start_row_id = 2; }; } +message CreateFieldPayload { + string grid_id = 1; + Field field = 2; + bytes type_option_data = 3; + oneof one_of_start_field_id { string start_field_id = 4; }; +} message QueryFieldPayload { string grid_id = 1; RepeatedFieldOrder field_orders = 2; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 24e1d22696..10b1183fea 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -22,17 +22,18 @@ message FieldMeta { bool frozen = 5; bool visibility = 6; int32 width = 7; - string type_options = 8; + string type_option = 8; } message FieldChangeset { string field_id = 1; - oneof one_of_name { string name = 2; }; - oneof one_of_desc { string desc = 3; }; - oneof one_of_field_type { FieldType field_type = 4; }; - oneof one_of_frozen { bool frozen = 5; }; - oneof one_of_visibility { bool visibility = 6; }; - oneof one_of_width { int32 width = 7; }; - oneof one_of_type_options { string type_options = 8; }; + string grid_id = 2; + oneof one_of_name { string name = 3; }; + oneof one_of_desc { string desc = 4; }; + oneof one_of_field_type { FieldType field_type = 5; }; + oneof one_of_frozen { bool frozen = 6; }; + oneof one_of_visibility { bool visibility = 7; }; + oneof one_of_width { int32 width = 8; }; + oneof one_of_type_options { string type_options = 9; }; } message AnyData { string type_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 8d4ab37b6d..372433cd34 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -5,6 +5,7 @@ use bytes::Bytes; use flowy_grid_data_model::entities::{ FieldChangeset, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, }; +use flowy_grid_data_model::parser::CreateFieldParams; use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::collections::HashMap; @@ -35,15 +36,49 @@ impl GridMetaPad { Self::from_delta(grid_delta) } - pub fn create_field(&mut self, field_meta: FieldMeta) -> CollaborateResult> { + pub fn create_field(&mut self, params: CreateFieldParams) -> CollaborateResult> { self.modify_grid(|grid| { - if grid.fields.contains(&field_meta) { - tracing::warn!("Duplicate grid field"); - Ok(None) - } else { - grid.fields.push(field_meta); - Ok(Some(())) + let CreateFieldParams { + field, + type_option_data, + start_field_id, + .. + } = params; + + if grid + .fields + .iter() + .find(|field_meta| field_meta.id == field.id) + .is_some() + { + tracing::warn!("Create grid field"); + return Ok(None); } + + let type_option = + String::from_utf8(type_option_data).map_err(|e| CollaborateError::internal().context(e))?; + + let field_meta = FieldMeta { + id: field.id, + name: field.name, + desc: field.desc, + field_type: field.field_type, + frozen: field.frozen, + visibility: field.visibility, + width: field.width, + type_option, + }; + + let insert_index = match start_field_id { + None => None, + Some(start_field_id) => grid.fields.iter().position(|field| field.id == start_field_id), + }; + + match insert_index { + None => grid.fields.push(field_meta), + Some(index) => grid.fields.insert(index, field_meta), + } + Ok(Some(())) }) } @@ -130,7 +165,7 @@ impl GridMetaPad { } if let Some(type_options) = changeset.type_options { - field.type_options = type_options; + field.type_option = type_options; is_changed = Some(()) } From 3fdf922f81585f1372b5ddb5b541d91ea14adfb2 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 24 Mar 2022 17:09:05 +0800 Subject: [PATCH 06/47] chore: config create field pannel --- .../assets/images/grid/field/checkbox.svg | 4 + .../assets/images/grid/field/checklist.svg | 4 + .../assets/images/grid/field/date.svg | 6 + .../assets/images/grid/field/multi_select.svg | 8 + .../assets/images/grid/field/number.svg | 3 + .../images/grid/field/single_select.svg | 4 + .../assets/images/grid/field/text.svg | 4 + .../app_flowy/assets/images/grid/more.svg | 3 + .../app_flowy/assets/translations/en.json | 8 +- .../lib/startup/home_deps_resolver.dart | 18 +- .../lib/workspace/application/grid/data.dart | 5 +- .../grid/field/create_field_bloc.dart | 47 ++ .../grid/field/edit_field_bloc.dart | 54 +++ .../grid/field/field_edit_bloc.dart | 58 --- .../application/grid/field/field_service.dart | 100 +++- .../grid/field/grid_header_bloc.dart | 4 +- .../application/grid/grid_listenr.dart | 4 +- .../workspace/application/grid/prelude.dart | 3 +- .../widgets/header/create_field_pannel.dart | 88 ++++ .../grid/src/widgets/header/field_editor.dart | 213 ++------ .../src/widgets/header/field_name_input.dart | 32 ++ .../widgets/header/field_operation_list.dart | 100 ++++ .../widgets/header/field_tyep_switcher.dart | 37 ++ .../src/widgets/header/field_type_list.dart | 132 +++++ .../grid/src/widgets/header/header.dart | 28 +- .../grid/src/widgets/header/header_cell.dart | 13 +- .../lib/style_widget/button.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 17 + .../lib/protobuf/flowy-grid/cell_data.pb.dart | 458 ------------------ .../protobuf/flowy-grid/cell_data.pbenum.dart | 62 --- .../protobuf/flowy-grid/cell_data.pbjson.dart | 125 ----- .../flowy-grid/checkbox_description.pb.dart | 58 --- .../checkbox_description.pbjson.dart | 20 - .../checkbox_description.pbserver.dart | 9 - .../flowy-grid/date_description.pb.dart | 76 --- .../flowy-grid/date_description.pbenum.dart | 45 -- .../flowy-grid/date_description.pbjson.dart | 45 -- .../flowy-grid/date_description.pbserver.dart | 9 - .../protobuf/flowy-grid/event_map.pbenum.dart | 2 + .../protobuf/flowy-grid/event_map.pbjson.dart | 3 +- .../flowy-grid/number_description.pb.dart | 118 ----- .../flowy-grid/number_description.pbenum.dart | 30 -- .../flowy-grid/number_description.pbjson.dart | 37 -- .../number_description.pbserver.dart | 9 - .../lib/protobuf/flowy-grid/protobuf.dart | 2 +- .../flowy-grid/selection_description.pb.dart | 196 -------- .../selection_description.pbenum.dart | 7 - .../selection_description.pbjson.dart | 44 -- .../selection_description.pbserver.dart | 9 - .../flowy-grid/text_type_option.pb.dart | 58 +++ ...enum.dart => text_type_option.pbenum.dart} | 2 +- .../flowy-grid/text_type_option.pbjson.dart | 20 + ...er.dart => text_type_option.pbserver.dart} | 4 +- .../protobuf/flowy-grid/type_options.pb.dart | 458 ------------------ .../flowy-grid/type_options.pbenum.dart | 62 --- .../flowy-grid/type_options.pbjson.dart | 125 ----- .../flowy-grid/type_options.pbserver.dart | 9 - frontend/app_flowy/pubspec.yaml | 1 + .../rust-lib/flowy-grid/src/event_handler.rs | 11 + frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../src/protobuf/model/event_map.rs | 11 +- .../flowy-grid/src/protobuf/model/mod.rs | 6 +- ...ext_description.rs => text_type_option.rs} | 4 +- .../src/protobuf/proto/event_map.proto | 1 + ...scription.proto => text_type_option.proto} | 0 .../src/services/field/field_builder.rs | 48 +- .../type_options/checkbox_type_option.rs | 8 +- .../field/type_options/date_type_option.rs | 8 +- .../src/services/field/type_options/mod.rs | 4 +- .../field/type_options/number_type_option.rs | 6 +- .../type_options/selection_type_option.rs | 16 +- ...ext_description.rs => text_type_option.rs} | 4 +- .../flowy-grid/src/services/grid_editor.rs | 35 +- frontend/rust-lib/flowy-grid/src/util.rs | 11 +- .../flowy-grid/tests/grid/grid_test.rs | 8 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 50 +- .../src/parser/grid_params.rs | 4 - .../src/client_grid/grid_meta_pad.rs | 4 +- 78 files changed, 964 insertions(+), 2381 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/field/checkbox.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/checklist.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/date.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/multi_select.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/number.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/single_select.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/text.svg create mode 100644 frontend/app_flowy/assets/images/grid/more.svg create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pb.dart rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/{checkbox_description.pbenum.dart => text_type_option.pbenum.dart} (87%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbjson.dart rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/{cell_data.pbserver.dart => text_type_option.pbserver.dart} (81%) delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbserver.dart rename frontend/rust-lib/flowy-grid/src/protobuf/model/{text_description.rs => text_type_option.rs} (98%) rename frontend/rust-lib/flowy-grid/src/protobuf/proto/{text_description.proto => text_type_option.proto} (100%) rename frontend/rust-lib/flowy-grid/src/services/field/type_options/{text_description.rs => text_type_option.rs} (90%) diff --git a/frontend/app_flowy/assets/images/grid/field/checkbox.svg b/frontend/app_flowy/assets/images/grid/field/checkbox.svg new file mode 100644 index 0000000000..37f52c47ed --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/checkbox.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/field/checklist.svg b/frontend/app_flowy/assets/images/grid/field/checklist.svg new file mode 100644 index 0000000000..3a88d236a1 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/checklist.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/field/date.svg b/frontend/app_flowy/assets/images/grid/field/date.svg new file mode 100644 index 0000000000..78243f1e75 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/date.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/app_flowy/assets/images/grid/field/multi_select.svg b/frontend/app_flowy/assets/images/grid/field/multi_select.svg new file mode 100644 index 0000000000..97a2e9c434 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/multi_select.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/frontend/app_flowy/assets/images/grid/field/number.svg b/frontend/app_flowy/assets/images/grid/field/number.svg new file mode 100644 index 0000000000..9d8b98d10d --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/number.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/images/grid/field/single_select.svg b/frontend/app_flowy/assets/images/grid/field/single_select.svg new file mode 100644 index 0000000000..8ccbc9a2e3 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/single_select.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/field/text.svg b/frontend/app_flowy/assets/images/grid/field/text.svg new file mode 100644 index 0000000000..7befa5080f --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/text.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/more.svg b/frontend/app_flowy/assets/images/grid/more.svg new file mode 100644 index 0000000000..b191e64a10 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/more.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 27574db94e..5646cdff58 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -148,7 +148,13 @@ "insertLeft": "Insert Left", "insertRight": "Insert Right", "duplicate": "Duplicate", - "delete": "Delete" + "delete": "Delete", + "textFieldName": "Text", + "checkboxFieldName": "Number", + "dateFieldName": "Date", + "numberFieldName": "Number", + "singleSelectFieldName": "Select", + "multiSelectFieldName": "Multiselect" } } } diff --git a/frontend/app_flowy/lib/startup/home_deps_resolver.dart b/frontend/app_flowy/lib/startup/home_deps_resolver.dart index 5c4fc6267f..1702544a64 100644 --- a/frontend/app_flowy/lib/startup/home_deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/home_deps_resolver.dart @@ -103,15 +103,21 @@ class HomeDepsResolver { getIt.registerFactoryParam>( (gridId, fields) => GridHeaderBloc( - data: GridColumnData(fields: fields), - service: FieldService(), + data: GridHeaderData(gridId: gridId, fields: fields), + service: FieldService(gridId: gridId), ), ); - getIt.registerFactoryParam( - (field, _) => FieldEditBloc( - field: field, - service: FieldService(), + getIt.registerFactoryParam( + (data, _) => EditFieldBloc( + field: data.field, + service: FieldService(gridId: data.gridId), + ), + ); + + getIt.registerFactoryParam( + (gridId, _) => CreateFieldBloc( + service: FieldService(gridId: gridId), ), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/data.dart b/frontend/app_flowy/lib/workspace/application/grid/data.dart index ff1b1e3efc..7c508a6867 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/data.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/data.dart @@ -1,7 +1,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -class GridColumnData { +class GridHeaderData { + final String gridId; final List fields; - GridColumnData({required this.fields}); + GridHeaderData({required this.gridId, required this.fields}); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart new file mode 100644 index 0000000000..0d9126cd1e --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -0,0 +1,47 @@ +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; +import 'package:dartz/dartz.dart'; + +part 'create_field_bloc.freezed.dart'; + +class CreateFieldBloc extends Bloc { + final FieldService service; + + CreateFieldBloc({required this.service}) : super(CreateFieldState.initial()) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) {}, + updateName: (_UpdateName value) {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class CreateFieldEvent with _$CreateFieldEvent { + const factory CreateFieldEvent.initial() = _InitialField; + const factory CreateFieldEvent.updateName(String newName) = _UpdateName; +} + +@freezed +class CreateFieldState with _$CreateFieldState { + const factory CreateFieldState({ + required String errorText, + required Option field, + }) = _CreateFieldState; + + factory CreateFieldState.initial() => CreateFieldState( + field: none(), + errorText: '', + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart new file mode 100644 index 0000000000..0944bdd1bb --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -0,0 +1,54 @@ +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; + +part 'edit_field_bloc.freezed.dart'; + +class EditFieldBloc extends Bloc { + final FieldService service; + + EditFieldBloc({required Field field, required this.service}) : super(EditFieldState.initial(field)) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) {}, + updateFieldName: (_UpdateFieldName value) { + // + }, + hideField: (_HideField value) {}, + deleteField: (_DeleteField value) {}, + duplicateField: (_DuplicateField value) {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class EditFieldEvent with _$EditFieldEvent { + const factory EditFieldEvent.initial() = _InitialField; + const factory EditFieldEvent.updateFieldName(String name) = _UpdateFieldName; + const factory EditFieldEvent.hideField() = _HideField; + const factory EditFieldEvent.duplicateField() = _DuplicateField; + const factory EditFieldEvent.deleteField() = _DeleteField; +} + +@freezed +class EditFieldState with _$EditFieldState { + const factory EditFieldState({ + required Field field, + required String errorText, + }) = _EditFieldState; + + factory EditFieldState.initial(Field field) => EditFieldState( + field: field, + errorText: '', + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart deleted file mode 100644 index 2d4aea16da..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_edit_bloc.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; -import 'field_service.dart'; - -part 'field_edit_bloc.freezed.dart'; - -class FieldEditBloc extends Bloc { - final FieldService service; - - FieldEditBloc({required Field field, required this.service}) : super(FieldEditState.initial(field)) { - on( - (event, emit) async { - await event.map( - initial: (_InitialField value) {}, - createField: (_CreateField value) {}, - updateFieldName: (_UpdateFieldName value) { - // - }, - hideField: (_HideField value) {}, - deleteField: (_DeleteField value) {}, - insertField: (_InsertField value) {}, - duplicateField: (_DuplicateField value) {}, - ); - }, - ); - } - - @override - Future close() async { - return super.close(); - } -} - -@freezed -class FieldEditEvent with _$FieldEditEvent { - const factory FieldEditEvent.initial() = _InitialField; - const factory FieldEditEvent.createField() = _CreateField; - const factory FieldEditEvent.updateFieldName(String name) = _UpdateFieldName; - const factory FieldEditEvent.hideField() = _HideField; - const factory FieldEditEvent.duplicateField() = _DuplicateField; - const factory FieldEditEvent.insertField({required bool onLeft}) = _InsertField; - const factory FieldEditEvent.deleteField() = _DeleteField; -} - -@freezed -class FieldEditState with _$FieldEditState { - const factory FieldEditState({ - required Field field, - required String errorText, - }) = _FieldEditState; - - factory FieldEditState.initial(Field field) => FieldEditState( - field: field, - errorText: '', - ); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 48d4aa21bd..5a8032b79a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -1 +1,99 @@ -class FieldService {} +import 'dart:typed_data'; + +import 'package:dartz/dartz.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; + +class FieldService { + final String gridId; + + FieldService({required this.gridId}); + + Future> getDefaultField( + String gridId, + ) { + final payload = GridId.create()..value = gridId; + return GridEventCreateDefaultField(payload).send(); + } + + Future> createTextField( + String gridId, + Field field, + RichTextTypeOption typeOption, + String? startFieldId, + ) { + final typeOptionData = typeOption.writeToBuffer(); + return _createField(gridId, field, typeOptionData, startFieldId); + } + + Future> createSingleSelectField( + String gridId, + Field field, + SingleSelectTypeOption typeOption, + String? startFieldId, + ) { + final typeOptionData = typeOption.writeToBuffer(); + return _createField(gridId, field, typeOptionData, startFieldId); + } + + Future> createMultiSelectField( + String gridId, + Field field, + MultiSelectTypeOption typeOption, + String? startFieldId, + ) { + final typeOptionData = typeOption.writeToBuffer(); + return _createField(gridId, field, typeOptionData, startFieldId); + } + + Future> createNumberField( + String gridId, + Field field, + NumberTypeOption typeOption, + String? startFieldId, + ) { + final typeOptionData = typeOption.writeToBuffer(); + return _createField(gridId, field, typeOptionData, startFieldId); + } + + Future> createDateField( + String gridId, + Field field, + DateTypeOption typeOption, + String? startFieldId, + ) { + final typeOptionData = typeOption.writeToBuffer(); + return _createField(gridId, field, typeOptionData, startFieldId); + } + + Future> _createField( + String gridId, + Field field, + Uint8List typeOptionData, + String? startFieldId, + ) { + final payload = CreateFieldPayload.create() + ..gridId = gridId + ..field_2 = field + ..typeOptionData = typeOptionData + ..startFieldId = startFieldId ?? ""; + + return GridEventCreateField(payload).send(); + } +} + +class GridFieldData extends Equatable { + final String gridId; + final Field field; + + const GridFieldData({ + required this.gridId, + required this.field, + }); + + @override + List get props => [field.id]; +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart index f4c7459337..a5f3a8414a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -11,7 +11,7 @@ class GridHeaderBloc extends Bloc { final FieldService service; GridHeaderBloc({ - required GridColumnData data, + required GridHeaderData data, required this.service, }) : super(GridHeaderState.initial(data.fields)) { on( @@ -19,6 +19,7 @@ class GridHeaderBloc extends Bloc { await event.map( initial: (_InitialHeader value) async {}, createField: (_CreateField value) {}, + insertField: (_InsertField value) {}, ); }, ); @@ -34,6 +35,7 @@ class GridHeaderBloc extends Bloc { class GridHeaderEvent with _$GridHeaderEvent { const factory GridHeaderEvent.initial() = _InitialHeader; const factory GridHeaderEvent.createField() = _CreateField; + const factory GridHeaderEvent.insertField({required bool onLeft}) = _InsertField; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart index e0423d7757..e110491912 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart @@ -31,9 +31,9 @@ class GridListener { void _handleObservableType(GridNotification ty, Either result) { switch (ty) { - case GridNotification.DidUpdateRow: + case GridNotification.DidUpdateFields: result.fold( - (payload) => fieldsUpdateNotifier.value = left(GridBlockId.fromBuffer(payload)), + (payload) => fieldsUpdateNotifier.value = left(RepeatedField.fromBuffer(payload).items), (error) => fieldsUpdateNotifier.value = right(error), ); break; diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 3190ced75d..a1c60d7efb 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -5,7 +5,8 @@ export 'grid_service.dart'; export 'data.dart'; export 'field/field_service.dart'; export 'field/grid_header_bloc.dart'; -export 'field/field_edit_bloc.dart'; +export 'field/edit_field_bloc.dart'; +export 'field/create_field_bloc.dart'; export 'cell_bloc/text_cell_bloc.dart'; export 'cell_bloc/number_cell_bloc.dart'; export 'cell_bloc/selection_cell_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart new file mode 100644 index 0000000000..69d57782a8 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -0,0 +1,88 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/create_field_bloc.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'field_name_input.dart'; +import 'field_tyep_switcher.dart'; + +class CreateFieldPannel extends StatelessWidget { + const CreateFieldPannel({Key? key}) : super(key: key); + + static void show(BuildContext context) { + const pannel = CreateFieldPannel(); + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: pannel, + constraints: BoxConstraints.loose(const Size(300, 200)), + ), + identifier: pannel.identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomWithLeftAligned, + style: FlowyOverlayStyle(blur: false), + ); + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt()..add(const CreateFieldEvent.initial()), + child: BlocBuilder( + builder: (context, state) { + return state.field.fold( + () => const SizedBox(), + (field) => Column(children: [ + const FlowyText.medium("Edit property"), + const VSpace(10), + _FieldNameTextField(field), + const VSpace(10), + _FieldTypeSwitcher(field), + ]), + ); + }, + ), + ); + } + + String identifier() { + return toString(); + } +} + +class _FieldTypeSwitcher extends StatelessWidget { + final Field field; + const _FieldTypeSwitcher(this.field, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return FieldTypeSwitcher( + field: field, + onSelectField: _switchToFieldType, + ); + } + + void _switchToFieldType(FieldType fieldType) { + throw UnimplementedError(); + } +} + +class _FieldNameTextField extends StatelessWidget { + final Field field; + const _FieldNameTextField(this.field, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return FieldNameTextField( + name: field.name, + errorText: context.read().state.errorText, + onNameChanged: (newName) { + context.read().add(CreateFieldEvent.updateName(newName)); + }, + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index 531d83a1f3..c199553cc6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -1,52 +1,47 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; + +import 'field_name_input.dart'; +import 'field_operation_list.dart'; +import 'field_tyep_switcher.dart'; class FieldEditor extends StatelessWidget { - final Field field; - const FieldEditor({required this.field, Key? key}) : super(key: key); + final GridFieldData fieldData; + const FieldEditor({required this.fieldData, Key? key}) : super(key: key); - static void show(BuildContext context, Field field) { - final editor = FieldEditor(field: field); + static void show(BuildContext context, GridFieldData fieldData) { + final editor = FieldEditor(fieldData: fieldData); FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer(child: editor), + widget: OverlayContainer( + child: editor, + constraints: BoxConstraints.loose(const Size(300, 200)), + ), identifier: editor.identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomWithLeftAligned, - style: FlowyOverlayStyle(blur: false), ); } @override Widget build(BuildContext context) { - final theme = context.watch(); return BlocProvider( - create: (context) => getIt(param1: field)..add(const FieldEditEvent.initial()), - child: Container( - color: theme.surface, - constraints: BoxConstraints.loose(const Size(300, 200)), - child: SingleChildScrollView( - child: Column(children: [ - const FieldNameTextField(), - // FieldTypeSwitcher(), - const VSpace(10), + create: (context) => getIt(param1: fieldData)..add(const EditFieldEvent.initial()), + child: SingleChildScrollView( + child: Column( + children: [ + const _FieldNameTextField(), + const VSpace(6), + const _FieldTypeSwitcher(), + const VSpace(6), FieldOperationList( - onTap: () { - FlowyOverlay.of(context).remove(identifier()); - }, + onDismiss: () => FlowyOverlay.of(context).remove(identifier()), ), - ]), + ], ), ), ); @@ -57,152 +52,40 @@ class FieldEditor extends StatelessWidget { } } -class FieldNameTextField extends StatelessWidget { - const FieldNameTextField({Key? key}) : super(key: key); +class _FieldTypeSwitcher extends StatelessWidget { + const _FieldTypeSwitcher({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final theme = context.watch(); - return BlocBuilder( + return BlocBuilder( + builder: (context, state) { + final field = context.read().state.field; + return FieldTypeSwitcher(field: field, onSelectField: _switchToFieldType); + }, + ); + } + + void _switchToFieldType(FieldType fieldType) { + throw UnimplementedError(); + } +} + +class _FieldNameTextField extends StatelessWidget { + const _FieldNameTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( buildWhen: ((previous, current) => previous.field.name == current.field.name), builder: (context, state) { - return RoundedInputField( - height: 36, - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), - initialValue: state.field.name, - normalBorderColor: theme.shader4, - errorBorderColor: theme.red, - focusBorderColor: theme.main1, - cursorColor: theme.main1, + return FieldNameTextField( + name: state.field.name, errorText: state.errorText, - onChanged: (value) { - context.read().add(FieldEditEvent.updateFieldName(value)); + onNameChanged: (newName) { + context.read().add(EditFieldEvent.updateFieldName(newName)); }, ); }, ); } } - -class FieldTypeSwitcher extends StatelessWidget { - const FieldTypeSwitcher({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - - return FlowyButton( - text: FlowyText.medium(context.read().state.field.name, fontSize: 12), - hoverColor: theme.hover, - onTap: () {}, - leftIcon: svg("editor/details", color: theme.iconColor), - ); - } -} - -class FieldOperationList extends StatelessWidget { - final VoidCallback onTap; - const FieldOperationList({required this.onTap, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final children = FieldAction.values - .map((action) => FieldActionItem( - action: action, - onTap: onTap, - )) - .toList(); - return GridView( - // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html - shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 4.0, - mainAxisSpacing: 8, - ), - children: children, - ); - } -} - -class FieldActionItem extends StatelessWidget { - final VoidCallback onTap; - final FieldAction action; - const FieldActionItem({required this.action, required this.onTap, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return FlowyButton( - text: FlowyText.medium(action.title(), fontSize: 12), - hoverColor: theme.hover, - onTap: () { - action.run(context); - onTap(); - }, - leftIcon: svg(action.iconName(), color: theme.iconColor), - ); - } -} - -enum FieldAction { - hide, - insertLeft, - duplicate, - insertRight, - delete, -} - -extension _FieldActionExtension on FieldAction { - String iconName() { - switch (this) { - case FieldAction.hide: - return 'grid/hide'; - case FieldAction.insertLeft: - return 'grid/left'; - case FieldAction.insertRight: - return 'grid/right'; - case FieldAction.duplicate: - return 'grid/duplicate'; - case FieldAction.delete: - return 'grid/delete'; - } - } - - String title() { - switch (this) { - case FieldAction.hide: - return LocaleKeys.grid_field_hide.tr(); - case FieldAction.insertLeft: - return LocaleKeys.grid_field_insertLeft.tr(); - case FieldAction.insertRight: - return LocaleKeys.grid_field_insertRight.tr(); - case FieldAction.duplicate: - return LocaleKeys.grid_field_duplicate.tr(); - case FieldAction.delete: - return LocaleKeys.grid_field_delete.tr(); - } - } - - void run(BuildContext context) { - final bloc = context.read(); - - switch (this) { - case FieldAction.hide: - bloc.add(const FieldEditEvent.hideField()); - break; - case FieldAction.insertLeft: - bloc.add(const FieldEditEvent.insertField(onLeft: true)); - break; - case FieldAction.insertRight: - bloc.add(const FieldEditEvent.insertField(onLeft: false)); - break; - case FieldAction.duplicate: - bloc.add(const FieldEditEvent.duplicateField()); - break; - case FieldAction.delete: - bloc.add(const FieldEditEvent.deleteField()); - break; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart new file mode 100644 index 0000000000..49f0513099 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart @@ -0,0 +1,32 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class FieldNameTextField extends StatelessWidget { + final void Function(String) onNameChanged; + final String name; + final String errorText; + const FieldNameTextField({ + required this.name, + required this.errorText, + required this.onNameChanged, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return RoundedInputField( + height: 36, + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + initialValue: name, + normalBorderColor: theme.shader4, + errorBorderColor: theme.red, + focusBorderColor: theme.main1, + cursorColor: theme.main1, + errorText: errorText, + onChanged: onNameChanged, + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart new file mode 100644 index 0000000000..f803bdee58 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -0,0 +1,100 @@ +import 'package:app_flowy/workspace/application/grid/field/edit_field_bloc.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class FieldOperationList extends StatelessWidget { + final VoidCallback onDismiss; + const FieldOperationList({required this.onDismiss, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final children = FieldAction.values + .map((action) => FieldActionItem( + action: action, + onTap: onDismiss, + )) + .toList(); + return GridView( + // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html + shrinkWrap: true, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 4.0, + mainAxisSpacing: 8, + ), + children: children, + ); + } +} + +class FieldActionItem extends StatelessWidget { + final VoidCallback onTap; + final FieldAction action; + const FieldActionItem({required this.action, required this.onTap, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyButton( + text: FlowyText.medium(action.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + action.run(context); + onTap(); + }, + leftIcon: svg(action.iconName(), color: theme.iconColor), + ); + } +} + +enum FieldAction { + hide, + // insertLeft, + duplicate, + // insertRight, + delete, +} + +extension _FieldActionExtension on FieldAction { + String iconName() { + switch (this) { + case FieldAction.hide: + return 'grid/hide'; + case FieldAction.duplicate: + return 'grid/duplicate'; + case FieldAction.delete: + return 'grid/delete'; + } + } + + String title() { + switch (this) { + case FieldAction.hide: + return LocaleKeys.grid_field_hide.tr(); + case FieldAction.duplicate: + return LocaleKeys.grid_field_duplicate.tr(); + case FieldAction.delete: + return LocaleKeys.grid_field_delete.tr(); + } + } + + void run(BuildContext context) { + switch (this) { + case FieldAction.hide: + context.read().add(const EditFieldEvent.hideField()); + break; + case FieldAction.duplicate: + context.read().add(const EditFieldEvent.duplicateField()); + break; + case FieldAction.delete: + context.read().add(const EditFieldEvent.deleteField()); + break; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart new file mode 100644 index 0000000000..505715d541 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -0,0 +1,37 @@ +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +typedef SelectFieldCallback = void Function(FieldType); + +class FieldTypeSwitcher extends StatelessWidget { + final Field field; + final SelectFieldCallback onSelectField; + const FieldTypeSwitcher({ + required this.field, + required this.onSelectField, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return SizedBox( + height: 36, + child: FlowyButton( + text: FlowyText.medium(field.name, fontSize: 12), + hoverColor: theme.hover, + onTap: () => FieldTypeList.show(context, onSelectField), + leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), + rightIcon: svg("grid/more", color: theme.iconColor), + ), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart new file mode 100644 index 0000000000..aa5d22804d --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -0,0 +1,132 @@ +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +typedef SelectFieldCallback = void Function(FieldType); + +class FieldTypeList extends StatelessWidget { + final SelectFieldCallback onSelectField; + const FieldTypeList({required this.onSelectField, Key? key}) : super(key: key); + + static void show(BuildContext context, SelectFieldCallback onSelectField) { + final list = FieldTypeList(onSelectField: onSelectField); + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: list, + constraints: BoxConstraints.loose(const Size(140, 300)), + ), + identifier: list.identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.leftWithCenterAligned, + style: FlowyOverlayStyle(blur: false), + anchorOffset: const Offset(-20, 0), + ); + } + + @override + Widget build(BuildContext context) { + final cells = FieldType.values.map((fieldType) { + return FieldTypeCell( + fieldType: fieldType, + onSelectField: (fieldType) { + onSelectField(fieldType); + FlowyOverlay.of(context).remove(identifier()); + }, + ); + }).toList(); + + return ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + itemCount: cells.length, + separatorBuilder: (context, index) { + return const VSpace(10); + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ); + } + + String identifier() { + return toString(); + } +} + +class FieldTypeCell extends StatelessWidget { + final FieldType fieldType; + final SelectFieldCallback onSelectField; + const FieldTypeCell({ + required this.fieldType, + required this.onSelectField, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return SizedBox( + height: 26, + child: FlowyButton( + text: FlowyText.medium(fieldType.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () => onSelectField(fieldType), + leftIcon: svg(fieldType.iconName(), color: theme.iconColor), + ), + ); + } +} + +extension FieldTypeListExtension on FieldType { + String iconName() { + switch (this) { + case FieldType.Checkbox: + return "grid/field/checkbox"; + case FieldType.DateTime: + return "grid/field/date"; + case FieldType.MultiSelect: + return "grid/field/multi_select"; + case FieldType.Number: + return "grid/field/number"; + case FieldType.RichText: + return "grid/field/text"; + case FieldType.SingleSelect: + return "grid/field/single_select"; + default: + assert(false, "Unsupport field type"); + return "grid/field/text"; + } + } + + String title() { + switch (this) { + case FieldType.Checkbox: + return LocaleKeys.grid_field_checkboxFieldName.tr(); + case FieldType.DateTime: + return LocaleKeys.grid_field_dateFieldName.tr(); + case FieldType.MultiSelect: + return LocaleKeys.grid_field_multiSelectFieldName.tr(); + case FieldType.Number: + return LocaleKeys.grid_field_numberFieldName.tr(); + case FieldType.RichText: + return LocaleKeys.grid_field_textFieldName.tr(); + case FieldType.SingleSelect: + return LocaleKeys.grid_field_singleSelectFieldName.tr(); + default: + assert(false, "Unsupport field type"); + return LocaleKeys.grid_field_textFieldName.tr(); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index f465e43843..1b1cde2acb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -9,6 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'create_field_pannel.dart'; import 'header_cell.dart'; class GridHeaderDelegate extends SliverPersistentHeaderDelegate { @@ -46,19 +47,30 @@ class GridHeader extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return BlocProvider( - create: (context) => getIt(param1: gridId, param2: fields)..add(const GridHeaderEvent.initial()), + create: (context) { + final bloc = getIt(param1: gridId, param2: fields); + bloc.add(const GridHeaderEvent.initial()); + return bloc; + }, child: BlocBuilder( - builder: (context, state) => Container( - color: theme.surface, - child: Row( + builder: (context, state) { + final cells = state.fields.map( + (field) => HeaderCell( + GridFieldData(gridId: gridId, field: field), + ), + ); + + final row = Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const _HeaderLeading(), - ...state.fields.map((field) => HeaderCell(field)), + ...cells, const _HeaderTrailing(), ], - ), - ), + ); + + return Container(color: theme.surface, child: row); + }, ), ); } @@ -102,7 +114,7 @@ class CreateFieldButton extends StatelessWidget { return FlowyButton( text: const FlowyText.medium('New column', fontSize: 12), hoverColor: theme.hover, - onTap: () => context.read().add(const GridHeaderEvent.createField()), + onTap: () => CreateFieldPannel.show(context), leftIcon: svg("home/add"), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index 472c32d8f5..d6e0faff47 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -1,34 +1,33 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; - import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_editor.dart'; class HeaderCell extends StatelessWidget { - final Field field; - const HeaderCell(this.field, {Key? key}) : super(key: key); + final GridFieldData fieldData; + const HeaderCell(this.fieldData, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => FieldEditor.show(context, field), + onTap: () => FieldEditor.show(context, fieldData), rightIcon: svg("editor/details", color: theme.iconColor), - text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(field.name, fontSize: 12)), + text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); final borderSide = BorderSide(color: theme.shader4, width: 0.4); final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); return Container( - width: field.width.toDouble(), + width: fieldData.field.width.toDouble(), decoration: decoration, padding: GridSize.headerContentInsets, child: button, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index dee66a8f11..d74edefba4 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -26,7 +26,7 @@ class FlowyButton extends StatelessWidget { return InkWell( onTap: onTap, child: FlowyHover( - config: HoverDisplayConfig(borderRadius: Corners.s5Border, hoverColor: hoverColor), + config: HoverDisplayConfig(borderRadius: Corners.s6Border, hoverColor: hoverColor), builder: (context, onHover) => _render(), ), ); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 80b965177c..c5f7002138 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -86,6 +86,23 @@ class GridEventCreateField { } } +class GridEventCreateDefaultField { + GridId request; + GridEventCreateDefaultField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.CreateDefaultField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(Field.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateRow { CreateRowPayload request; GridEventCreateRow(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pb.dart deleted file mode 100644 index d87c9e02c7..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pb.dart +++ /dev/null @@ -1,458 +0,0 @@ -/// -// Generated code. Do not modify. -// source: cell_data.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:protobuf/protobuf.dart' as $pb; - -import 'cell_data.pbenum.dart'; - -export 'cell_data.pbenum.dart'; - -class RichTextDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextDescription', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format') - ..hasRequiredFields = false - ; - - RichTextDescription._() : super(); - factory RichTextDescription({ - $core.String? format, - }) { - final _result = create(); - if (format != null) { - _result.format = format; - } - return _result; - } - factory RichTextDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory RichTextDescription.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') - RichTextDescription clone() => RichTextDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - RichTextDescription copyWith(void Function(RichTextDescription) updates) => super.copyWith((message) => updates(message as RichTextDescription)) as RichTextDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static RichTextDescription create() => RichTextDescription._(); - RichTextDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static RichTextDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static RichTextDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get format => $_getSZ(0); - @$pb.TagNumber(1) - set format($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasFormat() => $_has(0); - @$pb.TagNumber(1) - void clearFormat() => clearField(1); -} - -class CheckboxDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxDescription', createEmptyInstance: create) - ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected') - ..hasRequiredFields = false - ; - - CheckboxDescription._() : super(); - factory CheckboxDescription({ - $core.bool? isSelected, - }) { - final _result = create(); - if (isSelected != null) { - _result.isSelected = isSelected; - } - return _result; - } - factory CheckboxDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CheckboxDescription.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') - CheckboxDescription clone() => CheckboxDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - CheckboxDescription copyWith(void Function(CheckboxDescription) updates) => super.copyWith((message) => updates(message as CheckboxDescription)) as CheckboxDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static CheckboxDescription create() => CheckboxDescription._(); - CheckboxDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static CheckboxDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CheckboxDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.bool get isSelected => $_getBF(0); - @$pb.TagNumber(1) - set isSelected($core.bool v) { $_setBool(0, v); } - @$pb.TagNumber(1) - $core.bool hasIsSelected() => $_has(0); - @$pb.TagNumber(1) - void clearIsSelected() => clearField(1); -} - -class DateDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dateFormat', $pb.PbFieldType.OE, defaultOrMaker: DateFormat.Local, valueOf: DateFormat.valueOf, enumValues: DateFormat.values) - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeFormat', $pb.PbFieldType.OE, defaultOrMaker: TimeFormat.TwelveHour, valueOf: TimeFormat.valueOf, enumValues: TimeFormat.values) - ..hasRequiredFields = false - ; - - DateDescription._() : super(); - factory DateDescription({ - DateFormat? dateFormat, - TimeFormat? timeFormat, - }) { - final _result = create(); - if (dateFormat != null) { - _result.dateFormat = dateFormat; - } - if (timeFormat != null) { - _result.timeFormat = timeFormat; - } - return _result; - } - factory DateDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DateDescription.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') - DateDescription clone() => DateDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - DateDescription copyWith(void Function(DateDescription) updates) => super.copyWith((message) => updates(message as DateDescription)) as DateDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static DateDescription create() => DateDescription._(); - DateDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static DateDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DateDescription? _defaultInstance; - - @$pb.TagNumber(1) - DateFormat get dateFormat => $_getN(0); - @$pb.TagNumber(1) - set dateFormat(DateFormat v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasDateFormat() => $_has(0); - @$pb.TagNumber(1) - void clearDateFormat() => clearField(1); - - @$pb.TagNumber(2) - TimeFormat get timeFormat => $_getN(1); - @$pb.TagNumber(2) - set timeFormat(TimeFormat v) { setField(2, v); } - @$pb.TagNumber(2) - $core.bool hasTimeFormat() => $_has(1); - @$pb.TagNumber(2) - void clearTimeFormat() => clearField(2); -} - -class SingleSelect extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelect', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - SingleSelect._() : super(); - factory SingleSelect({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory SingleSelect.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SingleSelect.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') - SingleSelect clone() => SingleSelect()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SingleSelect copyWith(void Function(SingleSelect) updates) => super.copyWith((message) => updates(message as SingleSelect)) as SingleSelect; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SingleSelect create() => SingleSelect._(); - SingleSelect createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SingleSelect getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SingleSelect? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class MultiSelect extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiSelect', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - MultiSelect._() : super(); - factory MultiSelect({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory MultiSelect.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory MultiSelect.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') - MultiSelect clone() => MultiSelect()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - MultiSelect copyWith(void Function(MultiSelect) updates) => super.copyWith((message) => updates(message as MultiSelect)) as MultiSelect; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static MultiSelect create() => MultiSelect._(); - MultiSelect createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static MultiSelect getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static MultiSelect? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class SelectOption extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', 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') ? '' : 'color') - ..hasRequiredFields = false - ; - - SelectOption._() : super(); - factory SelectOption({ - $core.String? id, - $core.String? name, - $core.String? color, - }) { - final _result = create(); - if (id != null) { - _result.id = id; - } - if (name != null) { - _result.name = name; - } - if (color != null) { - _result.color = color; - } - return _result; - } - factory SelectOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SelectOption.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') - SelectOption clone() => SelectOption()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SelectOption copyWith(void Function(SelectOption) updates) => super.copyWith((message) => updates(message as SelectOption)) as SelectOption; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SelectOption create() => SelectOption._(); - SelectOption createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SelectOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SelectOption? _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 color => $_getSZ(2); - @$pb.TagNumber(3) - set color($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasColor() => $_has(2); - @$pb.TagNumber(3) - void clearColor() => clearField(3); -} - -class NumberDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'money', $pb.PbFieldType.OE, defaultOrMaker: FlowyMoney.CNY, valueOf: FlowyMoney.valueOf, enumValues: FlowyMoney.values) - ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3) - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol') - ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive') - ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') - ..hasRequiredFields = false - ; - - NumberDescription._() : super(); - factory NumberDescription({ - FlowyMoney? money, - $core.int? scale, - $core.String? symbol, - $core.bool? signPositive, - $core.String? name, - }) { - final _result = create(); - if (money != null) { - _result.money = money; - } - if (scale != null) { - _result.scale = scale; - } - if (symbol != null) { - _result.symbol = symbol; - } - if (signPositive != null) { - _result.signPositive = signPositive; - } - if (name != null) { - _result.name = name; - } - return _result; - } - factory NumberDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NumberDescription.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') - NumberDescription clone() => NumberDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - NumberDescription copyWith(void Function(NumberDescription) updates) => super.copyWith((message) => updates(message as NumberDescription)) as NumberDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static NumberDescription create() => NumberDescription._(); - NumberDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static NumberDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static NumberDescription? _defaultInstance; - - @$pb.TagNumber(1) - FlowyMoney get money => $_getN(0); - @$pb.TagNumber(1) - set money(FlowyMoney v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasMoney() => $_has(0); - @$pb.TagNumber(1) - void clearMoney() => clearField(1); - - @$pb.TagNumber(2) - $core.int get scale => $_getIZ(1); - @$pb.TagNumber(2) - set scale($core.int v) { $_setUnsignedInt32(1, v); } - @$pb.TagNumber(2) - $core.bool hasScale() => $_has(1); - @$pb.TagNumber(2) - void clearScale() => clearField(2); - - @$pb.TagNumber(3) - $core.String get symbol => $_getSZ(2); - @$pb.TagNumber(3) - set symbol($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasSymbol() => $_has(2); - @$pb.TagNumber(3) - void clearSymbol() => clearField(3); - - @$pb.TagNumber(4) - $core.bool get signPositive => $_getBF(3); - @$pb.TagNumber(4) - set signPositive($core.bool v) { $_setBool(3, v); } - @$pb.TagNumber(4) - $core.bool hasSignPositive() => $_has(3); - @$pb.TagNumber(4) - void clearSignPositive() => clearField(4); - - @$pb.TagNumber(5) - $core.String get name => $_getSZ(4); - @$pb.TagNumber(5) - set name($core.String v) { $_setString(4, v); } - @$pb.TagNumber(5) - $core.bool hasName() => $_has(4); - @$pb.TagNumber(5) - void clearName() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbenum.dart deleted file mode 100644 index b6512aafba..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbenum.dart +++ /dev/null @@ -1,62 +0,0 @@ -/// -// Generated code. Do not modify. -// source: cell_data.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 DateFormat extends $pb.ProtobufEnum { - static const DateFormat Local = DateFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); - static const DateFormat US = DateFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'US'); - static const DateFormat ISO = DateFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ISO'); - static const DateFormat Friendly = DateFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Friendly'); - - static const $core.List values = [ - Local, - US, - ISO, - Friendly, - ]; - - static final $core.Map<$core.int, DateFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static DateFormat? valueOf($core.int value) => _byValue[value]; - - const DateFormat._($core.int v, $core.String n) : super(v, n); -} - -class TimeFormat extends $pb.ProtobufEnum { - static const TimeFormat TwelveHour = TimeFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwelveHour'); - static const TimeFormat TwentyFourHour = TimeFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwentyFourHour'); - - static const $core.List values = [ - TwelveHour, - TwentyFourHour, - ]; - - static final $core.Map<$core.int, TimeFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static TimeFormat? valueOf($core.int value) => _byValue[value]; - - const TimeFormat._($core.int v, $core.String n) : super(v, n); -} - -class FlowyMoney extends $pb.ProtobufEnum { - static const FlowyMoney CNY = FlowyMoney._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY'); - static const FlowyMoney EUR = FlowyMoney._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR'); - static const FlowyMoney USD = FlowyMoney._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD'); - - static const $core.List values = [ - CNY, - EUR, - USD, - ]; - - static final $core.Map<$core.int, FlowyMoney> _byValue = $pb.ProtobufEnum.initByValue(values); - static FlowyMoney? valueOf($core.int value) => _byValue[value]; - - const FlowyMoney._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbjson.dart deleted file mode 100644 index c2caf59394..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbjson.dart +++ /dev/null @@ -1,125 +0,0 @@ -/// -// Generated code. Do not modify. -// source: cell_data.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 dateFormatDescriptor instead') -const DateFormat$json = const { - '1': 'DateFormat', - '2': const [ - const {'1': 'Local', '2': 0}, - const {'1': 'US', '2': 1}, - const {'1': 'ISO', '2': 2}, - const {'1': 'Friendly', '2': 3}, - ], -}; - -/// Descriptor for `DateFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List dateFormatDescriptor = $convert.base64Decode('CgpEYXRlRm9ybWF0EgkKBUxvY2FsEAASBgoCVVMQARIHCgNJU08QAhIMCghGcmllbmRseRAD'); -@$core.Deprecated('Use timeFormatDescriptor instead') -const TimeFormat$json = const { - '1': 'TimeFormat', - '2': const [ - const {'1': 'TwelveHour', '2': 0}, - const {'1': 'TwentyFourHour', '2': 1}, - ], -}; - -/// Descriptor for `TimeFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List timeFormatDescriptor = $convert.base64Decode('CgpUaW1lRm9ybWF0Eg4KClR3ZWx2ZUhvdXIQABISCg5Ud2VudHlGb3VySG91chAB'); -@$core.Deprecated('Use flowyMoneyDescriptor instead') -const FlowyMoney$json = const { - '1': 'FlowyMoney', - '2': const [ - const {'1': 'CNY', '2': 0}, - const {'1': 'EUR', '2': 1}, - const {'1': 'USD', '2': 2}, - ], -}; - -/// Descriptor for `FlowyMoney`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List flowyMoneyDescriptor = $convert.base64Decode('CgpGbG93eU1vbmV5EgcKA0NOWRAAEgcKA0VVUhABEgcKA1VTRBAC'); -@$core.Deprecated('Use richTextDescriptionDescriptor instead') -const RichTextDescription$json = const { - '1': 'RichTextDescription', - '2': const [ - const {'1': 'format', '3': 1, '4': 1, '5': 9, '10': 'format'}, - ], -}; - -/// Descriptor for `RichTextDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List richTextDescriptionDescriptor = $convert.base64Decode('ChNSaWNoVGV4dERlc2NyaXB0aW9uEhYKBmZvcm1hdBgBIAEoCVIGZm9ybWF0'); -@$core.Deprecated('Use checkboxDescriptionDescriptor instead') -const CheckboxDescription$json = const { - '1': 'CheckboxDescription', - '2': const [ - const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'}, - ], -}; - -/// Descriptor for `CheckboxDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List checkboxDescriptionDescriptor = $convert.base64Decode('ChNDaGVja2JveERlc2NyaXB0aW9uEh8KC2lzX3NlbGVjdGVkGAEgASgIUgppc1NlbGVjdGVk'); -@$core.Deprecated('Use dateDescriptionDescriptor instead') -const DateDescription$json = const { - '1': 'DateDescription', - '2': const [ - const {'1': 'date_format', '3': 1, '4': 1, '5': 14, '6': '.DateFormat', '10': 'dateFormat'}, - const {'1': 'time_format', '3': 2, '4': 1, '5': 14, '6': '.TimeFormat', '10': 'timeFormat'}, - ], -}; - -/// Descriptor for `DateDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List dateDescriptionDescriptor = $convert.base64Decode('Cg9EYXRlRGVzY3JpcHRpb24SLAoLZGF0ZV9mb3JtYXQYASABKA4yCy5EYXRlRm9ybWF0UgpkYXRlRm9ybWF0EiwKC3RpbWVfZm9ybWF0GAIgASgOMgsuVGltZUZvcm1hdFIKdGltZUZvcm1hdA=='); -@$core.Deprecated('Use singleSelectDescriptor instead') -const SingleSelect$json = const { - '1': 'SingleSelect', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `SingleSelect`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List singleSelectDescriptor = $convert.base64Decode('CgxTaW5nbGVTZWxlY3QSJwoHb3B0aW9ucxgBIAMoCzINLlNlbGVjdE9wdGlvblIHb3B0aW9ucxIjCg1kaXNhYmxlX2NvbG9yGAIgASgIUgxkaXNhYmxlQ29sb3I='); -@$core.Deprecated('Use multiSelectDescriptor instead') -const MultiSelect$json = const { - '1': 'MultiSelect', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `MultiSelect`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List multiSelectDescriptor = $convert.base64Decode('CgtNdWx0aVNlbGVjdBInCgdvcHRpb25zGAEgAygLMg0uU2VsZWN0T3B0aW9uUgdvcHRpb25zEiMKDWRpc2FibGVfY29sb3IYAiABKAhSDGRpc2FibGVDb2xvcg=='); -@$core.Deprecated('Use selectOptionDescriptor instead') -const SelectOption$json = const { - '1': 'SelectOption', - '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': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'}, - ], -}; - -/// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y'); -@$core.Deprecated('Use numberDescriptionDescriptor instead') -const NumberDescription$json = const { - '1': 'NumberDescription', - '2': const [ - const {'1': 'money', '3': 1, '4': 1, '5': 14, '6': '.FlowyMoney', '10': 'money'}, - const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'}, - const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'}, - const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'}, - const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'}, - ], -}; - -/// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIhCgVtb25leRgBIAEoDjILLkZsb3d5TW9uZXlSBW1vbmV5EhQKBXNjYWxlGAIgASgNUgVzY2FsZRIWCgZzeW1ib2wYAyABKAlSBnN5bWJvbBIjCg1zaWduX3Bvc2l0aXZlGAQgASgIUgxzaWduUG9zaXRpdmUSEgoEbmFtZRgFIAEoCVIEbmFtZQ=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart deleted file mode 100644 index 04b2ae6e81..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pb.dart +++ /dev/null @@ -1,58 +0,0 @@ -/// -// Generated code. Do not modify. -// source: checkbox_description.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:protobuf/protobuf.dart' as $pb; - -class CheckboxTypeOption extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxTypeOption', createEmptyInstance: create) - ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected') - ..hasRequiredFields = false - ; - - CheckboxTypeOption._() : super(); - factory CheckboxTypeOption({ - $core.bool? isSelected, - }) { - final _result = create(); - if (isSelected != null) { - _result.isSelected = isSelected; - } - return _result; - } - factory CheckboxTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CheckboxTypeOption.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') - CheckboxTypeOption clone() => CheckboxTypeOption()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - CheckboxTypeOption copyWith(void Function(CheckboxTypeOption) updates) => super.copyWith((message) => updates(message as CheckboxTypeOption)) as CheckboxTypeOption; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static CheckboxTypeOption create() => CheckboxTypeOption._(); - CheckboxTypeOption createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static CheckboxTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CheckboxTypeOption? _defaultInstance; - - @$pb.TagNumber(1) - $core.bool get isSelected => $_getBF(0); - @$pb.TagNumber(1) - set isSelected($core.bool v) { $_setBool(0, v); } - @$pb.TagNumber(1) - $core.bool hasIsSelected() => $_has(0); - @$pb.TagNumber(1) - void clearIsSelected() => clearField(1); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart deleted file mode 100644 index 0569b0665a..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbjson.dart +++ /dev/null @@ -1,20 +0,0 @@ -/// -// Generated code. Do not modify. -// source: checkbox_description.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 checkboxTypeOptionDescriptor instead') -const CheckboxTypeOption$json = const { - '1': 'CheckboxTypeOption', - '2': const [ - const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'}, - ], -}; - -/// Descriptor for `CheckboxTypeOption`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List checkboxTypeOptionDescriptor = $convert.base64Decode('ChJDaGVja2JveFR5cGVPcHRpb24SHwoLaXNfc2VsZWN0ZWQYASABKAhSCmlzU2VsZWN0ZWQ='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbserver.dart deleted file mode 100644 index 166969b429..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: checkbox_description.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 'checkbox_description.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pb.dart deleted file mode 100644 index a70bff6f3c..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pb.dart +++ /dev/null @@ -1,76 +0,0 @@ -/// -// Generated code. Do not modify. -// source: date_description.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:protobuf/protobuf.dart' as $pb; - -import 'date_description.pbenum.dart'; - -export 'date_description.pbenum.dart'; - -class DateDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dateFormat', $pb.PbFieldType.OE, defaultOrMaker: DateFormat.Local, valueOf: DateFormat.valueOf, enumValues: DateFormat.values) - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeFormat', $pb.PbFieldType.OE, defaultOrMaker: TimeFormat.TwelveHour, valueOf: TimeFormat.valueOf, enumValues: TimeFormat.values) - ..hasRequiredFields = false - ; - - DateDescription._() : super(); - factory DateDescription({ - DateFormat? dateFormat, - TimeFormat? timeFormat, - }) { - final _result = create(); - if (dateFormat != null) { - _result.dateFormat = dateFormat; - } - if (timeFormat != null) { - _result.timeFormat = timeFormat; - } - return _result; - } - factory DateDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DateDescription.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') - DateDescription clone() => DateDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - DateDescription copyWith(void Function(DateDescription) updates) => super.copyWith((message) => updates(message as DateDescription)) as DateDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static DateDescription create() => DateDescription._(); - DateDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static DateDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DateDescription? _defaultInstance; - - @$pb.TagNumber(1) - DateFormat get dateFormat => $_getN(0); - @$pb.TagNumber(1) - set dateFormat(DateFormat v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasDateFormat() => $_has(0); - @$pb.TagNumber(1) - void clearDateFormat() => clearField(1); - - @$pb.TagNumber(2) - TimeFormat get timeFormat => $_getN(1); - @$pb.TagNumber(2) - set timeFormat(TimeFormat v) { setField(2, v); } - @$pb.TagNumber(2) - $core.bool hasTimeFormat() => $_has(1); - @$pb.TagNumber(2) - void clearTimeFormat() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbenum.dart deleted file mode 100644 index 93ea01d9be..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbenum.dart +++ /dev/null @@ -1,45 +0,0 @@ -/// -// Generated code. Do not modify. -// source: date_description.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 DateFormat extends $pb.ProtobufEnum { - static const DateFormat Local = DateFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); - static const DateFormat US = DateFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'US'); - static const DateFormat ISO = DateFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ISO'); - static const DateFormat Friendly = DateFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Friendly'); - - static const $core.List values = [ - Local, - US, - ISO, - Friendly, - ]; - - static final $core.Map<$core.int, DateFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static DateFormat? valueOf($core.int value) => _byValue[value]; - - const DateFormat._($core.int v, $core.String n) : super(v, n); -} - -class TimeFormat extends $pb.ProtobufEnum { - static const TimeFormat TwelveHour = TimeFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwelveHour'); - static const TimeFormat TwentyFourHour = TimeFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwentyFourHour'); - - static const $core.List values = [ - TwelveHour, - TwentyFourHour, - ]; - - static final $core.Map<$core.int, TimeFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static TimeFormat? valueOf($core.int value) => _byValue[value]; - - const TimeFormat._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbjson.dart deleted file mode 100644 index 841db39005..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbjson.dart +++ /dev/null @@ -1,45 +0,0 @@ -/// -// Generated code. Do not modify. -// source: date_description.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 dateFormatDescriptor instead') -const DateFormat$json = const { - '1': 'DateFormat', - '2': const [ - const {'1': 'Local', '2': 0}, - const {'1': 'US', '2': 1}, - const {'1': 'ISO', '2': 2}, - const {'1': 'Friendly', '2': 3}, - ], -}; - -/// Descriptor for `DateFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List dateFormatDescriptor = $convert.base64Decode('CgpEYXRlRm9ybWF0EgkKBUxvY2FsEAASBgoCVVMQARIHCgNJU08QAhIMCghGcmllbmRseRAD'); -@$core.Deprecated('Use timeFormatDescriptor instead') -const TimeFormat$json = const { - '1': 'TimeFormat', - '2': const [ - const {'1': 'TwelveHour', '2': 0}, - const {'1': 'TwentyFourHour', '2': 1}, - ], -}; - -/// Descriptor for `TimeFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List timeFormatDescriptor = $convert.base64Decode('CgpUaW1lRm9ybWF0Eg4KClR3ZWx2ZUhvdXIQABISCg5Ud2VudHlGb3VySG91chAB'); -@$core.Deprecated('Use dateDescriptionDescriptor instead') -const DateDescription$json = const { - '1': 'DateDescription', - '2': const [ - const {'1': 'date_format', '3': 1, '4': 1, '5': 14, '6': '.DateFormat', '10': 'dateFormat'}, - const {'1': 'time_format', '3': 2, '4': 1, '5': 14, '6': '.TimeFormat', '10': 'timeFormat'}, - ], -}; - -/// Descriptor for `DateDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List dateDescriptionDescriptor = $convert.base64Decode('Cg9EYXRlRGVzY3JpcHRpb24SLAoLZGF0ZV9mb3JtYXQYASABKA4yCy5EYXRlRm9ybWF0UgpkYXRlRm9ybWF0EiwKC3RpbWVfZm9ybWF0GAIgASgOMgsuVGltZUZvcm1hdFIKdGltZUZvcm1hdA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbserver.dart deleted file mode 100644 index dd4ff2c3c7..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_description.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: date_description.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 'date_description.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 4488ba1a3d..7007f1f6c8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -15,6 +15,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields'); static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); + static const GridEvent CreateDefaultField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultField'); static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); @@ -25,6 +26,7 @@ class GridEvent extends $pb.ProtobufEnum { GetFields, UpdateField, CreateField, + CreateDefaultField, CreateRow, GetRow, UpdateCell, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index c70007eaaa..1d94f8227a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -17,6 +17,7 @@ const GridEvent$json = const { const {'1': 'GetFields', '2': 10}, const {'1': 'UpdateField', '2': 11}, const {'1': 'CreateField', '2': 12}, + const {'1': 'CreateDefaultField', '2': 13}, const {'1': 'CreateRow', '2': 21}, const {'1': 'GetRow', '2': 22}, const {'1': 'UpdateCell', '2': 30}, @@ -24,4 +25,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhYKEkNyZWF0ZURlZmF1bHRGaWVsZBANEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pb.dart deleted file mode 100644 index 19064fbfd1..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pb.dart +++ /dev/null @@ -1,118 +0,0 @@ -/// -// Generated code. Do not modify. -// source: number_description.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:protobuf/protobuf.dart' as $pb; - -import 'number_description.pbenum.dart'; - -export 'number_description.pbenum.dart'; - -class NumberDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: NumberFormat.Number, valueOf: NumberFormat.valueOf, enumValues: NumberFormat.values) - ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3) - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol') - ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive') - ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') - ..hasRequiredFields = false - ; - - NumberDescription._() : super(); - factory NumberDescription({ - NumberFormat? format, - $core.int? scale, - $core.String? symbol, - $core.bool? signPositive, - $core.String? name, - }) { - final _result = create(); - if (format != null) { - _result.format = format; - } - if (scale != null) { - _result.scale = scale; - } - if (symbol != null) { - _result.symbol = symbol; - } - if (signPositive != null) { - _result.signPositive = signPositive; - } - if (name != null) { - _result.name = name; - } - return _result; - } - factory NumberDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NumberDescription.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') - NumberDescription clone() => NumberDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - NumberDescription copyWith(void Function(NumberDescription) updates) => super.copyWith((message) => updates(message as NumberDescription)) as NumberDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static NumberDescription create() => NumberDescription._(); - NumberDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static NumberDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static NumberDescription? _defaultInstance; - - @$pb.TagNumber(1) - NumberFormat get format => $_getN(0); - @$pb.TagNumber(1) - set format(NumberFormat v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasFormat() => $_has(0); - @$pb.TagNumber(1) - void clearFormat() => clearField(1); - - @$pb.TagNumber(2) - $core.int get scale => $_getIZ(1); - @$pb.TagNumber(2) - set scale($core.int v) { $_setUnsignedInt32(1, v); } - @$pb.TagNumber(2) - $core.bool hasScale() => $_has(1); - @$pb.TagNumber(2) - void clearScale() => clearField(2); - - @$pb.TagNumber(3) - $core.String get symbol => $_getSZ(2); - @$pb.TagNumber(3) - set symbol($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasSymbol() => $_has(2); - @$pb.TagNumber(3) - void clearSymbol() => clearField(3); - - @$pb.TagNumber(4) - $core.bool get signPositive => $_getBF(3); - @$pb.TagNumber(4) - set signPositive($core.bool v) { $_setBool(3, v); } - @$pb.TagNumber(4) - $core.bool hasSignPositive() => $_has(3); - @$pb.TagNumber(4) - void clearSignPositive() => clearField(4); - - @$pb.TagNumber(5) - $core.String get name => $_getSZ(4); - @$pb.TagNumber(5) - set name($core.String v) { $_setString(4, v); } - @$pb.TagNumber(5) - $core.bool hasName() => $_has(4); - @$pb.TagNumber(5) - void clearName() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbenum.dart deleted file mode 100644 index f5c3d38628..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbenum.dart +++ /dev/null @@ -1,30 +0,0 @@ -/// -// Generated code. Do not modify. -// source: number_description.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 NumberFormat extends $pb.ProtobufEnum { - static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number'); - static const NumberFormat USD = NumberFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD'); - static const NumberFormat CNY = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY'); - static const NumberFormat EUR = NumberFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR'); - - static const $core.List values = [ - Number, - USD, - CNY, - EUR, - ]; - - static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static NumberFormat? valueOf($core.int value) => _byValue[value]; - - const NumberFormat._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbjson.dart deleted file mode 100644 index ff1b3dc40f..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbjson.dart +++ /dev/null @@ -1,37 +0,0 @@ -/// -// Generated code. Do not modify. -// source: number_description.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 numberFormatDescriptor instead') -const NumberFormat$json = const { - '1': 'NumberFormat', - '2': const [ - const {'1': 'Number', '2': 0}, - const {'1': 'USD', '2': 1}, - const {'1': 'CNY', '2': 2}, - const {'1': 'EUR', '2': 3}, - ], -}; - -/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESBwoDQ05ZEAISBwoDRVVSEAM='); -@$core.Deprecated('Use numberDescriptionDescriptor instead') -const NumberDescription$json = const { - '1': 'NumberDescription', - '2': const [ - const {'1': 'format', '3': 1, '4': 1, '5': 14, '6': '.NumberFormat', '10': 'format'}, - const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'}, - const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'}, - const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'}, - const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'}, - ], -}; - -/// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIlCgZmb3JtYXQYASABKA4yDS5OdW1iZXJGb3JtYXRSBmZvcm1hdBIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbserver.dart deleted file mode 100644 index 58225a92b7..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_description.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: number_description.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 'number_description.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 8f0a7e7d48..874107f9be 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,8 +1,8 @@ // Auto-generated, do not edit export './number_type_option.pb.dart'; -export './text_description.pb.dart'; export './dart_notification.pb.dart'; export './selection_type_option.pb.dart'; export './checkbox_type_option.pb.dart'; export './event_map.pb.dart'; +export './text_type_option.pb.dart'; export './date_type_option.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pb.dart deleted file mode 100644 index 27b2fa8431..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pb.dart +++ /dev/null @@ -1,196 +0,0 @@ -/// -// Generated code. Do not modify. -// source: selection_description.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:protobuf/protobuf.dart' as $pb; - -class SingleSelectDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelectDescription', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - SingleSelectDescription._() : super(); - factory SingleSelectDescription({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory SingleSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SingleSelectDescription.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') - SingleSelectDescription clone() => SingleSelectDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SingleSelectDescription copyWith(void Function(SingleSelectDescription) updates) => super.copyWith((message) => updates(message as SingleSelectDescription)) as SingleSelectDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SingleSelectDescription create() => SingleSelectDescription._(); - SingleSelectDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SingleSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SingleSelectDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class MultiSelectDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiSelectDescription', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - MultiSelectDescription._() : super(); - factory MultiSelectDescription({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory MultiSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory MultiSelectDescription.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') - MultiSelectDescription clone() => MultiSelectDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - MultiSelectDescription copyWith(void Function(MultiSelectDescription) updates) => super.copyWith((message) => updates(message as MultiSelectDescription)) as MultiSelectDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static MultiSelectDescription create() => MultiSelectDescription._(); - MultiSelectDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static MultiSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static MultiSelectDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class SelectOption extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', 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') ? '' : 'color') - ..hasRequiredFields = false - ; - - SelectOption._() : super(); - factory SelectOption({ - $core.String? id, - $core.String? name, - $core.String? color, - }) { - final _result = create(); - if (id != null) { - _result.id = id; - } - if (name != null) { - _result.name = name; - } - if (color != null) { - _result.color = color; - } - return _result; - } - factory SelectOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SelectOption.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') - SelectOption clone() => SelectOption()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SelectOption copyWith(void Function(SelectOption) updates) => super.copyWith((message) => updates(message as SelectOption)) as SelectOption; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SelectOption create() => SelectOption._(); - SelectOption createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SelectOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SelectOption? _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 color => $_getSZ(2); - @$pb.TagNumber(3) - set color($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasColor() => $_has(2); - @$pb.TagNumber(3) - void clearColor() => clearField(3); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbenum.dart deleted file mode 100644 index 6688bc34c9..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: selection_description.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 - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbjson.dart deleted file mode 100644 index 6bb0c9e4db..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbjson.dart +++ /dev/null @@ -1,44 +0,0 @@ -/// -// Generated code. Do not modify. -// source: selection_description.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 singleSelectDescriptionDescriptor instead') -const SingleSelectDescription$json = const { - '1': 'SingleSelectDescription', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `SingleSelectDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List singleSelectDescriptionDescriptor = $convert.base64Decode('ChdTaW5nbGVTZWxlY3REZXNjcmlwdGlvbhInCgdvcHRpb25zGAEgAygLMg0uU2VsZWN0T3B0aW9uUgdvcHRpb25zEiMKDWRpc2FibGVfY29sb3IYAiABKAhSDGRpc2FibGVDb2xvcg=='); -@$core.Deprecated('Use multiSelectDescriptionDescriptor instead') -const MultiSelectDescription$json = const { - '1': 'MultiSelectDescription', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `MultiSelectDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List multiSelectDescriptionDescriptor = $convert.base64Decode('ChZNdWx0aVNlbGVjdERlc2NyaXB0aW9uEicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSIwoNZGlzYWJsZV9jb2xvchgCIAEoCFIMZGlzYWJsZUNvbG9y'); -@$core.Deprecated('Use selectOptionDescriptor instead') -const SelectOption$json = const { - '1': 'SelectOption', - '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': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'}, - ], -}; - -/// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbserver.dart deleted file mode 100644 index f55cbba1ec..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_description.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: selection_description.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 'selection_description.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pb.dart new file mode 100644 index 0000000000..c30f2eb6e1 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pb.dart @@ -0,0 +1,58 @@ +/// +// Generated code. Do not modify. +// source: text_type_option.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:protobuf/protobuf.dart' as $pb; + +class RichTextTypeOption extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextTypeOption', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format') + ..hasRequiredFields = false + ; + + RichTextTypeOption._() : super(); + factory RichTextTypeOption({ + $core.String? format, + }) { + final _result = create(); + if (format != null) { + _result.format = format; + } + return _result; + } + factory RichTextTypeOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RichTextTypeOption.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') + RichTextTypeOption clone() => RichTextTypeOption()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + RichTextTypeOption copyWith(void Function(RichTextTypeOption) updates) => super.copyWith((message) => updates(message as RichTextTypeOption)) as RichTextTypeOption; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RichTextTypeOption create() => RichTextTypeOption._(); + RichTextTypeOption createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static RichTextTypeOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static RichTextTypeOption? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get format => $_getSZ(0); + @$pb.TagNumber(1) + set format($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasFormat() => $_has(0); + @$pb.TagNumber(1) + void clearFormat() => clearField(1); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbenum.dart similarity index 87% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbenum.dart index 0070b08607..f2bd90bfa5 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/checkbox_description.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbenum.dart @@ -1,6 +1,6 @@ /// // Generated code. Do not modify. -// source: checkbox_description.proto +// source: text_type_option.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 diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbjson.dart new file mode 100644 index 0000000000..e4ba6956ee --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbjson.dart @@ -0,0 +1,20 @@ +/// +// Generated code. Do not modify. +// source: text_type_option.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 richTextTypeOptionDescriptor instead') +const RichTextTypeOption$json = const { + '1': 'RichTextTypeOption', + '2': const [ + const {'1': 'format', '3': 1, '4': 1, '5': 9, '10': 'format'}, + ], +}; + +/// Descriptor for `RichTextTypeOption`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List richTextTypeOptionDescriptor = $convert.base64Decode('ChJSaWNoVGV4dFR5cGVPcHRpb24SFgoGZm9ybWF0GAEgASgJUgZmb3JtYXQ='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbserver.dart similarity index 81% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbserver.dart index bae86fb5d9..6620aa1ee7 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_data.pbserver.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/text_type_option.pbserver.dart @@ -1,9 +1,9 @@ /// // Generated code. Do not modify. -// source: cell_data.proto +// source: text_type_option.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 'cell_data.pb.dart'; +export 'text_type_option.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pb.dart deleted file mode 100644 index 152eef0c74..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pb.dart +++ /dev/null @@ -1,458 +0,0 @@ -/// -// Generated code. Do not modify. -// source: type_options.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:protobuf/protobuf.dart' as $pb; - -import 'type_options.pbenum.dart'; - -export 'type_options.pbenum.dart'; - -class RichTextDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextDescription', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format') - ..hasRequiredFields = false - ; - - RichTextDescription._() : super(); - factory RichTextDescription({ - $core.String? format, - }) { - final _result = create(); - if (format != null) { - _result.format = format; - } - return _result; - } - factory RichTextDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory RichTextDescription.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') - RichTextDescription clone() => RichTextDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - RichTextDescription copyWith(void Function(RichTextDescription) updates) => super.copyWith((message) => updates(message as RichTextDescription)) as RichTextDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static RichTextDescription create() => RichTextDescription._(); - RichTextDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static RichTextDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static RichTextDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get format => $_getSZ(0); - @$pb.TagNumber(1) - set format($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasFormat() => $_has(0); - @$pb.TagNumber(1) - void clearFormat() => clearField(1); -} - -class CheckboxDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxDescription', createEmptyInstance: create) - ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected') - ..hasRequiredFields = false - ; - - CheckboxDescription._() : super(); - factory CheckboxDescription({ - $core.bool? isSelected, - }) { - final _result = create(); - if (isSelected != null) { - _result.isSelected = isSelected; - } - return _result; - } - factory CheckboxDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CheckboxDescription.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') - CheckboxDescription clone() => CheckboxDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - CheckboxDescription copyWith(void Function(CheckboxDescription) updates) => super.copyWith((message) => updates(message as CheckboxDescription)) as CheckboxDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static CheckboxDescription create() => CheckboxDescription._(); - CheckboxDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static CheckboxDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CheckboxDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.bool get isSelected => $_getBF(0); - @$pb.TagNumber(1) - set isSelected($core.bool v) { $_setBool(0, v); } - @$pb.TagNumber(1) - $core.bool hasIsSelected() => $_has(0); - @$pb.TagNumber(1) - void clearIsSelected() => clearField(1); -} - -class DateDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dateFormat', $pb.PbFieldType.OE, defaultOrMaker: DateFormat.Local, valueOf: DateFormat.valueOf, enumValues: DateFormat.values) - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeFormat', $pb.PbFieldType.OE, defaultOrMaker: TimeFormat.TwelveHour, valueOf: TimeFormat.valueOf, enumValues: TimeFormat.values) - ..hasRequiredFields = false - ; - - DateDescription._() : super(); - factory DateDescription({ - DateFormat? dateFormat, - TimeFormat? timeFormat, - }) { - final _result = create(); - if (dateFormat != null) { - _result.dateFormat = dateFormat; - } - if (timeFormat != null) { - _result.timeFormat = timeFormat; - } - return _result; - } - factory DateDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DateDescription.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') - DateDescription clone() => DateDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - DateDescription copyWith(void Function(DateDescription) updates) => super.copyWith((message) => updates(message as DateDescription)) as DateDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static DateDescription create() => DateDescription._(); - DateDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static DateDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DateDescription? _defaultInstance; - - @$pb.TagNumber(1) - DateFormat get dateFormat => $_getN(0); - @$pb.TagNumber(1) - set dateFormat(DateFormat v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasDateFormat() => $_has(0); - @$pb.TagNumber(1) - void clearDateFormat() => clearField(1); - - @$pb.TagNumber(2) - TimeFormat get timeFormat => $_getN(1); - @$pb.TagNumber(2) - set timeFormat(TimeFormat v) { setField(2, v); } - @$pb.TagNumber(2) - $core.bool hasTimeFormat() => $_has(1); - @$pb.TagNumber(2) - void clearTimeFormat() => clearField(2); -} - -class SingleSelectDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelectDescription', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - SingleSelectDescription._() : super(); - factory SingleSelectDescription({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory SingleSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SingleSelectDescription.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') - SingleSelectDescription clone() => SingleSelectDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SingleSelectDescription copyWith(void Function(SingleSelectDescription) updates) => super.copyWith((message) => updates(message as SingleSelectDescription)) as SingleSelectDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SingleSelectDescription create() => SingleSelectDescription._(); - SingleSelectDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SingleSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SingleSelectDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class MultiSelectDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiSelectDescription', createEmptyInstance: create) - ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor') - ..hasRequiredFields = false - ; - - MultiSelectDescription._() : super(); - factory MultiSelectDescription({ - $core.Iterable? options, - $core.bool? disableColor, - }) { - final _result = create(); - if (options != null) { - _result.options.addAll(options); - } - if (disableColor != null) { - _result.disableColor = disableColor; - } - return _result; - } - factory MultiSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory MultiSelectDescription.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') - MultiSelectDescription clone() => MultiSelectDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - MultiSelectDescription copyWith(void Function(MultiSelectDescription) updates) => super.copyWith((message) => updates(message as MultiSelectDescription)) as MultiSelectDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static MultiSelectDescription create() => MultiSelectDescription._(); - MultiSelectDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static MultiSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static MultiSelectDescription? _defaultInstance; - - @$pb.TagNumber(1) - $core.List get options => $_getList(0); - - @$pb.TagNumber(2) - $core.bool get disableColor => $_getBF(1); - @$pb.TagNumber(2) - set disableColor($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasDisableColor() => $_has(1); - @$pb.TagNumber(2) - void clearDisableColor() => clearField(2); -} - -class SelectOption extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', 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') ? '' : 'color') - ..hasRequiredFields = false - ; - - SelectOption._() : super(); - factory SelectOption({ - $core.String? id, - $core.String? name, - $core.String? color, - }) { - final _result = create(); - if (id != null) { - _result.id = id; - } - if (name != null) { - _result.name = name; - } - if (color != null) { - _result.color = color; - } - return _result; - } - factory SelectOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SelectOption.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') - SelectOption clone() => SelectOption()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SelectOption copyWith(void Function(SelectOption) updates) => super.copyWith((message) => updates(message as SelectOption)) as SelectOption; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SelectOption create() => SelectOption._(); - SelectOption createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SelectOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SelectOption? _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 color => $_getSZ(2); - @$pb.TagNumber(3) - set color($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasColor() => $_has(2); - @$pb.TagNumber(3) - void clearColor() => clearField(3); -} - -class NumberDescription extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberDescription', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'money', $pb.PbFieldType.OE, defaultOrMaker: MoneySymbol.CNY, valueOf: MoneySymbol.valueOf, enumValues: MoneySymbol.values) - ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3) - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol') - ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive') - ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') - ..hasRequiredFields = false - ; - - NumberDescription._() : super(); - factory NumberDescription({ - MoneySymbol? money, - $core.int? scale, - $core.String? symbol, - $core.bool? signPositive, - $core.String? name, - }) { - final _result = create(); - if (money != null) { - _result.money = money; - } - if (scale != null) { - _result.scale = scale; - } - if (symbol != null) { - _result.symbol = symbol; - } - if (signPositive != null) { - _result.signPositive = signPositive; - } - if (name != null) { - _result.name = name; - } - return _result; - } - factory NumberDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory NumberDescription.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') - NumberDescription clone() => NumberDescription()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - NumberDescription copyWith(void Function(NumberDescription) updates) => super.copyWith((message) => updates(message as NumberDescription)) as NumberDescription; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static NumberDescription create() => NumberDescription._(); - NumberDescription createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static NumberDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static NumberDescription? _defaultInstance; - - @$pb.TagNumber(1) - MoneySymbol get money => $_getN(0); - @$pb.TagNumber(1) - set money(MoneySymbol v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasMoney() => $_has(0); - @$pb.TagNumber(1) - void clearMoney() => clearField(1); - - @$pb.TagNumber(2) - $core.int get scale => $_getIZ(1); - @$pb.TagNumber(2) - set scale($core.int v) { $_setUnsignedInt32(1, v); } - @$pb.TagNumber(2) - $core.bool hasScale() => $_has(1); - @$pb.TagNumber(2) - void clearScale() => clearField(2); - - @$pb.TagNumber(3) - $core.String get symbol => $_getSZ(2); - @$pb.TagNumber(3) - set symbol($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasSymbol() => $_has(2); - @$pb.TagNumber(3) - void clearSymbol() => clearField(3); - - @$pb.TagNumber(4) - $core.bool get signPositive => $_getBF(3); - @$pb.TagNumber(4) - set signPositive($core.bool v) { $_setBool(3, v); } - @$pb.TagNumber(4) - $core.bool hasSignPositive() => $_has(3); - @$pb.TagNumber(4) - void clearSignPositive() => clearField(4); - - @$pb.TagNumber(5) - $core.String get name => $_getSZ(4); - @$pb.TagNumber(5) - set name($core.String v) { $_setString(4, v); } - @$pb.TagNumber(5) - $core.bool hasName() => $_has(4); - @$pb.TagNumber(5) - void clearName() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbenum.dart deleted file mode 100644 index c3815cf5e1..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbenum.dart +++ /dev/null @@ -1,62 +0,0 @@ -/// -// Generated code. Do not modify. -// source: type_options.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 DateFormat extends $pb.ProtobufEnum { - static const DateFormat Local = DateFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); - static const DateFormat US = DateFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'US'); - static const DateFormat ISO = DateFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ISO'); - static const DateFormat Friendly = DateFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Friendly'); - - static const $core.List values = [ - Local, - US, - ISO, - Friendly, - ]; - - static final $core.Map<$core.int, DateFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static DateFormat? valueOf($core.int value) => _byValue[value]; - - const DateFormat._($core.int v, $core.String n) : super(v, n); -} - -class TimeFormat extends $pb.ProtobufEnum { - static const TimeFormat TwelveHour = TimeFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwelveHour'); - static const TimeFormat TwentyFourHour = TimeFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwentyFourHour'); - - static const $core.List values = [ - TwelveHour, - TwentyFourHour, - ]; - - static final $core.Map<$core.int, TimeFormat> _byValue = $pb.ProtobufEnum.initByValue(values); - static TimeFormat? valueOf($core.int value) => _byValue[value]; - - const TimeFormat._($core.int v, $core.String n) : super(v, n); -} - -class MoneySymbol extends $pb.ProtobufEnum { - static const MoneySymbol CNY = MoneySymbol._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY'); - static const MoneySymbol EUR = MoneySymbol._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR'); - static const MoneySymbol USD = MoneySymbol._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD'); - - static const $core.List values = [ - CNY, - EUR, - USD, - ]; - - static final $core.Map<$core.int, MoneySymbol> _byValue = $pb.ProtobufEnum.initByValue(values); - static MoneySymbol? valueOf($core.int value) => _byValue[value]; - - const MoneySymbol._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbjson.dart deleted file mode 100644 index 71e0cf884b..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbjson.dart +++ /dev/null @@ -1,125 +0,0 @@ -/// -// Generated code. Do not modify. -// source: type_options.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 dateFormatDescriptor instead') -const DateFormat$json = const { - '1': 'DateFormat', - '2': const [ - const {'1': 'Local', '2': 0}, - const {'1': 'US', '2': 1}, - const {'1': 'ISO', '2': 2}, - const {'1': 'Friendly', '2': 3}, - ], -}; - -/// Descriptor for `DateFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List dateFormatDescriptor = $convert.base64Decode('CgpEYXRlRm9ybWF0EgkKBUxvY2FsEAASBgoCVVMQARIHCgNJU08QAhIMCghGcmllbmRseRAD'); -@$core.Deprecated('Use timeFormatDescriptor instead') -const TimeFormat$json = const { - '1': 'TimeFormat', - '2': const [ - const {'1': 'TwelveHour', '2': 0}, - const {'1': 'TwentyFourHour', '2': 1}, - ], -}; - -/// Descriptor for `TimeFormat`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List timeFormatDescriptor = $convert.base64Decode('CgpUaW1lRm9ybWF0Eg4KClR3ZWx2ZUhvdXIQABISCg5Ud2VudHlGb3VySG91chAB'); -@$core.Deprecated('Use moneySymbolDescriptor instead') -const MoneySymbol$json = const { - '1': 'MoneySymbol', - '2': const [ - const {'1': 'CNY', '2': 0}, - const {'1': 'EUR', '2': 1}, - const {'1': 'USD', '2': 2}, - ], -}; - -/// Descriptor for `MoneySymbol`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List moneySymbolDescriptor = $convert.base64Decode('CgtNb25leVN5bWJvbBIHCgNDTlkQABIHCgNFVVIQARIHCgNVU0QQAg=='); -@$core.Deprecated('Use richTextDescriptionDescriptor instead') -const RichTextDescription$json = const { - '1': 'RichTextDescription', - '2': const [ - const {'1': 'format', '3': 1, '4': 1, '5': 9, '10': 'format'}, - ], -}; - -/// Descriptor for `RichTextDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List richTextDescriptionDescriptor = $convert.base64Decode('ChNSaWNoVGV4dERlc2NyaXB0aW9uEhYKBmZvcm1hdBgBIAEoCVIGZm9ybWF0'); -@$core.Deprecated('Use checkboxDescriptionDescriptor instead') -const CheckboxDescription$json = const { - '1': 'CheckboxDescription', - '2': const [ - const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'}, - ], -}; - -/// Descriptor for `CheckboxDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List checkboxDescriptionDescriptor = $convert.base64Decode('ChNDaGVja2JveERlc2NyaXB0aW9uEh8KC2lzX3NlbGVjdGVkGAEgASgIUgppc1NlbGVjdGVk'); -@$core.Deprecated('Use dateDescriptionDescriptor instead') -const DateDescription$json = const { - '1': 'DateDescription', - '2': const [ - const {'1': 'date_format', '3': 1, '4': 1, '5': 14, '6': '.DateFormat', '10': 'dateFormat'}, - const {'1': 'time_format', '3': 2, '4': 1, '5': 14, '6': '.TimeFormat', '10': 'timeFormat'}, - ], -}; - -/// Descriptor for `DateDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List dateDescriptionDescriptor = $convert.base64Decode('Cg9EYXRlRGVzY3JpcHRpb24SLAoLZGF0ZV9mb3JtYXQYASABKA4yCy5EYXRlRm9ybWF0UgpkYXRlRm9ybWF0EiwKC3RpbWVfZm9ybWF0GAIgASgOMgsuVGltZUZvcm1hdFIKdGltZUZvcm1hdA=='); -@$core.Deprecated('Use singleSelectDescriptionDescriptor instead') -const SingleSelectDescription$json = const { - '1': 'SingleSelectDescription', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `SingleSelectDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List singleSelectDescriptionDescriptor = $convert.base64Decode('ChdTaW5nbGVTZWxlY3REZXNjcmlwdGlvbhInCgdvcHRpb25zGAEgAygLMg0uU2VsZWN0T3B0aW9uUgdvcHRpb25zEiMKDWRpc2FibGVfY29sb3IYAiABKAhSDGRpc2FibGVDb2xvcg=='); -@$core.Deprecated('Use multiSelectDescriptionDescriptor instead') -const MultiSelectDescription$json = const { - '1': 'MultiSelectDescription', - '2': const [ - const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, - const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'}, - ], -}; - -/// Descriptor for `MultiSelectDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List multiSelectDescriptionDescriptor = $convert.base64Decode('ChZNdWx0aVNlbGVjdERlc2NyaXB0aW9uEicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSIwoNZGlzYWJsZV9jb2xvchgCIAEoCFIMZGlzYWJsZUNvbG9y'); -@$core.Deprecated('Use selectOptionDescriptor instead') -const SelectOption$json = const { - '1': 'SelectOption', - '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': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'}, - ], -}; - -/// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y'); -@$core.Deprecated('Use numberDescriptionDescriptor instead') -const NumberDescription$json = const { - '1': 'NumberDescription', - '2': const [ - const {'1': 'money', '3': 1, '4': 1, '5': 14, '6': '.MoneySymbol', '10': 'money'}, - const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'}, - const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'}, - const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'}, - const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'}, - ], -}; - -/// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIiCgVtb25leRgBIAEoDjIMLk1vbmV5U3ltYm9sUgVtb25leRIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbserver.dart deleted file mode 100644 index b46de00bf5..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/type_options.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: type_options.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 'type_options.pb.dart'; - diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index 61b69b45f1..2cc96e75d6 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -112,6 +112,7 @@ flutter: - assets/images/home/ - assets/images/editor/ - assets/images/grid/ + - assets/images/grid/field/ - assets/translations/ # - images/a_dot_ham.jpeg diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 59e3aa2a39..39d6bf2e95 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -71,6 +71,17 @@ pub(crate) async fn create_field_handler( Ok(()) } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn create_default_field_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let grid_id: GridId = data.into_inner(); + let editor = manager.get_grid_editor(grid_id.as_ref())?; + let field = editor.make_default_field().await?; + data_result(field) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_row_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 944c58d13b..8c08d547ff 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -13,6 +13,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) + .event(GridEvent::CreateDefaultField, create_default_field_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) .event(GridEvent::UpdateCell, update_cell_handler); @@ -38,6 +39,9 @@ pub enum GridEvent { #[event(input = "CreateFieldPayload")] CreateField = 12, + #[event(input = "GridId", output = "Field")] + CreateDefaultField = 13, + #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 21, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 0ba8fdebc4..4e0008c7a0 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -30,6 +30,7 @@ pub enum GridEvent { GetFields = 10, UpdateField = 11, CreateField = 12, + CreateDefaultField = 13, CreateRow = 21, GetRow = 22, UpdateCell = 30, @@ -47,6 +48,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 10 => ::std::option::Option::Some(GridEvent::GetFields), 11 => ::std::option::Option::Some(GridEvent::UpdateField), 12 => ::std::option::Option::Some(GridEvent::CreateField), + 13 => ::std::option::Option::Some(GridEvent::CreateDefaultField), 21 => ::std::option::Option::Some(GridEvent::CreateRow), 22 => ::std::option::Option::Some(GridEvent::GetRow), 30 => ::std::option::Option::Some(GridEvent::UpdateCell), @@ -61,6 +63,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::GetFields, GridEvent::UpdateField, GridEvent::CreateField, + GridEvent::CreateDefaultField, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, @@ -92,11 +95,11 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\x8b\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xa3\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ - \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\r\n\tCreate\ - Row\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06\ - proto3\ + \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x16\n\x12Cr\ + eateDefaultField\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\ + \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 2e768a115b..8408c120c1 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs @@ -4,9 +4,6 @@ mod number_type_option; pub use number_type_option::*; -mod text_description; -pub use text_description::*; - mod dart_notification; pub use dart_notification::*; @@ -19,5 +16,8 @@ pub use checkbox_type_option::*; mod event_map; pub use event_map::*; +mod text_type_option; +pub use text_type_option::*; + mod date_type_option; pub use date_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/text_type_option.rs similarity index 98% rename from frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs rename to frontend/rust-lib/flowy-grid/src/protobuf/model/text_type_option.rs index 2bedb36f63..febc180e03 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/text_description.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/text_type_option.rs @@ -17,7 +17,7 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `text_description.proto` +//! Generated file from `text_type_option.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. @@ -183,7 +183,7 @@ impl ::protobuf::reflect::ProtobufValue for RichTextTypeOption { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x16text_description.proto\",\n\x12RichTextTypeOption\x12\x16\n\x06for\ + \n\x16text_type_option.proto\",\n\x12RichTextTypeOption\x12\x16\n\x06for\ mat\x18\x01\x20\x01(\tR\x06formatb\x06proto3\ "; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 9a2177b6f4..894b2a111a 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -6,6 +6,7 @@ enum GridEvent { GetFields = 10; UpdateField = 11; CreateField = 12; + CreateDefaultField = 13; CreateRow = 21; GetRow = 22; UpdateCell = 30; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/text_type_option.proto similarity index 100% rename from frontend/rust-lib/flowy-grid/src/protobuf/proto/text_description.proto rename to frontend/rust-lib/flowy-grid/src/protobuf/proto/text_type_option.proto diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 14206f9254..64f5e40ee4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,19 +1,25 @@ +use crate::services::field::type_options::*; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; pub struct FieldBuilder { field_meta: FieldMeta, - type_options_builder: Box, + type_option_builder: Box, } impl FieldBuilder { - pub fn new(type_options_builder: T) -> Self { - let field_meta = FieldMeta::new("Name", "", FieldType::RichText); + pub fn new(type_option_builder: T) -> Self { + let field_meta = FieldMeta::new("", "", type_option_builder.field_type()); Self { field_meta, - type_options_builder: Box::new(type_options_builder), + type_option_builder: Box::new(type_option_builder), } } + pub fn from_field_type(field_type: &FieldType) -> Self { + let type_option_builder = type_option_builder_from_type(field_type); + Self::new(type_option_builder) + } + pub fn name(mut self, name: &str) -> Self { self.field_meta.name = name.to_owned(); self @@ -24,11 +30,6 @@ impl FieldBuilder { self } - pub fn field_type(mut self, field_type: FieldType) -> Self { - self.field_meta.field_type = field_type; - self - } - pub fn visibility(mut self, visibility: bool) -> Self { self.field_meta.visibility = visibility; self @@ -45,9 +46,8 @@ impl FieldBuilder { } pub fn build(mut self) -> FieldMeta { - assert_eq!(self.field_meta.field_type, self.type_options_builder.field_type()); - - let type_options = self.type_options_builder.build(); + debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); + let type_options = self.type_option_builder.build(); self.field_meta.type_option = type_options; self.field_meta } @@ -57,3 +57,27 @@ pub trait TypeOptionsBuilder { fn field_type(&self) -> FieldType; fn build(&self) -> String; } + +pub fn type_option_builder_from_type(field_type: &FieldType) -> Box { + match field_type { + FieldType::RichText => Box::new(RichTextTypeOptionBuilder::default()), + FieldType::Number => Box::new(NumberTypeOptionBuilder::default()), + FieldType::DateTime => Box::new(DateTypeOptionBuilder::default()), + FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::default()), + FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::default()), + FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::default()), + } +} + +impl TypeOptionsBuilder for Box +where + T: TypeOptionsBuilder + ?Sized, +{ + fn field_type(&self) -> FieldType { + (**self).field_type() + } + + fn build(&self) -> String { + (**self).build() + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index da6d057c03..08ae9f79c8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -7,15 +7,15 @@ use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; #[derive(Default)] -pub struct CheckboxTypeOptionsBuilder(CheckboxTypeOption); -impl CheckboxTypeOptionsBuilder { +pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); +impl CheckboxTypeOptionBuilder { pub fn set_selected(mut self, is_selected: bool) -> Self { self.0.is_selected = is_selected; self } } -impl TypeOptionsBuilder for CheckboxTypeOptionsBuilder { +impl TypeOptionsBuilder for CheckboxTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } @@ -66,7 +66,7 @@ mod tests { #[test] fn checkout_box_description_test() { - let description = CheckboxTypeOption::default(); + let type_option = CheckboxTypeOption::default(); assert_eq!(description.serialize_cell_data("true").unwrap(), "1".to_owned()); assert_eq!(description.serialize_cell_data("1").unwrap(), "1".to_owned()); assert_eq!(description.serialize_cell_data("yes").unwrap(), "1".to_owned()); diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 8c8fec6a86..20d94c8ca8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -63,8 +63,8 @@ impl CellDataSerde for DateTypeOption { } #[derive(Default)] -pub struct DateTypeOptionsBuilder(DateTypeOption); -impl DateTypeOptionsBuilder { +pub struct DateTypeOptionBuilder(DateTypeOption); +impl DateTypeOptionBuilder { pub fn date_format(mut self, date_format: DateFormat) -> Self { self.0.date_format = date_format; self @@ -75,7 +75,7 @@ impl DateTypeOptionsBuilder { self } } -impl TypeOptionsBuilder for DateTypeOptionsBuilder { +impl TypeOptionsBuilder for DateTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } @@ -258,7 +258,7 @@ mod tests { #[test] #[should_panic] fn date_description_invalid_data_test() { - let description = DateTypeOption::default(); + let type_option = DateTypeOption::default(); description.serialize_cell_data("he").unwrap(); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs index 51d06fff19..958edf2664 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs @@ -2,10 +2,10 @@ mod checkbox_type_option; mod date_type_option; mod number_type_option; mod selection_type_option; -mod text_description; +mod text_type_option; pub use checkbox_type_option::*; pub use date_type_option::*; pub use number_type_option::*; pub use selection_type_option::*; -pub use text_description::*; +pub use text_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 64783cda2b..5fa74285df 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -19,9 +19,9 @@ lazy_static! { } #[derive(Default)] -pub struct NumberTypeOptionsBuilder(NumberTypeOption); +pub struct NumberTypeOptionBuilder(NumberTypeOption); -impl NumberTypeOptionsBuilder { +impl NumberTypeOptionBuilder { pub fn name(mut self, name: &str) -> Self { self.0.name = name.to_string(); self @@ -43,7 +43,7 @@ impl NumberTypeOptionsBuilder { } } -impl TypeOptionsBuilder for NumberTypeOptionsBuilder { +impl TypeOptionsBuilder for NumberTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index af5e58119f..5c4a3c5141 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -33,15 +33,15 @@ impl CellDataSerde for SingleSelectTypeOption { } #[derive(Default)] -pub struct SingleSelectTypeOptionsBuilder(SingleSelectTypeOption); +pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption); -impl SingleSelectTypeOptionsBuilder { +impl SingleSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { self.0.options.push(opt); self } } -impl TypeOptionsBuilder for SingleSelectTypeOptionsBuilder { +impl TypeOptionsBuilder for SingleSelectTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } @@ -72,15 +72,15 @@ impl CellDataSerde for MultiSelectTypeOption { } #[derive(Default)] -pub struct MultiSelectTypeOptionsBuilder(MultiSelectTypeOption); -impl MultiSelectTypeOptionsBuilder { +pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); +impl MultiSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { self.0.options.push(opt); self } } -impl TypeOptionsBuilder for MultiSelectTypeOptionsBuilder { +impl TypeOptionsBuilder for MultiSelectTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } @@ -157,10 +157,10 @@ mod tests { #[test] #[should_panic] fn selection_description_test() { - let description = SingleSelectTypeOption::default(); + let type_option = SingleSelectTypeOption::default(); assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1".to_owned()); - let description = MultiSelectDescription::default(); + let type_option = MultiSelectDescription::default(); assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1,2,3".to_owned()); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs similarity index 90% rename from frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 9b6b988fc0..dc7e0e56d0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_description.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -8,9 +8,9 @@ use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; #[derive(Default)] -pub struct RichTextTypeOptionsBuilder(RichTextTypeOption); +pub struct RichTextTypeOptionBuilder(RichTextTypeOption); -impl TypeOptionsBuilder for RichTextTypeOptionsBuilder { +impl TypeOptionsBuilder for RichTextTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } 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 80768c5251..2582ad77b0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,25 +1,19 @@ +use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; +use crate::services::field::{type_option_builder_from_type, FieldBuilder}; +use crate::services::row::*; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{ - CellMetaChangeset, Field, FieldChangeset, FieldMeta, Grid, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, - RepeatedField, RepeatedFieldOrder, RepeatedGridBlock, RepeatedRow, Row, RowMeta, RowMetaChangeset, RowOrder, -}; +use flowy_grid_data_model::entities::*; +use flowy_grid_data_model::parser::CreateFieldParams; +use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridChangeset, GridMetaPad}; use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_delta_from_revisions; -use std::collections::HashMap; - -use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::services::row::{ - make_grid_block_from_block_metas, make_grid_blocks, make_row_meta_from_context, make_rows_from_row_metas, - serialize_cell_data, CreateRowMetaBuilder, CreateRowMetaPayload, GridBlockMetaData, -}; -use flowy_grid_data_model::parser::CreateFieldParams; -use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; +use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; @@ -55,12 +49,25 @@ impl ClientGridEditor { })) } - pub async fn create_field(&self, params: CreateFieldParams) -> FlowyResult<()> { + pub async fn create_field(&self, mut params: CreateFieldParams) -> FlowyResult<()> { + if params.type_option_data.is_empty() { + params.type_option_data = type_option_builder_from_type(¶ms.field.field_type) + .build() + .as_bytes() + .to_vec(); + } + let _ = self.modify(|grid| Ok(grid.create_field(params)?)).await?; let _ = self.notify_did_update_fields().await?; Ok(()) } + pub async fn make_default_field(&self) -> FlowyResult { + let field_type = FieldType::default(); + let field_meta = FieldBuilder::from_field_type(&field_type).build(); + Ok(field_meta.into()) + } + pub async fn contain_field(&self, field_id: &str) -> bool { self.pad.read().await.contain_field(field_id) } diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 9349854433..1638060f61 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -3,22 +3,17 @@ use flowy_grid_data_model::entities::{BuildGridContext, FieldType}; use flowy_sync::client_grid::GridBuilder; pub fn make_default_grid() -> BuildGridContext { - let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) + let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default()) .name("Name") .visibility(true) - .field_type(FieldType::RichText) .build(); - let single_select = SingleSelectTypeOptionsBuilder::default() + let single_select = SingleSelectTypeOptionBuilder::default() .option(SelectOption::new("Done")) .option(SelectOption::new("Unknown")) .option(SelectOption::new("Progress")); - let single_select_field = FieldBuilder::new(single_select) - .name("Status") - .visibility(true) - .field_type(FieldType::SingleSelect) - .build(); + let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build(); GridBuilder::default() .add_field(text_field) diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 803c2409a9..4cda3a599e 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -253,13 +253,13 @@ async fn grid_row_add_cells_test() { builder.add_cell(&field.id, data).unwrap(); } FieldType::SingleSelect => { - let description = SingleSelectTypeOption::from(field); + let type_option = SingleSelectTypeOption::from(field); let options = description.options.first().unwrap(); let data = description.serialize_cell_data(&options.id).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::MultiSelect => { - let description = MultiSelectTypeOption::from(field); + let type_option = MultiSelectTypeOption::from(field); let options = description .options .iter() @@ -382,11 +382,11 @@ async fn grid_cell_update() { FieldType::Number => "123".to_string(), FieldType::DateTime => "123".to_string(), FieldType::SingleSelect => { - let description = SingleSelectTypeOption::from(field_meta); + let type_option = SingleSelectTypeOption::from(field_meta); description.options.first().unwrap().id.clone() } FieldType::MultiSelect => { - let description = MultiSelectTypeOption::from(field_meta); + let type_option = MultiSelectTypeOption::from(field_meta); description.options.first().unwrap().id.clone() } FieldType::Checkbox => "1".to_string(), diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index fa25ef3e78..d622d3acbe 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -248,10 +248,9 @@ async fn get_row_metas(editor: &Arc) -> Vec> { } pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { - let field_meta = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) + let field_meta = FieldBuilder::new(RichTextTypeOptionBuilder::default()) .name("Name") .visibility(true) - .field_type(FieldType::RichText) .build(); let cloned_field_meta = field_meta.clone(); @@ -276,16 +275,11 @@ pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { } pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { - let single_select = SingleSelectTypeOptionsBuilder::default() + let single_select = SingleSelectTypeOptionBuilder::default() .option(SelectOption::new("Done")) .option(SelectOption::new("Progress")); - let field_meta = FieldBuilder::new(single_select) - .name("Name") - .visibility(true) - .field_type(FieldType::SingleSelect) - .build(); - + let field_meta = FieldBuilder::new(single_select).name("Name").visibility(true).build(); let cloned_field_meta = field_meta.clone(); let field = Field { @@ -308,60 +302,42 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMet } fn make_template_1_grid() -> BuildGridContext { - let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) + let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default()) .name("Name") .visibility(true) - .field_type(FieldType::RichText) .build(); // Single Select - let single_select = SingleSelectTypeOptionsBuilder::default() + let single_select = SingleSelectTypeOptionBuilder::default() .option(SelectOption::new("Live")) .option(SelectOption::new("Completed")) .option(SelectOption::new("Planned")) .option(SelectOption::new("Paused")); - let single_select_field = FieldBuilder::new(single_select) - .name("Status") - .visibility(true) - .field_type(FieldType::SingleSelect) - .build(); + let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build(); // MultiSelect - let multi_select = MultiSelectTypeOptionsBuilder::default() + let multi_select = MultiSelectTypeOptionBuilder::default() .option(SelectOption::new("Google")) .option(SelectOption::new("Facebook")) .option(SelectOption::new("Twitter")); let multi_select_field = FieldBuilder::new(multi_select) .name("Platform") .visibility(true) - .field_type(FieldType::MultiSelect) .build(); // Number - let number = NumberTypeOptionsBuilder::default().set_format(NumberFormat::USD); - let number_field = FieldBuilder::new(number) - .name("Price") - .visibility(true) - .field_type(FieldType::Number) - .build(); + let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD); + let number_field = FieldBuilder::new(number).name("Price").visibility(true).build(); // Date - let date = DateTypeOptionsBuilder::default() + let date = DateTypeOptionBuilder::default() .date_format(DateFormat::US) .time_format(TimeFormat::TwentyFourHour); - let date_field = FieldBuilder::new(date) - .name("Time") - .visibility(true) - .field_type(FieldType::DateTime) - .build(); + let date_field = FieldBuilder::new(date).name("Time").visibility(true).build(); // Checkbox - let checkbox = CheckboxTypeOptionsBuilder::default(); - let checkbox_field = FieldBuilder::new(checkbox) - .name("is done") - .visibility(true) - .field_type(FieldType::Checkbox) - .build(); + let checkbox = CheckboxTypeOptionBuilder::default(); + let checkbox_field = FieldBuilder::new(checkbox).name("is done").visibility(true).build(); GridBuilder::default() .add_field(text_field) diff --git a/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs b/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs index bfcb802c22..83f0395f53 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs @@ -102,10 +102,6 @@ impl TryInto for CreateFieldPayload { Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), }; - if self.type_option_data.is_empty() { - return Err(ErrorCode::TypeOptionIsEmpty); - } - Ok(CreateFieldParams { grid_id: grid_id.0, field: self.field, diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 372433cd34..06ecf07030 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -45,16 +45,18 @@ impl GridMetaPad { .. } = params; + // Check if the field exists or not if grid .fields .iter() .find(|field_meta| field_meta.id == field.id) .is_some() { - tracing::warn!("Create grid field"); + tracing::warn!("Duplicate grid field"); return Ok(None); } + // Parse type option let type_option = String::from_utf8(type_option_data).map_err(|e| CollaborateError::internal().context(e))?; From 2eccd0452bd0ef5d8369803cc313b0263b5378a1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 24 Mar 2022 23:52:06 +0800 Subject: [PATCH 07/47] chore: close bloc when overlay dismiss --- .../app_flowy/assets/translations/en.json | 2 +- .../grid/field/create_field_bloc.dart | 11 ++- .../application/grid/field/field_service.dart | 20 +++-- .../widgets/header/create_field_pannel.dart | 78 ++++++++++++------- .../widgets/header/field_operation_list.dart | 2 - .../widgets/header/field_tyep_switcher.dart | 3 +- .../src/widgets/header/field_type_list.dart | 1 - .../grid/src/widgets/header/header.dart | 12 +-- .../lib/style_widget/button.dart | 2 +- .../flowy_infra_ui/lib/style_widget/text.dart | 3 +- .../lib/widget/rounded_input_field.dart | 1 + .../flowy-grid/src/services/grid_editor.rs | 3 +- 12 files changed, 83 insertions(+), 55 deletions(-) diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 5646cdff58..5e5fc661ec 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -150,7 +150,7 @@ "duplicate": "Duplicate", "delete": "Delete", "textFieldName": "Text", - "checkboxFieldName": "Number", + "checkboxFieldName": "Checkbox", "dateFieldName": "Date", "numberFieldName": "Number", "singleSelectFieldName": "Select", diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart index 0d9126cd1e..9f70646415 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -1,3 +1,4 @@ +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -14,8 +15,15 @@ class CreateFieldBloc extends Bloc { on( (event, emit) async { await event.map( - initial: (_InitialField value) {}, + initial: (_InitialField value) async { + final result = await service.getDefaultField(); + result.fold( + (field) => emit(state.copyWith(field: Some(field))), + (err) => Log.error(err), + ); + }, updateName: (_UpdateName value) {}, + done: (_Done value) {}, ); }, ); @@ -31,6 +39,7 @@ class CreateFieldBloc extends Bloc { class CreateFieldEvent with _$CreateFieldEvent { const factory CreateFieldEvent.initial() = _InitialField; const factory CreateFieldEvent.updateName(String newName) = _UpdateName; + const factory CreateFieldEvent.done() = _Done; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 5a8032b79a..f63d8d5d5f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -12,9 +12,7 @@ class FieldService { FieldService({required this.gridId}); - Future> getDefaultField( - String gridId, - ) { + Future> getDefaultField() { final payload = GridId.create()..value = gridId; return GridEventCreateDefaultField(payload).send(); } @@ -26,7 +24,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return _createField(gridId, field, typeOptionData, startFieldId); + return createField(gridId, field, typeOptionData, startFieldId); } Future> createSingleSelectField( @@ -36,7 +34,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return _createField(gridId, field, typeOptionData, startFieldId); + return createField(gridId, field, typeOptionData, startFieldId); } Future> createMultiSelectField( @@ -46,7 +44,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return _createField(gridId, field, typeOptionData, startFieldId); + return createField(gridId, field, typeOptionData, startFieldId); } Future> createNumberField( @@ -56,7 +54,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return _createField(gridId, field, typeOptionData, startFieldId); + return createField(gridId, field, typeOptionData, startFieldId); } Future> createDateField( @@ -66,19 +64,19 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return _createField(gridId, field, typeOptionData, startFieldId); + return createField(gridId, field, typeOptionData, startFieldId); } - Future> _createField( + Future> createField( String gridId, Field field, - Uint8List typeOptionData, + Uint8List? typeOptionData, String? startFieldId, ) { final payload = CreateFieldPayload.create() ..gridId = gridId ..field_2 = field - ..typeOptionData = typeOptionData + ..typeOptionData = typeOptionData ?? Uint8List.fromList([]) ..startFieldId = startFieldId ?? ""; return GridEventCreateField(payload).send(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 69d57782a8..0b8e2c3eac 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -3,55 +3,73 @@ import 'package:app_flowy/workspace/application/grid/field/create_field_bloc.dar import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - import 'field_name_input.dart'; import 'field_tyep_switcher.dart'; -class CreateFieldPannel extends StatelessWidget { - const CreateFieldPannel({Key? key}) : super(key: key); +class CreateFieldPannel extends FlowyOverlayDelegate { + final String gridId; + final CreateFieldBloc _createFieldBloc; + CreateFieldPannel({required this.gridId, Key? key}) : _createFieldBloc = getIt(param1: gridId) { + _createFieldBloc.add(const CreateFieldEvent.initial()); + } - static void show(BuildContext context) { - const pannel = CreateFieldPannel(); + void show(BuildContext context, String gridId) { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: pannel, - constraints: BoxConstraints.loose(const Size(300, 200)), + child: _CreateFieldPannelWidget(_createFieldBloc), + constraints: BoxConstraints.loose(const Size(220, 200)), ), - identifier: pannel.identifier(), + identifier: identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomWithLeftAligned, style: FlowyOverlayStyle(blur: false), - ); - } - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt()..add(const CreateFieldEvent.initial()), - child: BlocBuilder( - builder: (context, state) { - return state.field.fold( - () => const SizedBox(), - (field) => Column(children: [ - const FlowyText.medium("Edit property"), - const VSpace(10), - _FieldNameTextField(field), - const VSpace(10), - _FieldTypeSwitcher(field), - ]), - ); - }, - ), + delegate: this, ); } String identifier() { return toString(); } + + @override + void didRemove() async { + await _createFieldBloc.close(); + // TODO: implement didRemove + } +} + +class _CreateFieldPannelWidget extends StatelessWidget { + final CreateFieldBloc createFieldBloc; + const _CreateFieldPannelWidget(this.createFieldBloc, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider.value( + value: createFieldBloc, + child: BlocBuilder( + builder: (context, state) { + return state.field.fold( + () => const SizedBox(), + (field) => ListView( + shrinkWrap: true, + children: [ + const FlowyText.medium("Edit property", fontSize: 12), + const VSpace(10), + _FieldNameTextField(field), + const VSpace(10), + _FieldTypeSwitcher(field), + const VSpace(10), + ], + ), + ); + }, + ), + ); + } } class _FieldTypeSwitcher extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart index f803bdee58..fb639e5f5b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -55,9 +55,7 @@ class FieldActionItem extends StatelessWidget { enum FieldAction { hide, - // insertLeft, duplicate, - // insertRight, delete, } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index 505715d541..61b7c49b2d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -26,7 +26,8 @@ class FieldTypeSwitcher extends StatelessWidget { return SizedBox( height: 36, child: FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: FlowyText.medium(field.fieldType.title(), fontSize: 12), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), hoverColor: theme.hover, onTap: () => FieldTypeList.show(context, onSelectField), leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index aa5d22804d..25ff77494d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index 1b1cde2acb..cfac576cd5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -65,7 +65,7 @@ class GridHeader extends StatelessWidget { children: [ const _HeaderLeading(), ...cells, - const _HeaderTrailing(), + _HeaderTrailing(gridId: gridId), ], ); @@ -88,7 +88,8 @@ class _HeaderLeading extends StatelessWidget { } class _HeaderTrailing extends StatelessWidget { - const _HeaderTrailing({Key? key}) : super(key: key); + final String gridId; + const _HeaderTrailing({required this.gridId, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -100,13 +101,14 @@ class _HeaderTrailing extends StatelessWidget { border: Border(top: borderSide, bottom: borderSide), ), padding: GridSize.headerContentInsets, - child: const CreateFieldButton(), + child: CreateFieldButton(gridId: gridId), ); } } class CreateFieldButton extends StatelessWidget { - const CreateFieldButton({Key? key}) : super(key: key); + final String gridId; + const CreateFieldButton({required this.gridId, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -114,7 +116,7 @@ class CreateFieldButton extends StatelessWidget { return FlowyButton( text: const FlowyText.medium('New column', fontSize: 12), hoverColor: theme.hover, - onTap: () => CreateFieldPannel.show(context), + onTap: () => CreateFieldPannel(gridId: gridId).show(context, gridId), leftIcon: svg("home/add"), ); } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index d74edefba4..78d65a9941 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -40,7 +40,7 @@ class FlowyButton extends StatelessWidget { children.add(const HSpace(6)); } - children.add(Align(child: text)); + children.add(text); if (rightIcon != null) { children.add(const Spacer()); diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart index 243cf37b7a..7ddfdc1c13 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart @@ -1,5 +1,5 @@ import 'package:flowy_infra/theme.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class FlowyText extends StatelessWidget { @@ -42,6 +42,7 @@ class FlowyText extends StatelessWidget { return Text(title, overflow: overflow, softWrap: false, + textAlign: textAlign, style: TextStyle( color: theme.textColor, fontWeight: fontWeight, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart index 0cd2265cce..110cd29c73 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart @@ -81,6 +81,7 @@ class _RoundedInputFieldState extends State { }, cursorColor: widget.cursorColor, obscureText: obscuteText, + style: widget.style, decoration: InputDecoration( contentPadding: widget.contentPadding, hintText: widget.hintText, 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 2582ad77b0..d81b96a1ad 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -64,7 +64,8 @@ impl ClientGridEditor { pub async fn make_default_field(&self) -> FlowyResult { let field_type = FieldType::default(); - let field_meta = FieldBuilder::from_field_type(&field_type).build(); + let name = format!("Property {}", self.pad.read().await.fields().len()); + let field_meta = FieldBuilder::from_field_type(&field_type).name(&name).build(); Ok(field_meta.into()) } From 90e7873135fa9554b41b1700cde92b0effa3902c Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 25 Mar 2022 15:02:43 +0800 Subject: [PATCH 08/47] chore: create field --- .../app_flowy/lib/startup/deps_resolver.dart | 222 ++++++++ .../lib/startup/home_deps_resolver.dart | 169 ------ frontend/app_flowy/lib/startup/startup.dart | 6 +- .../lib/startup/user_deps_resolver.dart | 29 -- .../lib/user/application/prelude.dart | 4 + .../lib/user/application/sign_in_bloc.dart | 4 +- .../lib/user/application/sign_up_bloc.dart | 12 +- .../app_flowy/lib/user/domain/auth_state.dart | 2 +- .../grid/cell_bloc/checkbox_cell_bloc.dart | 4 +- .../grid/cell_bloc/date_cell_bloc.dart | 4 +- .../grid/cell_bloc/number_cell_bloc.dart | 4 +- .../grid/cell_bloc/selection_cell_bloc.dart | 4 +- .../grid/cell_bloc/text_cell_bloc.dart | 4 +- .../grid/field/create_field_bloc.dart | 9 +- .../grid/field/edit_field_bloc.dart | 9 +- .../application/grid/field/field_service.dart | 21 +- .../grid/field/switch_field_type_bloc.dart | 61 +++ .../grid/field/type_option/date_bloc.dart | 39 ++ .../grid/field/type_option/number_bloc.dart | 39 ++ .../field/type_option/selection_bloc.dart | 39 ++ .../workspace/application/grid/grid_bloc.dart | 4 +- .../workspace/application/grid/prelude.dart | 10 + .../application/grid/row/row_bloc.dart | 2 +- .../src/widgets/content/cell_builder.dart | 2 +- .../widgets/header/create_field_pannel.dart | 24 +- .../grid/src/widgets/header/field_editor.dart | 12 +- .../src/widgets/header/field_name_input.dart | 2 +- .../widgets/header/field_tyep_switcher.dart | 199 +++++++- .../src/widgets/header/field_type_list.dart | 6 +- .../src/flowy_overlay/overlay_container.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 12 +- .../flowy-grid-data-model/grid.pb.dart | 138 +++++ .../flowy-grid-data-model/grid.pbjson.dart | 23 + .../protobuf/flowy-grid/event_map.pbenum.dart | 4 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 28 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 6 +- .../src/protobuf/model/event_map.rs | 14 +- .../src/protobuf/proto/event_map.proto | 2 +- .../flowy-grid/src/services/grid_editor.rs | 5 +- .../src/entities/grid.rs | 21 + .../src/protobuf/model/grid.rs | 483 +++++++++++++++++- .../src/protobuf/proto/grid.proto | 9 + 43 files changed, 1371 insertions(+), 326 deletions(-) create mode 100644 frontend/app_flowy/lib/startup/deps_resolver.dart delete mode 100644 frontend/app_flowy/lib/startup/home_deps_resolver.dart delete mode 100644 frontend/app_flowy/lib/startup/user_deps_resolver.dart create mode 100644 frontend/app_flowy/lib/user/application/prelude.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart new file mode 100644 index 0000000000..56f115a22b --- /dev/null +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -0,0 +1,222 @@ +import 'package:app_flowy/core/network_monitor.dart'; +import 'package:app_flowy/user/application/user_listener.dart'; +import 'package:app_flowy/user/application/user_service.dart'; +import 'package:app_flowy/workspace/application/app/prelude.dart'; +import 'package:app_flowy/workspace/application/doc/prelude.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_listener.dart'; +import 'package:app_flowy/workspace/application/trash/prelude.dart'; +import 'package:app_flowy/workspace/application/workspace/prelude.dart'; +import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; +import 'package:app_flowy/workspace/application/home/home_bloc.dart'; +import 'package:app_flowy/workspace/application/view/prelude.dart'; +import 'package:app_flowy/workspace/application/home/prelude.dart'; +import 'package:app_flowy/workspace/application/menu/prelude.dart'; +import 'package:app_flowy/user/application/prelude.dart'; +import 'package:app_flowy/user/presentation/router.dart'; +import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; +import 'package:get_it/get_it.dart'; + +class DependencyResolver { + static Future resolve(GetIt getIt) async { + _resolveUserDeps(getIt); + + _resolveHomeDeps(getIt); + + _resolveFolderDeps(getIt); + + _resolveDocDeps(getIt); + + _resolveGridDeps(getIt); + } +} + +void _resolveUserDeps(GetIt getIt) { + getIt.registerFactory(() => AuthService()); + getIt.registerFactory(() => AuthRouter()); + + getIt.registerFactory(() => SignInBloc(getIt())); + getIt.registerFactory(() => SignUpBloc(getIt())); + + getIt.registerFactory(() => SplashRoute()); + getIt.registerFactory(() => HomeBloc()); + getIt.registerFactory(() => EditPannelBloc()); + getIt.registerFactory(() => SplashBloc()); + getIt.registerLazySingleton(() => NetworkListener()); +} + +void _resolveHomeDeps(GetIt getIt) { + getIt.registerFactoryParam( + (user, _) => UserListener(user: user), + ); + + getIt.registerFactoryParam( + (user, _) => HomeListenBloc(getIt(param1: user)), + ); + + // + getIt.registerLazySingleton(() => HomeStackManager()); + + getIt.registerFactoryParam( + (user, _) => WelcomeBloc( + userService: UserService(), + userListener: getIt(param1: user), + ), + ); + + // share + getIt.registerLazySingleton(() => ShareService()); + getIt.registerFactoryParam( + (view, _) => DocShareBloc(view: view, service: getIt())); +} + +void _resolveFolderDeps(GetIt getIt) { + //workspace + getIt.registerFactoryParam((user, workspaceId) => + WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId))); + + // View + getIt.registerFactoryParam( + (view, _) => ViewListener(view: view), + ); + + getIt.registerFactoryParam( + (view, _) => ViewBloc( + view: view, + service: ViewService(), + listener: getIt(param1: view), + ), + ); + + //Menu + getIt.registerFactoryParam( + (user, workspaceId) => MenuBloc( + workspaceId: workspaceId, + service: WorkspaceService(), + listener: getIt(param1: user, param2: workspaceId), + ), + ); + + getIt.registerFactoryParam( + (user, _) => MenuUserBloc( + user, + UserService(), + getIt(param1: user), + ), + ); + + // App + getIt.registerFactoryParam( + (app, _) => AppBloc( + app: app, + service: AppService(), + listener: AppListener(appId: app.id), + ), + ); + + // trash + getIt.registerLazySingleton(() => TrashService()); + getIt.registerLazySingleton(() => TrashListener()); + getIt.registerFactory( + () => TrashBloc( + service: getIt(), + listener: getIt(), + ), + ); +} + +void _resolveDocDeps(GetIt getIt) { +// Doc + getIt.registerFactoryParam( + (view, _) => DocumentBloc( + view: view, + service: DocumentService(), + listener: getIt(param1: view), + trashService: getIt(), + ), + ); +} + +void _resolveGridDeps(GetIt getIt) { + // Grid + getIt.registerFactoryParam( + (view, _) => GridBloc(view: view, service: GridService()), + ); + + getIt.registerFactoryParam( + (data, _) => RowBloc( + rowService: RowService(data), + listener: RowListener(rowId: data.rowId), + ), + ); + + getIt.registerFactoryParam>( + (gridId, fields) => GridHeaderBloc( + data: GridHeaderData(gridId: gridId, fields: fields), + service: FieldService(gridId: gridId), + ), + ); + + getIt.registerFactoryParam( + (data, _) => EditFieldBloc( + field: data.field, + service: FieldService(gridId: data.gridId), + ), + ); + + getIt.registerFactoryParam( + (gridId, _) => CreateFieldBloc( + service: FieldService(gridId: gridId), + ), + ); + + getIt.registerFactoryParam( + (context, _) => TextCellBloc( + service: CellService(context), + ), + ); + + getIt.registerFactoryParam( + (context, _) => SelectionCellBloc( + service: CellService(context), + ), + ); + + getIt.registerFactoryParam( + (context, _) => NumberCellBloc( + service: CellService(context), + ), + ); + + getIt.registerFactoryParam( + (context, _) => DateCellBloc( + service: CellService(context), + ), + ); + + getIt.registerFactoryParam( + (context, _) => CheckboxCellBloc( + service: CellService(context), + ), + ); + + getIt.registerFactoryParam( + (editContext, _) => SwitchFieldTypeBloc(editContext), + ); + + getIt.registerFactory( + () => SelectionTypeOptionBloc(), + ); + + getIt.registerFactory( + () => DateTypeOptionBloc(), + ); + + getIt.registerFactory( + () => NumberTypeOptionBloc(), + ); +} diff --git a/frontend/app_flowy/lib/startup/home_deps_resolver.dart b/frontend/app_flowy/lib/startup/home_deps_resolver.dart deleted file mode 100644 index 1702544a64..0000000000 --- a/frontend/app_flowy/lib/startup/home_deps_resolver.dart +++ /dev/null @@ -1,169 +0,0 @@ -import 'package:app_flowy/user/application/user_listener.dart'; -import 'package:app_flowy/user/application/user_service.dart'; -import 'package:app_flowy/workspace/application/app/prelude.dart'; -import 'package:app_flowy/workspace/application/doc/prelude.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/application/grid/row/row_listener.dart'; -import 'package:app_flowy/workspace/application/trash/prelude.dart'; -import 'package:app_flowy/workspace/application/workspace/prelude.dart'; -import 'package:app_flowy/workspace/application/view/prelude.dart'; -import 'package:app_flowy/workspace/application/home/prelude.dart'; -import 'package:app_flowy/workspace/application/menu/prelude.dart'; - -import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; -import 'package:get_it/get_it.dart'; - -class HomeDepsResolver { - static Future resolve(GetIt getIt) async { - getIt.registerFactoryParam( - (user, _) => UserListener(user: user), - ); - - getIt.registerFactoryParam( - (user, _) => HomeListenBloc(getIt(param1: user)), - ); - - // - getIt.registerLazySingleton(() => HomeStackManager()); - getIt.registerFactoryParam( - (user, _) => WelcomeBloc( - userService: UserService(), - userListener: getIt(param1: user), - ), - ); - - //workspace - getIt.registerFactoryParam((user, workspaceId) => - WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId))); - - // View - getIt.registerFactoryParam( - (view, _) => ViewListener(view: view), - ); - - getIt.registerFactoryParam( - (view, _) => ViewBloc( - view: view, - service: ViewService(), - listener: getIt(param1: view), - ), - ); - - //Menu Bloc - getIt.registerFactoryParam( - (user, workspaceId) => MenuBloc( - workspaceId: workspaceId, - service: WorkspaceService(), - listener: getIt(param1: user, param2: workspaceId), - ), - ); - - getIt.registerFactoryParam( - (user, _) => MenuUserBloc( - user, - UserService(), - getIt(param1: user), - ), - ); - - // App - getIt.registerFactoryParam( - (app, _) => AppBloc( - app: app, - service: AppService(), - listener: AppListener(appId: app.id), - ), - ); - - // Doc - getIt.registerFactoryParam( - (view, _) => DocumentBloc( - view: view, - service: DocumentService(), - listener: getIt(param1: view), - trashService: getIt(), - ), - ); - - // Grid - getIt.registerFactoryParam( - (view, _) => GridBloc(view: view, service: GridService()), - ); - - getIt.registerFactoryParam( - (data, _) => RowBloc( - rowService: RowService(data), - listener: RowListener(rowId: data.rowId), - ), - ); - - getIt.registerFactoryParam>( - (gridId, fields) => GridHeaderBloc( - data: GridHeaderData(gridId: gridId, fields: fields), - service: FieldService(gridId: gridId), - ), - ); - - getIt.registerFactoryParam( - (data, _) => EditFieldBloc( - field: data.field, - service: FieldService(gridId: data.gridId), - ), - ); - - getIt.registerFactoryParam( - (gridId, _) => CreateFieldBloc( - service: FieldService(gridId: gridId), - ), - ); - - getIt.registerFactoryParam( - (context, _) => TextCellBloc( - service: CellService(context), - ), - ); - - getIt.registerFactoryParam( - (context, _) => SelectionCellBloc( - service: CellService(context), - ), - ); - - getIt.registerFactoryParam( - (context, _) => NumberCellBloc( - service: CellService(context), - ), - ); - - getIt.registerFactoryParam( - (context, _) => DateCellBloc( - service: CellService(context), - ), - ); - - getIt.registerFactoryParam( - (context, _) => CheckboxCellBloc( - service: CellService(context), - ), - ); - - // trash - getIt.registerLazySingleton(() => TrashService()); - getIt.registerLazySingleton(() => TrashListener()); - getIt.registerFactory( - () => TrashBloc( - service: getIt(), - listener: getIt(), - ), - ); - - // share - getIt.registerLazySingleton(() => ShareService()); - getIt.registerFactoryParam( - (view, _) => DocShareBloc(view: view, service: getIt())); - } -} diff --git a/frontend/app_flowy/lib/startup/startup.dart b/frontend/app_flowy/lib/startup/startup.dart index 0335879f5a..38243afa56 100644 --- a/frontend/app_flowy/lib/startup/startup.dart +++ b/frontend/app_flowy/lib/startup/startup.dart @@ -2,8 +2,7 @@ import 'dart:io'; import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/startup/tasks/prelude.dart'; -import 'package:app_flowy/startup/home_deps_resolver.dart'; -import 'package:app_flowy/startup/user_deps_resolver.dart'; +import 'package:app_flowy/startup/deps_resolver.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; @@ -62,8 +61,7 @@ Future initGetIt( getIt.registerLazySingleton(() => AppLauncher(env, getIt)); getIt.registerSingleton(PluginSandbox()); - await UserDepsResolver.resolve(getIt); - await HomeDepsResolver.resolve(getIt); + await DependencyResolver.resolve(getIt); } class LaunchContext { diff --git a/frontend/app_flowy/lib/startup/user_deps_resolver.dart b/frontend/app_flowy/lib/startup/user_deps_resolver.dart deleted file mode 100644 index daf67a071a..0000000000 --- a/frontend/app_flowy/lib/startup/user_deps_resolver.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:app_flowy/user/application/auth_service.dart'; -import 'package:app_flowy/user/application/sign_in_bloc.dart'; -import 'package:app_flowy/user/application/sign_up_bloc.dart'; -import 'package:app_flowy/user/application/splash_bloc.dart'; -import 'package:app_flowy/user/presentation/router.dart'; -import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; -import 'package:app_flowy/workspace/application/home/home_bloc.dart'; -import 'package:get_it/get_it.dart'; - -import '../core/network_monitor.dart'; - -class UserDepsResolver { - static Future resolve(GetIt getIt) async { - getIt.registerFactory(() => AuthService()); - - //Interface implementation - getIt.registerFactory(() => AuthRouter()); - - //Bloc - getIt.registerFactory(() => SignInBloc(getIt())); - getIt.registerFactory(() => SignUpBloc(getIt())); - - getIt.registerFactory(() => SplashRoute()); - getIt.registerFactory(() => HomeBloc()); - getIt.registerFactory(() => EditPannelBloc()); - getIt.registerFactory(() => SplashBloc()); - getIt.registerLazySingleton(() => NetworkListener()); - } -} diff --git a/frontend/app_flowy/lib/user/application/prelude.dart b/frontend/app_flowy/lib/user/application/prelude.dart new file mode 100644 index 0000000000..74b644808e --- /dev/null +++ b/frontend/app_flowy/lib/user/application/prelude.dart @@ -0,0 +1,4 @@ +export './auth_service.dart'; +export './sign_in_bloc.dart'; +export './sign_up_bloc.dart'; +export './splash_bloc.dart'; diff --git a/frontend/app_flowy/lib/user/application/sign_in_bloc.dart b/frontend/app_flowy/lib/user/application/sign_in_bloc.dart index 25aa66cc50..e0f5bed605 100644 --- a/frontend/app_flowy/lib/user/application/sign_in_bloc.dart +++ b/frontend/app_flowy/lib/user/application/sign_in_bloc.dart @@ -54,14 +54,14 @@ class SignInBloc extends Bloc { } @freezed -abstract class SignInEvent with _$SignInEvent { +class SignInEvent with _$SignInEvent { const factory SignInEvent.signedInWithUserEmailAndPassword() = SignedInWithUserEmailAndPassword; const factory SignInEvent.emailChanged(String email) = EmailChanged; const factory SignInEvent.passwordChanged(String password) = PasswordChanged; } @freezed -abstract class SignInState with _$SignInState { +class SignInState with _$SignInState { const factory SignInState({ String? email, String? password, diff --git a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart index 11acd1d385..2efc82d3c7 100644 --- a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart +++ b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart @@ -15,11 +15,11 @@ class SignUpBloc extends Bloc { on((event, emit) async { await event.map(signUpWithUserEmailAndPassword: (e) async { await _performActionOnSignUp(emit); - }, emailChanged: (EmailChanged value) async { + }, emailChanged: (_EmailChanged value) async { emit(state.copyWith(email: value.email, emailError: none(), successOrFail: none())); - }, passwordChanged: (PasswordChanged value) async { + }, passwordChanged: (_PasswordChanged value) async { emit(state.copyWith(password: value.password, passwordError: none(), successOrFail: none())); - }, repeatPasswordChanged: (RepeatPasswordChanged value) async { + }, repeatPasswordChanged: (_RepeatPasswordChanged value) async { emit(state.copyWith(repeatedPassword: value.password, repeatPasswordError: none(), successOrFail: none())); }); }); @@ -104,9 +104,9 @@ class SignUpBloc extends Bloc { @freezed class SignUpEvent with _$SignUpEvent { const factory SignUpEvent.signUpWithUserEmailAndPassword() = SignUpWithUserEmailAndPassword; - const factory SignUpEvent.emailChanged(String email) = EmailChanged; - const factory SignUpEvent.passwordChanged(String password) = PasswordChanged; - const factory SignUpEvent.repeatPasswordChanged(String password) = RepeatPasswordChanged; + const factory SignUpEvent.emailChanged(String email) = _EmailChanged; + const factory SignUpEvent.passwordChanged(String password) = _PasswordChanged; + const factory SignUpEvent.repeatPasswordChanged(String password) = _RepeatPasswordChanged; } @freezed diff --git a/frontend/app_flowy/lib/user/domain/auth_state.dart b/frontend/app_flowy/lib/user/domain/auth_state.dart index b70383c0aa..96f2036e01 100644 --- a/frontend/app_flowy/lib/user/domain/auth_state.dart +++ b/frontend/app_flowy/lib/user/domain/auth_state.dart @@ -4,7 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'auth_state.freezed.dart'; @freezed -abstract class AuthState with _$AuthState { +class AuthState with _$AuthState { const factory AuthState.authenticated(UserProfile userProfile) = Authenticated; const factory AuthState.unauthenticated(FlowyError error) = Unauthenticated; const factory AuthState.initial() = _Initial; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index ab844448dc..2199d59562 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -28,12 +28,12 @@ class CheckboxCellBloc extends Bloc { } @freezed -abstract class CheckboxCellEvent with _$CheckboxCellEvent { +class CheckboxCellEvent with _$CheckboxCellEvent { const factory CheckboxCellEvent.initial() = _InitialCell; } @freezed -abstract class CheckboxCellState with _$CheckboxCellState { +class CheckboxCellState with _$CheckboxCellState { const factory CheckboxCellState({ required Cell? cell, }) = _CheckboxCellState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart index dcb0461165..071757fdeb 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart @@ -28,12 +28,12 @@ class DateCellBloc extends Bloc { } @freezed -abstract class DateCellEvent with _$DateCellEvent { +class DateCellEvent with _$DateCellEvent { const factory DateCellEvent.initial() = _InitialCell; } @freezed -abstract class DateCellState with _$DateCellState { +class DateCellState with _$DateCellState { const factory DateCellState({ required Cell? cell, }) = _DateCellState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart index caa91fa408..e368c32c35 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart @@ -28,12 +28,12 @@ class NumberCellBloc extends Bloc { } @freezed -abstract class NumberCellEvent with _$NumberCellEvent { +class NumberCellEvent with _$NumberCellEvent { const factory NumberCellEvent.initial() = _InitialCell; } @freezed -abstract class NumberCellState with _$NumberCellState { +class NumberCellState with _$NumberCellState { const factory NumberCellState({ required Cell? cell, }) = _NumberCellState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 7f21a84fff..1a94d4ce69 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -28,12 +28,12 @@ class SelectionCellBloc extends Bloc { } @freezed -abstract class SelectionCellEvent with _$SelectionCellEvent { +class SelectionCellEvent with _$SelectionCellEvent { const factory SelectionCellEvent.initial() = _InitialCell; } @freezed -abstract class SelectionCellState with _$SelectionCellState { +class SelectionCellState with _$SelectionCellState { const factory SelectionCellState({ required Cell? cell, }) = _SelectionCellState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index 407cde3d2c..d999ea774d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -31,13 +31,13 @@ class TextCellBloc extends Bloc { } @freezed -abstract class TextCellEvent with _$TextCellEvent { +class TextCellEvent with _$TextCellEvent { const factory TextCellEvent.initial() = _InitialCell; const factory TextCellEvent.updateText(String text) = _UpdateText; } @freezed -abstract class TextCellState with _$TextCellState { +class TextCellState with _$TextCellState { const factory TextCellState({ required String content, }) = _TextCellState; diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart index 9f70646415..aa0d47e5d6 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -1,5 +1,6 @@ import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -16,9 +17,9 @@ class CreateFieldBloc extends Bloc { (event, emit) async { await event.map( initial: (_InitialField value) async { - final result = await service.getDefaultField(); + final result = await service.getEditFieldContext(FieldType.RichText); result.fold( - (field) => emit(state.copyWith(field: Some(field))), + (editContext) => emit(state.copyWith(editContext: Some(editContext))), (err) => Log.error(err), ); }, @@ -46,11 +47,11 @@ class CreateFieldEvent with _$CreateFieldEvent { class CreateFieldState with _$CreateFieldState { const factory CreateFieldState({ required String errorText, - required Option field, + required Option editContext, }) = _CreateFieldState; factory CreateFieldState.initial() => CreateFieldState( - field: none(), + editContext: none(), errorText: '', ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart index 0944bdd1bb..75a0a7c9bc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -9,7 +9,8 @@ part 'edit_field_bloc.freezed.dart'; class EditFieldBloc extends Bloc { final FieldService service; - EditFieldBloc({required Field field, required this.service}) : super(EditFieldState.initial(field)) { + EditFieldBloc({required Field field, required this.service}) + : super(EditFieldState.initial(EditFieldContext.create()..gridField = field)) { on( (event, emit) async { await event.map( @@ -43,12 +44,12 @@ class EditFieldEvent with _$EditFieldEvent { @freezed class EditFieldState with _$EditFieldState { const factory EditFieldState({ - required Field field, + required EditFieldContext editContext, required String errorText, }) = _EditFieldState; - factory EditFieldState.initial(Field field) => EditFieldState( - field: field, + factory EditFieldState.initial(EditFieldContext editContext) => EditFieldState( + editContext: editContext, errorText: '', ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index f63d8d5d5f..e3dfdf3ce9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -5,6 +5,7 @@ import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; class FieldService { @@ -12,9 +13,12 @@ class FieldService { FieldService({required this.gridId}); - Future> getDefaultField() { - final payload = GridId.create()..value = gridId; - return GridEventCreateDefaultField(payload).send(); + Future> getEditFieldContext(FieldType fieldType) { + final payload = CreateEditFieldContextParams.create() + ..gridId = gridId + ..fieldType = fieldType; + + return GridEventCreateEditFieldContext(payload).send(); } Future> createTextField( @@ -24,7 +28,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return createField(gridId, field, typeOptionData, startFieldId); + return createField(field, typeOptionData, startFieldId); } Future> createSingleSelectField( @@ -34,7 +38,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return createField(gridId, field, typeOptionData, startFieldId); + return createField(field, typeOptionData, startFieldId); } Future> createMultiSelectField( @@ -44,7 +48,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return createField(gridId, field, typeOptionData, startFieldId); + return createField(field, typeOptionData, startFieldId); } Future> createNumberField( @@ -54,7 +58,7 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return createField(gridId, field, typeOptionData, startFieldId); + return createField(field, typeOptionData, startFieldId); } Future> createDateField( @@ -64,11 +68,10 @@ class FieldService { String? startFieldId, ) { final typeOptionData = typeOption.writeToBuffer(); - return createField(gridId, field, typeOptionData, startFieldId); + return createField(field, typeOptionData, startFieldId); } Future> createField( - String gridId, Field field, Uint8List? typeOptionData, String? startFieldId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart new file mode 100644 index 0000000000..a6042c52e3 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -0,0 +1,61 @@ +import 'dart:typed_data'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; + +part 'switch_field_type_bloc.freezed.dart'; + +class SwitchFieldTypeBloc extends Bloc { + SwitchFieldTypeBloc(EditFieldContext editContext) : super(SwitchFieldTypeState.initial(editContext)) { + on( + (event, emit) async { + await event.map( + toFieldType: (_ToFieldType value) async { + final fieldService = FieldService(gridId: state.gridId); + final result = await fieldService.getEditFieldContext(value.fieldType); + result.fold( + (newEditContext) { + emit( + state.copyWith( + field: newEditContext.gridField, + typeOptionData: Uint8List.fromList(newEditContext.typeOptionData), + ), + ); + }, + (err) => Log.error(err), + ); + }, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class SwitchFieldTypeEvent with _$SwitchFieldTypeEvent { + const factory SwitchFieldTypeEvent.toFieldType(FieldType fieldType) = _ToFieldType; +} + +@freezed +class SwitchFieldTypeState with _$SwitchFieldTypeState { + const factory SwitchFieldTypeState({ + required String gridId, + required Field field, + required Uint8List typeOptionData, + }) = _SwitchFieldTypeState; + + factory SwitchFieldTypeState.initial(EditFieldContext editContext) => SwitchFieldTypeState( + gridId: editContext.gridId, + field: editContext.gridField, + typeOptionData: Uint8List.fromList(editContext.typeOptionData), + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart new file mode 100644 index 0000000000..78b22b078b --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart @@ -0,0 +1,39 @@ +import 'dart:typed_data'; + +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'date_bloc.freezed.dart'; + +class DateTypeOptionBloc extends Bloc { + DateTypeOptionBloc() : super(DateTypeOptionState.initial()) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) async {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class DateTypeOptionEvent with _$DateTypeOptionEvent { + const factory DateTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField; +} + +@freezed +class DateTypeOptionState with _$DateTypeOptionState { + const factory DateTypeOptionState() = _DateTypeOptionState; + + factory DateTypeOptionState.initial() => DateTypeOptionState(); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart new file mode 100644 index 0000000000..21043f003b --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart @@ -0,0 +1,39 @@ +import 'dart:typed_data'; + +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'number_bloc.freezed.dart'; + +class NumberTypeOptionBloc extends Bloc { + NumberTypeOptionBloc() : super(NumberTypeOptionState.initial()) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) async {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class NumberTypeOptionEvent with _$NumberTypeOptionEvent { + const factory NumberTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField; +} + +@freezed +class NumberTypeOptionState with _$NumberTypeOptionState { + const factory NumberTypeOptionState() = _NumberTypeOptionState; + + factory NumberTypeOptionState.initial() => NumberTypeOptionState(); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart new file mode 100644 index 0000000000..ac6d3fb6d4 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart @@ -0,0 +1,39 @@ +import 'dart:typed_data'; + +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'selection_bloc.freezed.dart'; + +class SelectionTypeOptionBloc extends Bloc { + SelectionTypeOptionBloc() : super(SelectionTypeOptionState.initial()) { + on( + (event, emit) async { + await event.map( + initial: (_InitialField value) async {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class SelectionTypeOptionEvent with _$SelectionTypeOptionEvent { + const factory SelectionTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField; +} + +@freezed +class SelectionTypeOptionState with _$SelectionTypeOptionState { + const factory SelectionTypeOptionState() = _SelectionTypeOptionState; + + factory SelectionTypeOptionState.initial() => SelectionTypeOptionState(); +} 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 63a2a19ec7..ea090a086a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -124,7 +124,7 @@ class GridBloc extends Bloc { } @freezed -abstract class GridEvent with _$GridEvent { +class GridEvent with _$GridEvent { const factory GridEvent.initial() = InitialGrid; const factory GridEvent.rename(String gridId, String name) = _Rename; const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; @@ -135,7 +135,7 @@ abstract class GridEvent with _$GridEvent { } @freezed -abstract class GridState with _$GridState { +class GridState with _$GridState { const factory GridState({ required GridLoadingState loadingState, required List fields, diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index a1c60d7efb..38135f75f6 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -3,10 +3,20 @@ export 'row/row_bloc.dart'; export 'row/row_service.dart'; export 'grid_service.dart'; export 'data.dart'; + +// Field export 'field/field_service.dart'; export 'field/grid_header_bloc.dart'; export 'field/edit_field_bloc.dart'; export 'field/create_field_bloc.dart'; +export 'field/switch_field_type_bloc.dart'; + +// Field Type Option +export 'field/type_option/date_bloc.dart'; +export 'field/type_option/number_bloc.dart'; +export 'field/type_option/selection_bloc.dart'; + +// Cell export 'cell_bloc/text_cell_bloc.dart'; export 'cell_bloc/number_cell_bloc.dart'; export 'cell_bloc/selection_cell_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index a30bea39ee..b7e4f40c5d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -88,7 +88,7 @@ class RowBloc extends Bloc { } @freezed -abstract class RowEvent with _$RowEvent { +class RowEvent with _$RowEvent { const factory RowEvent.initial() = _InitialRow; const factory RowEvent.createRow() = _CreateRow; const factory RowEvent.activeRow() = _ActiveRow; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart index 7aa412589e..d612110ecb 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart @@ -22,7 +22,7 @@ Widget buildGridCell(GridCellData cellData) { case FieldType.SingleSelect: return SingleSelectCell(cellContext: cellData); default: - return const BlankCell(); + throw UnimplementedError; } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 0b8e2c3eac..8ac70b3741 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -37,8 +37,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate { @override void didRemove() async { - await _createFieldBloc.close(); - // TODO: implement didRemove + _createFieldBloc.add(const CreateFieldEvent.done()); } } @@ -52,16 +51,16 @@ class _CreateFieldPannelWidget extends StatelessWidget { value: createFieldBloc, child: BlocBuilder( builder: (context, state) { - return state.field.fold( + return state.editContext.fold( () => const SizedBox(), - (field) => ListView( + (editContext) => ListView( shrinkWrap: true, children: [ const FlowyText.medium("Edit property", fontSize: 12), const VSpace(10), - _FieldNameTextField(field), + _FieldNameTextField(editContext.gridField), const VSpace(10), - _FieldTypeSwitcher(field), + _FieldTypeSwitcher(editContext), const VSpace(10), ], ), @@ -73,19 +72,12 @@ class _CreateFieldPannelWidget extends StatelessWidget { } class _FieldTypeSwitcher extends StatelessWidget { - final Field field; - const _FieldTypeSwitcher(this.field, {Key? key}) : super(key: key); + final EditFieldContext editContext; + const _FieldTypeSwitcher(this.editContext, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return FieldTypeSwitcher( - field: field, - onSelectField: _switchToFieldType, - ); - } - - void _switchToFieldType(FieldType fieldType) { - throw UnimplementedError(); + return FieldTypeSwitcher(editContext: editContext); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index c199553cc6..ed26ecbd64 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -59,15 +59,11 @@ class _FieldTypeSwitcher extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final field = context.read().state.field; - return FieldTypeSwitcher(field: field, onSelectField: _switchToFieldType); + final editContext = context.read().state.editContext; + return FieldTypeSwitcher(editContext: editContext); }, ); } - - void _switchToFieldType(FieldType fieldType) { - throw UnimplementedError(); - } } class _FieldNameTextField extends StatelessWidget { @@ -76,10 +72,10 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: ((previous, current) => previous.field.name == current.field.name), + buildWhen: ((previous, current) => previous.editContext.gridField.name == current.editContext.gridField.name), builder: (context, state) { return FieldNameTextField( - name: state.field.name, + name: state.editContext.gridField.name, errorText: state.errorText, onNameChanged: (newName) { context.read().add(EditFieldEvent.updateFieldName(newName)); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart index 49f0513099..80cb327379 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_name_input.dart @@ -19,7 +19,7 @@ class FieldNameTextField extends StatelessWidget { final theme = context.watch(); return RoundedInputField( height: 36, - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500), initialValue: name, normalBorderColor: theme.shader4, errorBorderColor: theme.red, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index 61b7c49b2d..df6ecf0d6a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -1,3 +1,7 @@ +import 'dart:typed_data'; + +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -5,34 +9,217 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; typedef SelectFieldCallback = void Function(FieldType); class FieldTypeSwitcher extends StatelessWidget { - final Field field; - final SelectFieldCallback onSelectField; + final EditFieldContext editContext; + const FieldTypeSwitcher({ - required this.field, - required this.onSelectField, + required this.editContext, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { - final theme = context.watch(); + return BlocProvider( + create: (context) => getIt(param1: editContext), + child: BlocBuilder( + builder: (context, state) { + List children = [ + _switchFieldTypeButton(context, state.field), + ]; + final builder = _makeTypeOptionBuild( + state.field.fieldType, + state.typeOptionData, + ); + + final typeOptionWidget = builder.customWidget; + if (typeOptionWidget != null) { + children.add(typeOptionWidget); + } + + return ListView( + shrinkWrap: true, + children: children, + ); + }, + ), + ); + } + + Widget _switchFieldTypeButton(BuildContext context, Field field) { + final theme = context.watch(); return SizedBox( height: 36, child: FlowyButton( text: FlowyText.medium(field.fieldType.title(), fontSize: 12), padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), hoverColor: theme.hover, - onTap: () => FieldTypeList.show(context, onSelectField), + onTap: () => FieldTypeList.show(context, (fieldType) { + context.read().add(SwitchFieldTypeEvent.toFieldType(fieldType)); + }), leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), rightIcon: svg("grid/more", color: theme.iconColor), ), ); } } + +abstract class TypeOptionBuilder { + Uint8List? get typeOptionData; + Widget? get customWidget; +} + +abstract class TypeOptionWidget extends StatelessWidget { + const TypeOptionWidget({Key? key}) : super(key: key); +} + +TypeOptionBuilder _makeTypeOptionBuild(FieldType fieldType, Uint8List typeOptionData) { + switch (fieldType) { + case FieldType.Checkbox: + return CheckboxTypeOptionBuilder(typeOptionData); + case FieldType.DateTime: + return DateTypeOptionBuilder(typeOptionData); + case FieldType.MultiSelect: + return MultiSelectTypeOptionBuilder(typeOptionData); + case FieldType.Number: + return NumberTypeOptionBuilder(typeOptionData); + case FieldType.RichText: + return RichTextTypeOptionBuilder(typeOptionData); + case FieldType.SingleSelect: + return SingleSelectTypeOptionBuilder(typeOptionData); + default: + throw UnimplementedError; + } +} + +class RichTextTypeOptionBuilder extends TypeOptionBuilder { + RichTextTypeOption typeOption; + + RichTextTypeOptionBuilder(Uint8List typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => typeOption.writeToBuffer(); + + @override + Widget? get customWidget => null; +} + +class NumberTypeOptionBuilder extends TypeOptionBuilder { + NumberTypeOption typeOption; + + NumberTypeOptionBuilder(Uint8List typeOptionData) : typeOption = NumberTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => typeOption.writeToBuffer(); + + @override + Widget? get customWidget => const NumberTypeOptionWidget(); +} + +class NumberTypeOptionWidget extends TypeOptionWidget { + const NumberTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(), + ); + } +} + +class DateTypeOptionBuilder extends TypeOptionBuilder { + DateTypeOption typeOption; + + DateTypeOptionBuilder(Uint8List typeOptionData) : typeOption = DateTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => typeOption.writeToBuffer(); + + @override + Widget? get customWidget => const DateTypeOptionWidget(); +} + +class DateTypeOptionWidget extends TypeOptionWidget { + const DateTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(), + ); + } +} + +class CheckboxTypeOptionBuilder extends TypeOptionBuilder { + CheckboxTypeOption typeOption; + + CheckboxTypeOptionBuilder(Uint8List typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => throw UnimplementedError(); + + @override + Widget? get customWidget => null; +} + +class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { + SingleSelectTypeOption typeOption; + + SingleSelectTypeOptionBuilder(Uint8List typeOptionData) + : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => typeOption.writeToBuffer(); + + @override + Widget? get customWidget => const SingleSelectTypeOptionWidget(); +} + +class SingleSelectTypeOptionWidget extends TypeOptionWidget { + const SingleSelectTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(), + ); + } +} + +class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { + MultiSelectTypeOption typeOption; + + MultiSelectTypeOptionBuilder(Uint8List typeOptionData) + : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); + + @override + Uint8List? get typeOptionData => typeOption.writeToBuffer(); + + @override + Widget? get customWidget => const MultiSelectTypeOptionWidget(); +} + +class MultiSelectTypeOptionWidget extends TypeOptionWidget { + const MultiSelectTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index 25ff77494d..25481fce09 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -104,8 +104,7 @@ extension FieldTypeListExtension on FieldType { case FieldType.SingleSelect: return "grid/field/single_select"; default: - assert(false, "Unsupport field type"); - return "grid/field/text"; + throw UnimplementedError; } } @@ -124,8 +123,7 @@ extension FieldTypeListExtension on FieldType { case FieldType.SingleSelect: return LocaleKeys.grid_field_singleSelectFieldName.tr(); default: - assert(false, "Unsupport field type"); - return LocaleKeys.grid_field_textFieldName.tr(); + throw UnimplementedError; } } } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart index bee123d248..b1f18b6695 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart @@ -21,7 +21,7 @@ class OverlayContainer extends StatelessWidget { type: MaterialType.transparency, child: Container( padding: padding, - decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.1)), + decoration: FlowyDecoration.decoration(theme.surface, theme.shadowColor.withOpacity(0.15)), constraints: constraints, child: child, ), diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index c5f7002138..88f404d4f6 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -86,18 +86,18 @@ class GridEventCreateField { } } -class GridEventCreateDefaultField { - GridId request; - GridEventCreateDefaultField(this.request); +class GridEventCreateEditFieldContext { + CreateEditFieldContextParams request; + GridEventCreateEditFieldContext(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() - ..event = GridEvent.CreateDefaultField.toString() + ..event = GridEvent.CreateEditFieldContext.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( - (okBytes) => left(Field.fromBuffer(okBytes)), + (okBytes) => left(EditFieldContext.fromBuffer(okBytes)), (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } 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 ce247ef7d6..4ea447d729 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 @@ -252,6 +252,144 @@ class FieldOrder extends $pb.GeneratedMessage { void clearFieldId() => clearField(1); } +class CreateEditFieldContextParams extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateEditFieldContextParams', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..e<$0.FieldType>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values) + ..hasRequiredFields = false + ; + + CreateEditFieldContextParams._() : super(); + factory CreateEditFieldContextParams({ + $core.String? gridId, + $0.FieldType? fieldType, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (fieldType != null) { + _result.fieldType = fieldType; + } + return _result; + } + factory CreateEditFieldContextParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateEditFieldContextParams.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') + CreateEditFieldContextParams clone() => CreateEditFieldContextParams()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CreateEditFieldContextParams copyWith(void Function(CreateEditFieldContextParams) updates) => super.copyWith((message) => updates(message as CreateEditFieldContextParams)) as CreateEditFieldContextParams; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateEditFieldContextParams create() => CreateEditFieldContextParams._(); + CreateEditFieldContextParams createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CreateEditFieldContextParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateEditFieldContextParams? _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) + $0.FieldType get fieldType => $_getN(1); + @$pb.TagNumber(2) + set fieldType($0.FieldType v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasFieldType() => $_has(1); + @$pb.TagNumber(2) + void clearFieldType() => clearField(2); +} + +class EditFieldContext extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditFieldContext', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridField', subBuilder: Field.create) + ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + EditFieldContext._() : super(); + factory EditFieldContext({ + $core.String? gridId, + Field? gridField, + $core.List<$core.int>? typeOptionData, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (gridField != null) { + _result.gridField = gridField; + } + if (typeOptionData != null) { + _result.typeOptionData = typeOptionData; + } + return _result; + } + factory EditFieldContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory EditFieldContext.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') + EditFieldContext clone() => EditFieldContext()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + EditFieldContext copyWith(void Function(EditFieldContext) updates) => super.copyWith((message) => updates(message as EditFieldContext)) as EditFieldContext; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static EditFieldContext create() => EditFieldContext._(); + EditFieldContext createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static EditFieldContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static EditFieldContext? _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) + Field get gridField => $_getN(1); + @$pb.TagNumber(2) + set gridField(Field v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasGridField() => $_has(1); + @$pb.TagNumber(2) + void clearGridField() => clearField(2); + @$pb.TagNumber(2) + Field ensureGridField() => $_ensure(1); + + @$pb.TagNumber(3) + $core.List<$core.int> get typeOptionData => $_getN(2); + @$pb.TagNumber(3) + set typeOptionData($core.List<$core.int> v) { $_setBytes(2, v); } + @$pb.TagNumber(3) + $core.bool hasTypeOptionData() => $_has(2); + @$pb.TagNumber(3) + void clearTypeOptionData() => clearField(3); +} + class RepeatedField extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RepeatedField', createEmptyInstance: create) ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Field.create) 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 adb25af959..a7dc3255c8 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 @@ -46,6 +46,29 @@ const FieldOrder$json = const { /// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElk'); +@$core.Deprecated('Use createEditFieldContextParamsDescriptor instead') +const CreateEditFieldContextParams$json = const { + '1': 'CreateEditFieldContextParams', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field_type', '3': 2, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'}, + ], +}; + +/// Descriptor for `CreateEditFieldContextParams`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createEditFieldContextParamsDescriptor = $convert.base64Decode('ChxDcmVhdGVFZGl0RmllbGRDb250ZXh0UGFyYW1zEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIpCgpmaWVsZF90eXBlGAIgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGU='); +@$core.Deprecated('Use editFieldContextDescriptor instead') +const EditFieldContext$json = const { + '1': 'EditFieldContext', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'grid_field', '3': 2, '4': 1, '5': 11, '6': '.Field', '10': 'gridField'}, + const {'1': 'type_option_data', '3': 3, '4': 1, '5': 12, '10': 'typeOptionData'}, + ], +}; + +/// Descriptor for `EditFieldContext`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List editFieldContextDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRDb250ZXh0EhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIlCgpncmlkX2ZpZWxkGAIgASgLMgYuRmllbGRSCWdyaWRGaWVsZBIoChB0eXBlX29wdGlvbl9kYXRhGAMgASgMUg50eXBlT3B0aW9uRGF0YQ=='); @$core.Deprecated('Use repeatedFieldDescriptor instead') const RepeatedField$json = const { '1': 'RepeatedField', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 7007f1f6c8..74cb74e42e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -15,7 +15,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields'); static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); - static const GridEvent CreateDefaultField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultField'); + static const GridEvent CreateEditFieldContext = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); @@ -26,7 +26,7 @@ class GridEvent extends $pb.ProtobufEnum { GetFields, UpdateField, CreateField, - CreateDefaultField, + CreateEditFieldContext, CreateRow, GetRow, UpdateCell, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 1d94f8227a..386cdd5bcb 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -17,7 +17,7 @@ const GridEvent$json = const { const {'1': 'GetFields', '2': 10}, const {'1': 'UpdateField', '2': 11}, const {'1': 'CreateField', '2': 12}, - const {'1': 'CreateDefaultField', '2': 13}, + const {'1': 'CreateEditFieldContext', '2': 13}, const {'1': 'CreateRow', '2': 21}, const {'1': 'GetRow', '2': 22}, const {'1': 'UpdateCell', '2': 30}, @@ -25,4 +25,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhYKEkNyZWF0ZURlZmF1bHRGaWVsZBANEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhoKFkNyZWF0ZUVkaXRGaWVsZENvbnRleHQQDRINCglDcmVhdGVSb3cQFRIKCgZHZXRSb3cQFhIOCgpVcGRhdGVDZWxsEB4='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 39d6bf2e95..fb21efdd37 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,8 +1,9 @@ use crate::manager::GridManager; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{ - CellMetaChangeset, CreateFieldPayload, CreateRowPayload, Field, FieldChangeset, Grid, GridId, QueryFieldPayload, - QueryGridBlocksPayload, QueryRowPayload, RepeatedField, RepeatedGridBlock, Row, + CellMetaChangeset, CreateEditFieldContextParams, CreateFieldPayload, CreateRowPayload, EditFieldContext, Field, + FieldChangeset, Grid, GridId, QueryFieldPayload, QueryGridBlocksPayload, QueryRowPayload, RepeatedField, + RepeatedGridBlock, Row, }; use flowy_grid_data_model::parser::{ CreateFieldParams, CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams, @@ -72,14 +73,23 @@ pub(crate) async fn create_field_handler( } #[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn create_default_field_handler( - data: Data, +pub(crate) async fn create_field_edit_context_handler( + data: Data, manager: AppData>, -) -> DataResult { - let grid_id: GridId = data.into_inner(); - let editor = manager.get_grid_editor(grid_id.as_ref())?; - let field = editor.make_default_field().await?; - data_result(field) +) -> DataResult { + let params: CreateEditFieldContextParams = data.into_inner(); + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let field_meta = editor.make_field_meta_from_ty(¶ms.field_type).await?; + let type_option_data = field_meta.type_option.as_bytes().to_vec(); + let field: Field = field_meta.into(); + + let edit_context = EditFieldContext { + grid_id: params.grid_id, + grid_field: field, + type_option_data, + }; + + data_result(edit_context) } #[tracing::instrument(level = "debug", skip(data, manager), err)] diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 8c08d547ff..b9fb842151 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -13,7 +13,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) - .event(GridEvent::CreateDefaultField, create_default_field_handler) + .event(GridEvent::CreateEditFieldContext, create_field_edit_context_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) .event(GridEvent::UpdateCell, update_cell_handler); @@ -39,8 +39,8 @@ pub enum GridEvent { #[event(input = "CreateFieldPayload")] CreateField = 12, - #[event(input = "GridId", output = "Field")] - CreateDefaultField = 13, + #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")] + CreateEditFieldContext = 13, #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 21, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 4e0008c7a0..fb0e652790 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -30,7 +30,7 @@ pub enum GridEvent { GetFields = 10, UpdateField = 11, CreateField = 12, - CreateDefaultField = 13, + CreateEditFieldContext = 13, CreateRow = 21, GetRow = 22, UpdateCell = 30, @@ -48,7 +48,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 10 => ::std::option::Option::Some(GridEvent::GetFields), 11 => ::std::option::Option::Some(GridEvent::UpdateField), 12 => ::std::option::Option::Some(GridEvent::CreateField), - 13 => ::std::option::Option::Some(GridEvent::CreateDefaultField), + 13 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), 21 => ::std::option::Option::Some(GridEvent::CreateRow), 22 => ::std::option::Option::Some(GridEvent::GetRow), 30 => ::std::option::Option::Some(GridEvent::UpdateCell), @@ -63,7 +63,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::GetFields, GridEvent::UpdateField, GridEvent::CreateField, - GridEvent::CreateDefaultField, + GridEvent::CreateEditFieldContext, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, @@ -95,11 +95,11 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xa3\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xa7\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ - \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x16\n\x12Cr\ - eateDefaultField\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\ - \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ + \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x1a\n\x16Cr\ + eateEditFieldContext\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\ + \x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 894b2a111a..f6a07a0119 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -6,7 +6,7 @@ enum GridEvent { GetFields = 10; UpdateField = 11; CreateField = 12; - CreateDefaultField = 13; + CreateEditFieldContext = 13; CreateRow = 21; GetRow = 22; UpdateCell = 30; 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 d81b96a1ad..3089836220 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -62,11 +62,10 @@ impl ClientGridEditor { Ok(()) } - pub async fn make_default_field(&self) -> FlowyResult { - let field_type = FieldType::default(); + pub async fn make_field_meta_from_ty(&self, field_type: &FieldType) -> FlowyResult { let name = format!("Property {}", self.pad.read().await.fields().len()); let field_meta = FieldBuilder::from_field_type(&field_type).name(&name).build(); - Ok(field_meta.into()) + Ok(field_meta) } pub async fn contain_field(&self, field_id: &str) -> bool { 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 c421dcac64..6d17fbca0f 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -67,6 +67,27 @@ impl std::convert::From for Field { } } +#[derive(Debug, Default, ProtoBuf)] +pub struct CreateEditFieldContextParams { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field_type: FieldType, +} + +#[derive(Debug, Default, ProtoBuf)] +pub struct EditFieldContext { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub grid_field: Field, + + #[pb(index = 3)] + pub type_option_data: Vec, +} + #[derive(Debug, Default, ProtoBuf)] pub struct RepeatedField { #[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 5a8dced09b..a6afa46d9a 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 @@ -818,6 +818,454 @@ impl ::protobuf::reflect::ProtobufValue for FieldOrder { } } +#[derive(PartialEq,Clone,Default)] +pub struct CreateEditFieldContextParams { + // message fields + pub grid_id: ::std::string::String, + pub field_type: super::meta::FieldType, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CreateEditFieldContextParams { + fn default() -> &'a CreateEditFieldContextParams { + ::default_instance() + } +} + +impl CreateEditFieldContextParams { + pub fn new() -> CreateEditFieldContextParams { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // .FieldType field_type = 2; + + + pub fn get_field_type(&self) -> super::meta::FieldType { + self.field_type + } + pub fn clear_field_type(&mut self) { + self.field_type = super::meta::FieldType::RichText; + } + + // Param is passed by value, moved + pub fn set_field_type(&mut self, v: super::meta::FieldType) { + self.field_type = v; + } +} + +impl ::protobuf::Message for CreateEditFieldContextParams { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 2, &mut self.unknown_fields)? + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if self.field_type != super::meta::FieldType::RichText { + my_size += ::protobuf::rt::enum_size(2, self.field_type); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if self.field_type != super::meta::FieldType::RichText { + os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.field_type))?; + } + 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() -> CreateEditFieldContextParams { + CreateEditFieldContextParams::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>( + "grid_id", + |m: &CreateEditFieldContextParams| { &m.grid_id }, + |m: &mut CreateEditFieldContextParams| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "field_type", + |m: &CreateEditFieldContextParams| { &m.field_type }, + |m: &mut CreateEditFieldContextParams| { &mut m.field_type }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateEditFieldContextParams", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CreateEditFieldContextParams { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateEditFieldContextParams::new) + } +} + +impl ::protobuf::Clear for CreateEditFieldContextParams { + fn clear(&mut self) { + self.grid_id.clear(); + self.field_type = super::meta::FieldType::RichText; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CreateEditFieldContextParams { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CreateEditFieldContextParams { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct EditFieldContext { + // message fields + pub grid_id: ::std::string::String, + pub grid_field: ::protobuf::SingularPtrField, + pub type_option_data: ::std::vec::Vec, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a EditFieldContext { + fn default() -> &'a EditFieldContext { + ::default_instance() + } +} + +impl EditFieldContext { + pub fn new() -> EditFieldContext { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // .Field grid_field = 2; + + + pub fn get_grid_field(&self) -> &Field { + self.grid_field.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_grid_field(&mut self) { + self.grid_field.clear(); + } + + pub fn has_grid_field(&self) -> bool { + self.grid_field.is_some() + } + + // Param is passed by value, moved + pub fn set_grid_field(&mut self, v: Field) { + self.grid_field = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_field(&mut self) -> &mut Field { + if self.grid_field.is_none() { + self.grid_field.set_default(); + } + self.grid_field.as_mut().unwrap() + } + + // Take field + pub fn take_grid_field(&mut self) -> Field { + self.grid_field.take().unwrap_or_else(|| Field::new()) + } + + // bytes type_option_data = 3; + + + pub fn get_type_option_data(&self) -> &[u8] { + &self.type_option_data + } + pub fn clear_type_option_data(&mut self) { + self.type_option_data.clear(); + } + + // Param is passed by value, moved + pub fn set_type_option_data(&mut self, v: ::std::vec::Vec) { + self.type_option_data = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_type_option_data(&mut self) -> &mut ::std::vec::Vec { + &mut self.type_option_data + } + + // Take field + pub fn take_type_option_data(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.type_option_data, ::std::vec::Vec::new()) + } +} + +impl ::protobuf::Message for EditFieldContext { + fn is_initialized(&self) -> bool { + for v in &self.grid_field { + 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_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.grid_field)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.type_option_data)?; + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if let Some(ref v) = self.grid_field.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if !self.type_option_data.is_empty() { + my_size += ::protobuf::rt::bytes_size(3, &self.type_option_data); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if let Some(ref v) = self.grid_field.as_ref() { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if !self.type_option_data.is_empty() { + os.write_bytes(3, &self.type_option_data)?; + } + 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() -> EditFieldContext { + EditFieldContext::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>( + "grid_id", + |m: &EditFieldContext| { &m.grid_id }, + |m: &mut EditFieldContext| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "grid_field", + |m: &EditFieldContext| { &m.grid_field }, + |m: &mut EditFieldContext| { &mut m.grid_field }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "type_option_data", + |m: &EditFieldContext| { &m.type_option_data }, + |m: &mut EditFieldContext| { &mut m.type_option_data }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "EditFieldContext", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static EditFieldContext { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(EditFieldContext::new) + } +} + +impl ::protobuf::Clear for EditFieldContext { + fn clear(&mut self) { + self.grid_id.clear(); + self.grid_field.clear(); + self.type_option_data.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for EditFieldContext { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for EditFieldContext { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct RepeatedField { // message fields @@ -4418,21 +4866,26 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\ \x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\ \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\ - \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"-\n\rRepeatedField\ - \x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Re\ - peatedFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\ - \x05items\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05ro\ - wId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06he\ - ight\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\ - \x18\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\ - \x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\ - \x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03k\ - ey\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\ - \x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\ - \x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\ - \x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockO\ - rder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBloc\ - k\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ + \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFiel\ + dContextParams\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\ + \nfield_type\x18\x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditF\ + ieldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ng\ + rid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_opt\ + ion_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\ + \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\ + edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\ + ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\ + \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\ + t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\ + \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\ + \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\ + \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ + .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ + \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ + items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ + \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ + \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\ 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 b1252fc72e..ec109f580f 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 @@ -18,6 +18,15 @@ message Field { message FieldOrder { string field_id = 1; } +message CreateEditFieldContextParams { + string grid_id = 1; + FieldType field_type = 2; +} +message EditFieldContext { + string grid_id = 1; + Field grid_field = 2; + bytes type_option_data = 3; +} message RepeatedField { repeated Field items = 1; } From 28948e567c1eee815e4250cd240ef9094e999f14 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 25 Mar 2022 20:55:56 +0800 Subject: [PATCH 09/47] fix: serde type option data --- .../flowy-grid-data-model/meta.pb.dart | 16 +-- .../flowy-grid-data-model/meta.pbjson.dart | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 9 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 2 +- frontend/rust-lib/flowy-grid/src/macros.rs | 34 ++++- .../src/services/field/field_builder.rs | 81 ++++++++---- .../type_options/checkbox_type_option.rs | 14 +- .../field/type_options/date_type_option.rs | 14 +- .../field/type_options/number_type_option.rs | 13 +- .../type_options/selection_type_option.rs | 25 +++- .../field/type_options/text_type_option.rs | 14 +- .../flowy-grid/src/services/grid_editor.rs | 35 +++-- .../flowy-grid/tests/grid/grid_test.rs | 2 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 4 +- .../src/entities/meta.rs | 4 +- .../src/protobuf/model/meta.rs | 120 +++++++++--------- .../src/protobuf/proto/meta.proto | 2 +- .../src/client_grid/grid_meta_pad.rs | 36 ++---- 18 files changed, 264 insertions(+), 165 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index 24f3409349..d76dac347c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -215,7 +215,7 @@ class FieldMeta extends $pb.GeneratedMessage { ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOption') + ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionJson') ..hasRequiredFields = false ; @@ -228,7 +228,7 @@ class FieldMeta extends $pb.GeneratedMessage { $core.bool? frozen, $core.bool? visibility, $core.int? width, - $core.String? typeOption, + $core.String? typeOptionJson, }) { final _result = create(); if (id != null) { @@ -252,8 +252,8 @@ class FieldMeta extends $pb.GeneratedMessage { if (width != null) { _result.width = width; } - if (typeOption != null) { - _result.typeOption = typeOption; + if (typeOptionJson != null) { + _result.typeOptionJson = typeOptionJson; } return _result; } @@ -342,13 +342,13 @@ class FieldMeta extends $pb.GeneratedMessage { void clearWidth() => clearField(7); @$pb.TagNumber(8) - $core.String get typeOption => $_getSZ(7); + $core.String get typeOptionJson => $_getSZ(7); @$pb.TagNumber(8) - set typeOption($core.String v) { $_setString(7, v); } + set typeOptionJson($core.String v) { $_setString(7, v); } @$pb.TagNumber(8) - $core.bool hasTypeOption() => $_has(7); + $core.bool hasTypeOptionJson() => $_has(7); @$pb.TagNumber(8) - void clearTypeOption() => clearField(8); + void clearTypeOptionJson() => clearField(8); } enum FieldChangeset_OneOfName { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index cf69a051b1..cec14f8af9 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -69,12 +69,12 @@ const FieldMeta$json = const { const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'}, const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'}, const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'}, - const {'1': 'type_option', '3': 8, '4': 1, '5': 9, '10': 'typeOption'}, + const {'1': 'type_option_json', '3': 8, '4': 1, '5': 9, '10': 'typeOptionJson'}, ], }; /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSHwoLdHlwZV9vcHRpb24YCCABKAlSCnR5cGVPcHRpb24='); +final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSKAoQdHlwZV9vcHRpb25fanNvbhgIIAEoCVIOdHlwZU9wdGlvbkpzb24='); @$core.Deprecated('Use fieldChangesetDescriptor instead') const FieldChangeset$json = const { '1': 'FieldChangeset', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index fb21efdd37..84a526c164 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,4 +1,5 @@ use crate::manager::GridManager; +use crate::services::field::type_option_data_from_str; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{ CellMetaChangeset, CreateEditFieldContextParams, CreateFieldPayload, CreateRowPayload, EditFieldContext, Field, @@ -73,22 +74,20 @@ pub(crate) async fn create_field_handler( } #[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn create_field_edit_context_handler( +pub(crate) async fn create_edit_field_context_handler( data: Data, manager: AppData>, ) -> DataResult { let params: CreateEditFieldContextParams = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let field_meta = editor.make_field_meta_from_ty(¶ms.field_type).await?; - let type_option_data = field_meta.type_option.as_bytes().to_vec(); + let field_meta = editor.default_field_meta(¶ms.field_type).await?; + let type_option_data = type_option_data_from_str(&field_meta.type_option_json, &field_meta.field_type); let field: Field = field_meta.into(); - let edit_context = EditFieldContext { grid_id: params.grid_id, grid_field: field, type_option_data, }; - data_result(edit_context) } diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index b9fb842151..054e1f2328 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -13,7 +13,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) - .event(GridEvent::CreateEditFieldContext, create_field_edit_context_handler) + .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) .event(GridEvent::UpdateCell, update_cell_handler); diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index b4a9cf1531..f2970fb96c 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -1,3 +1,29 @@ +#[macro_export] +macro_rules! impl_into_box_type_option_builder { + ($target: ident) => { + impl std::convert::Into for $target { + fn into(self) -> Box { + Box::new(self) + } + } + }; +} + +macro_rules! impl_from_json_str_and_from_bytes { + ($target: ident,$type_option: ident) => { + impl $target { + pub fn from_json_str(s: &str) -> $target { + $target($type_option::from(s)) + } + + pub fn from_bytes(bytes: Bytes) -> $target { + let type_option = $type_option::try_from(bytes).unwrap_or($type_option::default()); + $target(type_option) + } + } + }; +} + #[macro_export] macro_rules! impl_from_and_to_type_option { ($target: ident, $field_type:expr) => { @@ -11,7 +37,13 @@ macro_rules! impl_from_field_type_option { ($target: ident) => { impl std::convert::From<&FieldMeta> for $target { fn from(field_meta: &FieldMeta) -> $target { - match serde_json::from_str(&field_meta.type_option) { + $target::from(field_meta.type_option_json.as_str()) + } + } + + impl std::convert::From<&str> for $target { + fn from(type_option_str: &str) -> $target { + match serde_json::from_str(type_option_str) { Ok(obj) => obj, Err(err) => { tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 64f5e40ee4..474a97e885 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,22 +1,26 @@ use crate::services::field::type_options::*; +use bytes::Bytes; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; pub struct FieldBuilder { field_meta: FieldMeta, - type_option_builder: Box, + type_option_builder: Box, } +pub type BoxTypeOptionBuilder = Box; + impl FieldBuilder { - pub fn new(type_option_builder: T) -> Self { + pub fn new>(type_option_builder: T) -> Self { + let type_option_builder = type_option_builder.into(); let field_meta = FieldMeta::new("", "", type_option_builder.field_type()); Self { field_meta, - type_option_builder: Box::new(type_option_builder), + type_option_builder, } } pub fn from_field_type(field_type: &FieldType) -> Self { - let type_option_builder = type_option_builder_from_type(field_type); + let type_option_builder = default_type_option_builder_from_type(field_type); Self::new(type_option_builder) } @@ -45,39 +49,62 @@ impl FieldBuilder { self } - pub fn build(mut self) -> FieldMeta { + pub fn build(self) -> FieldMeta { debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); - let type_options = self.type_option_builder.build(); - self.field_meta.type_option = type_options; - self.field_meta + let mut field_meta = self.field_meta; + let type_option_json = self.type_option_builder.build_type_option_str(); + field_meta.type_option_json = type_option_json; + field_meta } } -pub trait TypeOptionsBuilder { +pub trait TypeOptionBuilder { fn field_type(&self) -> FieldType; - fn build(&self) -> String; + fn build_type_option_str(&self) -> String; + fn build_type_option_data(&self) -> Bytes; } -pub fn type_option_builder_from_type(field_type: &FieldType) -> Box { +pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box { + let s: String = match field_type { + FieldType::RichText => RichTextTypeOption::default().into(), + FieldType::Number => NumberTypeOption::default().into(), + FieldType::DateTime => DateTypeOption::default().into(), + FieldType::SingleSelect => SingleSelectTypeOption::default().into(), + FieldType::MultiSelect => MultiSelectTypeOption::default().into(), + FieldType::Checkbox => CheckboxTypeOption::default().into(), + }; + + type_option_builder_from_json_str(&s, field_type) +} + +pub fn type_option_builder_from_json_str(s: &str, field_type: &FieldType) -> Box { match field_type { - FieldType::RichText => Box::new(RichTextTypeOptionBuilder::default()), - FieldType::Number => Box::new(NumberTypeOptionBuilder::default()), - FieldType::DateTime => Box::new(DateTypeOptionBuilder::default()), - FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::default()), - FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::default()), - FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::default()), + FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_json_str(s)), + FieldType::Number => Box::new(NumberTypeOptionBuilder::from_json_str(s)), + FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_json_str(s)), + FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_json_str(s)), + FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_json_str(s)), + FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_json_str(s)), } } -impl TypeOptionsBuilder for Box -where - T: TypeOptionsBuilder + ?Sized, -{ - fn field_type(&self) -> FieldType { - (**self).field_type() - } - - fn build(&self) -> String { - (**self).build() +pub fn type_option_builder_from_bytes(bytes: Bytes, field_type: &FieldType) -> Box { + match field_type { + FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_bytes(bytes)), + FieldType::Number => Box::new(NumberTypeOptionBuilder::from_bytes(bytes)), + FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_bytes(bytes)), + FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_bytes(bytes)), + FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_bytes(bytes)), + FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_bytes(bytes)), } } + +pub fn type_option_data_from_str(s: &str, field_type: &FieldType) -> Vec { + let builder = type_option_builder_from_json_str(s, field_type); + builder.build_type_option_data().to_vec() +} + +pub fn type_option_json_str_from_bytes(bytes: Vec, field_type: &FieldType) -> String { + let builder = type_option_builder_from_bytes(Bytes::from(bytes), field_type); + builder.build_type_option_str() +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 08ae9f79c8..e150b9f96d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,6 +1,7 @@ use crate::impl_from_and_to_type_option; -use crate::services::field::TypeOptionsBuilder; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; +use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; @@ -8,6 +9,9 @@ use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); +impl_into_box_type_option_builder!(CheckboxTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(CheckboxTypeOptionBuilder, CheckboxTypeOption); + impl CheckboxTypeOptionBuilder { pub fn set_selected(mut self, is_selected: bool) -> Self { self.0.is_selected = is_selected; @@ -15,14 +19,18 @@ impl CheckboxTypeOptionBuilder { } } -impl TypeOptionsBuilder for CheckboxTypeOptionBuilder { +impl TypeOptionBuilder for CheckboxTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 20d94c8ca8..4e2a50ea33 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,5 +1,6 @@ use crate::impl_from_and_to_type_option; use crate::services::row::CellDataSerde; +use bytes::Bytes; use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; @@ -8,7 +9,7 @@ use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; -use crate::services::field::TypeOptionsBuilder; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use strum_macros::EnumIter; // Date @@ -64,6 +65,9 @@ impl CellDataSerde for DateTypeOption { #[derive(Default)] pub struct DateTypeOptionBuilder(DateTypeOption); +impl_into_box_type_option_builder!(DateTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); + impl DateTypeOptionBuilder { pub fn date_format(mut self, date_format: DateFormat) -> Self { self.0.date_format = date_format; @@ -75,14 +79,18 @@ impl DateTypeOptionBuilder { self } } -impl TypeOptionsBuilder for DateTypeOptionBuilder { +impl TypeOptionBuilder for DateTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } #[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 5fa74285df..f3b546fcc9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -9,7 +9,8 @@ use rust_decimal::Decimal; use rusty_money::iso::{Currency, CNY, EUR, USD}; use serde::{Deserialize, Serialize}; -use crate::services::field::TypeOptionsBuilder; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use bytes::Bytes; use std::str::FromStr; use strum::IntoEnumIterator; use strum_macros::EnumIter; @@ -20,6 +21,8 @@ lazy_static! { #[derive(Default)] pub struct NumberTypeOptionBuilder(NumberTypeOption); +impl_into_box_type_option_builder!(NumberTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); impl NumberTypeOptionBuilder { pub fn name(mut self, name: &str) -> Self { @@ -43,14 +46,18 @@ impl NumberTypeOptionBuilder { } } -impl TypeOptionsBuilder for NumberTypeOptionBuilder { +impl TypeOptionBuilder for NumberTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } // Number diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 5c4a3c5141..84feb9e051 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,7 +1,8 @@ use crate::impl_from_and_to_type_option; -use crate::services::field::TypeOptionsBuilder; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use crate::services::util::*; +use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; @@ -34,6 +35,8 @@ impl CellDataSerde for SingleSelectTypeOption { #[derive(Default)] pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption); +impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOption); impl SingleSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { @@ -41,14 +44,19 @@ impl SingleSelectTypeOptionBuilder { self } } -impl TypeOptionsBuilder for SingleSelectTypeOptionBuilder { + +impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } // Multiple select @@ -61,6 +69,7 @@ pub struct MultiSelectTypeOption { pub disable_color: bool, } impl_from_and_to_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); + impl CellDataSerde for MultiSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { data @@ -73,6 +82,8 @@ impl CellDataSerde for MultiSelectTypeOption { #[derive(Default)] pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); +impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); impl MultiSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { self.0.options.push(opt); @@ -80,14 +91,18 @@ impl MultiSelectTypeOptionBuilder { } } -impl TypeOptionsBuilder for MultiSelectTypeOptionBuilder { +impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } fn single_select_option_id_from_data(data: String) -> FlowyResult { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index dc7e0e56d0..3b2cfa051d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,7 +1,7 @@ use crate::impl_from_and_to_type_option; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; - -use crate::services::field::TypeOptionsBuilder; +use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; @@ -9,15 +9,21 @@ use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct RichTextTypeOptionBuilder(RichTextTypeOption); +impl_into_box_type_option_builder!(RichTextTypeOptionBuilder); +impl_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); -impl TypeOptionsBuilder for RichTextTypeOptionBuilder { +impl TypeOptionBuilder for RichTextTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build(&self) -> String { + fn build_type_option_str(&self) -> String { self.0.clone().into() } + + fn build_type_option_data(&self) -> Bytes { + self.0.clone().try_into().unwrap() + } } #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] 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 3089836220..6978705592 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{type_option_builder_from_type, FieldBuilder}; +use crate::services::field::{default_type_option_builder_from_type, type_option_json_str_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; @@ -49,20 +49,35 @@ impl ClientGridEditor { })) } - pub async fn create_field(&self, mut params: CreateFieldParams) -> FlowyResult<()> { - if params.type_option_data.is_empty() { - params.type_option_data = type_option_builder_from_type(¶ms.field.field_type) - .build() - .as_bytes() - .to_vec(); - } + pub async fn create_field(&self, params: CreateFieldParams) -> FlowyResult<()> { + let CreateFieldParams { + field, + type_option_data, + start_field_id, + .. + } = params; - let _ = self.modify(|grid| Ok(grid.create_field(params)?)).await?; + let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); + + let field_meta = FieldMeta { + id: field.id, + name: field.name, + desc: field.desc, + field_type: field.field_type, + frozen: field.frozen, + visibility: field.visibility, + width: field.width, + type_option_json, + }; + + let _ = self + .modify(|grid| Ok(grid.create_field(field_meta, start_field_id)?)) + .await?; let _ = self.notify_did_update_fields().await?; Ok(()) } - pub async fn make_field_meta_from_ty(&self, field_type: &FieldType) -> FlowyResult { + pub async fn default_field_meta(&self, field_type: &FieldType) -> FlowyResult { let name = format!("Property {}", self.pad.read().await.fields().len()); let field_meta = FieldBuilder::from_field_type(&field_type).name(&name).build(); Ok(field_meta) diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 4cda3a599e..5881c7ee84 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -100,7 +100,7 @@ async fn grid_update_field() { cloned_field.frozen = true; cloned_field.width = 1000; - cloned_field.type_option = single_select_type_options.into(); + cloned_field.type_option_json = single_select_type_options.into(); let scripts = vec![ CreateField { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index d622d3acbe..b2dbc2c7a9 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -268,7 +268,7 @@ pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { let params = CreateFieldParams { grid_id: grid_id.to_owned(), field, - type_option_data: field_meta.type_option.as_bytes().to_vec(), + type_option_data: field_meta.type_option_json.as_bytes().to_vec(), start_field_id: None, }; (params, cloned_field_meta) @@ -295,7 +295,7 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMet let params = CreateFieldParams { grid_id: grid_id.to_owned(), field, - type_option_data: field_meta.type_option.as_bytes().to_vec(), + type_option_data: field_meta.type_option_json.as_bytes().to_vec(), start_field_id: None, }; (params, cloned_field_meta) diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 9bfc977838..24258c2d0c 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -98,7 +98,7 @@ pub struct FieldMeta { pub width: i32, #[pb(index = 8)] - pub type_option: String, + pub type_option_json: String, } impl FieldMeta { @@ -111,7 +111,7 @@ impl FieldMeta { frozen: false, visibility: true, width: DEFAULT_FIELD_WIDTH, - type_option: Default::default(), + type_option_json: Default::default(), } } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index df2c87d586..eaea731897 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -727,7 +727,7 @@ pub struct FieldMeta { pub frozen: bool, pub visibility: bool, pub width: i32, - pub type_option: ::std::string::String, + pub type_option_json: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -882,30 +882,30 @@ impl FieldMeta { self.width = v; } - // string type_option = 8; + // string type_option_json = 8; - pub fn get_type_option(&self) -> &str { - &self.type_option + pub fn get_type_option_json(&self) -> &str { + &self.type_option_json } - pub fn clear_type_option(&mut self) { - self.type_option.clear(); + pub fn clear_type_option_json(&mut self) { + self.type_option_json.clear(); } // Param is passed by value, moved - pub fn set_type_option(&mut self, v: ::std::string::String) { - self.type_option = v; + pub fn set_type_option_json(&mut self, v: ::std::string::String) { + self.type_option_json = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_type_option(&mut self) -> &mut ::std::string::String { - &mut self.type_option + pub fn mut_type_option_json(&mut self) -> &mut ::std::string::String { + &mut self.type_option_json } // Take field - pub fn take_type_option(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.type_option, ::std::string::String::new()) + pub fn take_type_option_json(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.type_option_json, ::std::string::String::new()) } } @@ -952,7 +952,7 @@ impl ::protobuf::Message for FieldMeta { self.width = tmp; }, 8 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_option)?; + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_option_json)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -987,8 +987,8 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint); } - if !self.type_option.is_empty() { - my_size += ::protobuf::rt::string_size(8, &self.type_option); + if !self.type_option_json.is_empty() { + my_size += ::protobuf::rt::string_size(8, &self.type_option_json); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1017,8 +1017,8 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { os.write_int32(7, self.width)?; } - if !self.type_option.is_empty() { - os.write_string(8, &self.type_option)?; + if !self.type_option_json.is_empty() { + os.write_string(8, &self.type_option_json)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1094,9 +1094,9 @@ impl ::protobuf::Message for FieldMeta { |m: &mut FieldMeta| { &mut m.width }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "type_option", - |m: &FieldMeta| { &m.type_option }, - |m: &mut FieldMeta| { &mut m.type_option }, + "type_option_json", + |m: &FieldMeta| { &m.type_option_json }, + |m: &mut FieldMeta| { &mut m.type_option_json }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "FieldMeta", @@ -1121,7 +1121,7 @@ impl ::protobuf::Clear for FieldMeta { self.frozen = false; self.visibility = false; self.width = 0; - self.type_option.clear(); + self.type_option_json.clear(); self.unknown_fields.clear(); } } @@ -3507,50 +3507,50 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"V\n\x12GridBlockMet\ aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\ - metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xdd\x01\n\tFieldM\ + metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xe6\x01\n\tFieldM\ eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12\x1f\n\x0btype_option\x18\x08\x20\x01(\tR\ntypeOption\"\x96\x03\ - \n\x0eFieldChangeset\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldI\ - d\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\x04name\ - \x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\ - \x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\ - \tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06frozen\x12\ - \x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\x05w\ - idth\x18\x08\x20\x01(\x05H\x05R\x05width\x12#\n\x0ctype_options\x18\t\ - \x20\x01(\tH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\r\n\x0bone_of_desc\ - B\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visi\ - bilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type_options\"8\n\x07AnyD\ - ata\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05valu\ - e\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\ - \x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07\ - blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.Cel\ - lByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05\ - R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\ - \n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\ - \x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\ - \xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\ - \x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\ - \n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_\ - field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rce\ - llByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\ - \x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05\ - value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\ - \x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\ - \x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\x11CellMetaChange\ - set\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_\ - id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\t\ - R\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bon\ - e_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bfield_metas\x18\x01\ - \x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bblock_metas\x18\x02\ - \x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fblock_meta_data\ - \x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\rblockMetaData*d\n\tField\ - Type\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08\ - DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSel\ - ect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\ + idth\x12(\n\x10type_option_json\x18\x08\x20\x01(\tR\x0etypeOptionJson\"\ + \x96\x03\n\x0eFieldChangeset\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\ + \x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\ + \x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\ + \x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTy\ + peH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06fr\ + ozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\ + \x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12#\n\x0ctype_optio\ + ns\x18\t\x20\x01(\tH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\r\n\x0bone\ + _of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one\ + _of_visibilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type_options\"8\n\ + \x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\ + \x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\ + \n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01\ + (\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.Row\ + Meta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\ + \x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibi\ + lity\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\ + \x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\ + \x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\ + \x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06he\ + ight\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\ + \x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByField\ + IdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.C\ + ellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visib\ + ility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fiel\ + dId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\x11CellMet\ + aChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\ + \x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\ + \x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\x04data\ + B\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bfield_met\ + as\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bblock_metas\ + \x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fblock_me\ + ta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\rblockMetaData*d\n\ + \tFieldType\x12\x0c\n\x08RichText\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\ "; 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/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 10b1183fea..44ed367956 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -22,7 +22,7 @@ message FieldMeta { bool frozen = 5; bool visibility = 6; int32 width = 7; - string type_option = 8; + string type_option_json = 8; } message FieldChangeset { string field_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 06ecf07030..44b848a275 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -36,49 +36,31 @@ impl GridMetaPad { Self::from_delta(grid_delta) } - pub fn create_field(&mut self, params: CreateFieldParams) -> CollaborateResult> { + pub fn create_field( + &mut self, + new_field_meta: FieldMeta, + start_field_id: Option, + ) -> CollaborateResult> { self.modify_grid(|grid| { - let CreateFieldParams { - field, - type_option_data, - start_field_id, - .. - } = params; - // Check if the field exists or not if grid .fields .iter() - .find(|field_meta| field_meta.id == field.id) + .find(|field_meta| field_meta.id == new_field_meta.id) .is_some() { tracing::warn!("Duplicate grid field"); return Ok(None); } - // Parse type option - let type_option = - String::from_utf8(type_option_data).map_err(|e| CollaborateError::internal().context(e))?; - - let field_meta = FieldMeta { - id: field.id, - name: field.name, - desc: field.desc, - field_type: field.field_type, - frozen: field.frozen, - visibility: field.visibility, - width: field.width, - type_option, - }; - let insert_index = match start_field_id { None => None, Some(start_field_id) => grid.fields.iter().position(|field| field.id == start_field_id), }; match insert_index { - None => grid.fields.push(field_meta), - Some(index) => grid.fields.insert(index, field_meta), + None => grid.fields.push(new_field_meta), + Some(index) => grid.fields.insert(index, new_field_meta), } Ok(Some(())) }) @@ -167,7 +149,7 @@ impl GridMetaPad { } if let Some(type_options) = changeset.type_options { - field.type_option = type_options; + field.type_option_json = type_options; is_changed = Some(()) } From 16598650ffbc688b6e3a382f7861c343c6b62054 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Mar 2022 20:27:32 +0800 Subject: [PATCH 10/47] chore: lazy load cell --- .../app_flowy/lib/startup/deps_resolver.dart | 43 ++++--- .../lib/startup/tasks/app_widget.dart | 2 +- .../lib/user/application/user_listener.dart | 11 +- .../application/app/app_listener.dart | 5 +- .../grid/cell_bloc/cell_service.dart | 18 +-- .../grid/cell_bloc/checkbox_cell_bloc.dart | 9 +- .../grid/cell_bloc/date_cell_bloc.dart | 9 +- .../grid/cell_bloc/number_cell_bloc.dart | 8 +- .../grid/cell_bloc/selection_cell_bloc.dart | 8 +- .../grid/cell_bloc/text_cell_bloc.dart | 36 +++++- .../grid/field/create_field_bloc.dart | 59 +++++++-- .../application/grid/field/field_service.dart | 67 ++-------- .../grid/field/switch_field_type_bloc.dart | 18 ++- .../workspace/application/grid/grid_bloc.dart | 87 +++++++++---- .../application/grid/grid_block_service.dart | 13 +- .../application/grid/grid_listenr.dart | 7 +- .../application/grid/grid_service.dart | 20 --- .../application/grid/row/row_bloc.dart | 120 ++++++++++++------ .../application/grid/row/row_listener.dart | 50 +++++++- .../application/grid/row/row_service.dart | 28 ++-- .../application/trash/trash_listener.dart | 5 +- .../application/view/view_listener.dart | 5 +- .../workspace/workspace_listener.dart | 7 +- .../plugins/grid/src/grid_page.dart | 74 ++++++----- .../src/widgets/content/cell_builder.dart | 16 +-- .../src/widgets/content/checkbox_cell.dart | 2 +- .../grid/src/widgets/content/date_cell.dart | 2 +- .../grid/src/widgets/content/grid_row.dart | 96 +++++--------- .../grid/src/widgets/content/number_cell.dart | 2 +- .../src/widgets/content/selection_cell.dart | 12 +- .../grid/src/widgets/content/text_cell.dart | 10 +- .../widgets/header/create_field_pannel.dart | 57 +++++---- .../grid/src/widgets/header/field_editor.dart | 7 +- .../widgets/header/field_tyep_switcher.dart | 18 +-- .../grid/src/widgets/header/header.dart | 2 +- .../scrolling/styled_scrollview.dart | 12 +- frontend/rust-lib/flowy-grid/src/macros.rs | 6 +- .../src/services/block_meta_editor.rs | 5 +- .../type_options/checkbox_type_option.rs | 16 +-- .../field/type_options/date_type_option.rs | 4 +- .../field/type_options/number_type_option.rs | 44 +++---- .../type_options/selection_type_option.rs | 8 +- .../flowy-grid/src/services/grid_editor.rs | 6 +- frontend/rust-lib/flowy-grid/src/util.rs | 2 +- .../flowy-grid/tests/grid/grid_test.rs | 12 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 4 +- .../flowy-text-block/tests/editor/mod.rs | 1 + .../src/entities/grid.rs | 28 ++-- .../src/parser/id_parser.rs | 7 +- .../src/client_grid/grid_meta_pad.rs | 9 +- 50 files changed, 628 insertions(+), 469 deletions(-) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 56f115a22b..8293efd652 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -149,8 +149,8 @@ void _resolveGridDeps(GetIt getIt) { getIt.registerFactoryParam( (data, _) => RowBloc( - rowService: RowService(data), - listener: RowListener(rowId: data.rowId), + rowData: data, + rowlistener: RowListener(rowId: data.rowId), ), ); @@ -174,38 +174,43 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => TextCellBloc( - service: CellService(context), + getIt.registerFactoryParam( + (cellData, _) => TextCellBloc( + service: CellService(), + cellData: cellData, ), ); - getIt.registerFactoryParam( - (context, _) => SelectionCellBloc( - service: CellService(context), + getIt.registerFactoryParam( + (cellData, _) => SelectionCellBloc( + service: CellService(), + cellData: cellData, ), ); - getIt.registerFactoryParam( - (context, _) => NumberCellBloc( - service: CellService(context), + getIt.registerFactoryParam( + (cellData, _) => NumberCellBloc( + service: CellService(), + cellData: cellData, ), ); - getIt.registerFactoryParam( - (context, _) => DateCellBloc( - service: CellService(context), + getIt.registerFactoryParam( + (cellData, _) => DateCellBloc( + service: CellService(), + cellData: cellData, ), ); - getIt.registerFactoryParam( - (context, _) => CheckboxCellBloc( - service: CellService(context), + getIt.registerFactoryParam( + (cellData, _) => CheckboxCellBloc( + service: CellService(), + cellData: cellData, ), ); - getIt.registerFactoryParam( - (editContext, _) => SwitchFieldTypeBloc(editContext), + getIt.registerFactoryParam( + (context, _) => SwitchFieldTypeBloc(context), ); getIt.registerFactory( diff --git a/frontend/app_flowy/lib/startup/tasks/app_widget.dart b/frontend/app_flowy/lib/startup/tasks/app_widget.dart index 23f4109042..78672193da 100644 --- a/frontend/app_flowy/lib/startup/tasks/app_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/app_widget.dart @@ -112,7 +112,7 @@ class ApplicationBlocObserver extends BlocObserver { // ignore: unnecessary_overrides void onTransition(Bloc bloc, Transition transition) { // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}"); - //Log.debug("${transition.nextState}"); + Log.debug("${transition.nextState}"); super.onTransition(bloc, transition); } diff --git a/frontend/app_flowy/lib/user/application/user_listener.dart b/frontend/app_flowy/lib/user/application/user_listener.dart index 993aee60e0..5b212cc2d0 100644 --- a/frontend/app_flowy/lib/user/application/user_listener.dart +++ b/frontend/app_flowy/lib/user/application/user_listener.dart @@ -12,7 +12,6 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user; import 'package:flowy_sdk/rust_stream.dart'; - typedef UserProfileUpdatedNotifierValue = Either; typedef AuthNotifierValue = Either; typedef WorkspaceUpdatedNotifierValue = Either, FlowyError>; @@ -23,8 +22,8 @@ class UserListener { final authDidChangedNotifier = PublishNotifier(); final workspaceUpdatedNotifier = PublishNotifier(); - late FolderNotificationParser _workspaceParser; - late UserNotificationParser _userParser; + FolderNotificationParser? _workspaceParser; + UserNotificationParser? _userParser; late UserProfile _user; UserListener({ required UserProfile user, @@ -36,12 +35,14 @@ class UserListener { _workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback); _userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback); _subscription = RustStreamReceiver.listen((observable) { - _workspaceParser.parse(observable); - _userParser.parse(observable); + _workspaceParser?.parse(observable); + _userParser?.parse(observable); }); } Future stop() async { + _workspaceParser = null; + _userParser = null; await _subscription?.cancel(); profileUpdatedNotifier.dispose(); authDidChangedNotifier.dispose(); diff --git a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart index 3d9bbbc65c..46b16bb080 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart @@ -17,7 +17,7 @@ class AppListener { StreamSubscription? _subscription; ViewsDidChangeCallback? _viewsChanged; AppDidUpdateCallback? _updated; - late FolderNotificationParser _parser; + FolderNotificationParser? _parser; String appId; AppListener({ @@ -28,7 +28,7 @@ class AppListener { _viewsChanged = viewsChanged; _updated = appUpdated; _parser = FolderNotificationParser(id: appId, callback: _bservableCallback); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _bservableCallback(FolderNotification ty, Either result) { @@ -61,6 +61,7 @@ class AppListener { } Future close() async { + _parser = null; await _subscription?.cancel(); _viewsChanged = null; _updated = null; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index 79b4d2cf52..e1af022d95 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -1,19 +1,21 @@ -import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; class CellService { - final GridCellData context; + CellService(); - CellService(this.context); - - Future> updateCell({required String data}) { + Future> updateCell({ + required String gridId, + required String fieldId, + required String rowId, + required String data, + }) { final payload = CellMetaChangeset.create() - ..gridId = context.gridId - ..fieldId = context.field.id - ..rowId = context.rowId + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId ..data = data; return GridEventUpdateCell(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index 2199d59562..3e3c1b37bc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -8,10 +9,14 @@ part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { final CellService service; + // final FutureCellData cellData; CheckboxCellBloc({ required this.service, - }) : super(CheckboxCellState.initial(service.context.cell)) { + required FutureCellData cellData, + }) : super(CheckboxCellState.initial()) { + cellData.then((a) {}); + on( (event, emit) async { await event.map( @@ -38,5 +43,5 @@ class CheckboxCellState with _$CheckboxCellState { required Cell? cell, }) = _CheckboxCellState; - factory CheckboxCellState.initial(Cell? cell) => CheckboxCellState(cell: cell); + factory CheckboxCellState.initial() => const CheckboxCellState(cell: null); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart index 071757fdeb..33829863dd 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -8,10 +9,12 @@ part 'date_cell_bloc.freezed.dart'; class DateCellBloc extends Bloc { final CellService service; + final FutureCellData cellData; DateCellBloc({ required this.service, - }) : super(DateCellState.initial(service.context.cell)) { + required this.cellData, + }) : super(DateCellState.initial()) { on( (event, emit) async { await event.map( @@ -35,8 +38,8 @@ class DateCellEvent with _$DateCellEvent { @freezed class DateCellState with _$DateCellState { const factory DateCellState({ - required Cell? cell, + Cell? cell, }) = _DateCellState; - factory DateCellState.initial(Cell? cell) => DateCellState(cell: cell); + factory DateCellState.initial() => const DateCellState(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart index e368c32c35..6e58d24a54 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -11,7 +12,8 @@ class NumberCellBloc extends Bloc { NumberCellBloc({ required this.service, - }) : super(NumberCellState.initial(service.context.cell)) { + required FutureCellData cellData, + }) : super(NumberCellState.initial()) { on( (event, emit) async { await event.map( @@ -35,8 +37,8 @@ class NumberCellEvent with _$NumberCellEvent { @freezed class NumberCellState with _$NumberCellState { const factory NumberCellState({ - required Cell? cell, + Cell? cell, }) = _NumberCellState; - factory NumberCellState.initial(Cell? cell) => NumberCellState(cell: cell); + factory NumberCellState.initial() => const NumberCellState(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 1a94d4ce69..917e848a78 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -11,7 +12,8 @@ class SelectionCellBloc extends Bloc { SelectionCellBloc({ required this.service, - }) : super(SelectionCellState.initial(service.context.cell)) { + required FutureCellData cellData, + }) : super(SelectionCellState.initial()) { on( (event, emit) async { await event.map( @@ -35,8 +37,8 @@ class SelectionCellEvent with _$SelectionCellEvent { @freezed class SelectionCellState with _$SelectionCellState { const factory SelectionCellState({ - required Cell? cell, + Cell? cell, }) = _SelectionCellState; - factory SelectionCellState.initial(Cell? cell) => SelectionCellState(cell: cell); + factory SelectionCellState.initial() => const SelectionCellState(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index d999ea774d..73c2e8e03d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -10,20 +11,47 @@ class TextCellBloc extends Bloc { TextCellBloc({ required this.service, - }) : super(TextCellState.initial(service.context.cell?.content ?? "")) { + required FutureCellData cellData, + }) : super(TextCellState.initial()) { + cellData.then((cellData) { + if (cellData != null) { + add(TextCellEvent.didReceiveCellData(cellData)); + } + }); + on( (event, emit) async { await event.map( initial: (_InitialCell value) async {}, updateText: (_UpdateText value) { - service.updateCell(data: value.text); + updateCellContent(value.text); emit(state.copyWith(content: value.text)); }, + didReceiveCellData: (_DidReceiveCellData value) { + emit(state.copyWith( + cellData: value.cellData, + content: value.cellData.cell?.content ?? "", + )); + }, ); }, ); } + void updateCellContent(String content) { + if (state.cellData != null) { + final fieldId = state.cellData!.field.id; + final gridId = state.cellData!.gridId; + final rowId = state.cellData!.rowId; + service.updateCell( + data: content, + fieldId: fieldId, + gridId: gridId, + rowId: rowId, + ); + } + } + @override Future close() async { return super.close(); @@ -33,6 +61,7 @@ class TextCellBloc extends Bloc { @freezed class TextCellEvent with _$TextCellEvent { const factory TextCellEvent.initial() = _InitialCell; + const factory TextCellEvent.didReceiveCellData(GridCellData cellData) = _DidReceiveCellData; const factory TextCellEvent.updateText(String text) = _UpdateText; } @@ -40,7 +69,8 @@ class TextCellEvent with _$TextCellEvent { class TextCellState with _$TextCellState { const factory TextCellState({ required String content, + GridCellData? cellData, }) = _TextCellState; - factory TextCellState.initial(String content) => TextCellState(content: content); + factory TextCellState.initial() => const TextCellState(content: ""); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart index aa0d47e5d6..0fd0fb0a83 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; @@ -12,19 +14,22 @@ part 'create_field_bloc.freezed.dart'; class CreateFieldBloc extends Bloc { final FieldService service; - CreateFieldBloc({required this.service}) : super(CreateFieldState.initial()) { + CreateFieldBloc({required this.service}) : super(CreateFieldState.initial(service.gridId)) { on( (event, emit) async { await event.map( initial: (_InitialField value) async { - final result = await service.getEditFieldContext(FieldType.RichText); - result.fold( - (editContext) => emit(state.copyWith(editContext: Some(editContext))), - (err) => Log.error(err), - ); + await _getEditFieldContext(emit); + }, + updateName: (_UpdateName value) { + emit(state.copyWith(fieldName: value.name)); + }, + switchField: (_SwitchField value) { + emit(state.copyWith(field: Some(value.field), typeOptionData: value.typeOptionData)); + }, + done: (_Done value) async { + await _saveField(emit); }, - updateName: (_UpdateName value) {}, - done: (_Done value) {}, ); }, ); @@ -34,24 +39,54 @@ class CreateFieldBloc extends Bloc { Future close() async { return super.close(); } + + Future _saveField(Emitter emit) async { + await state.field.fold( + () async => null, + (field) async { + final result = await service.createField(field: field, typeOptionData: state.typeOptionData); + result.fold((l) => null, (r) => null); + }, + ); + } + + Future _getEditFieldContext(Emitter emit) async { + final result = await service.getEditFieldContext(FieldType.RichText); + result.fold( + (editContext) { + emit(state.copyWith( + field: Some(editContext.gridField), + typeOptionData: editContext.typeOptionData, + )); + }, + (err) => Log.error(err), + ); + } } @freezed class CreateFieldEvent with _$CreateFieldEvent { const factory CreateFieldEvent.initial() = _InitialField; - const factory CreateFieldEvent.updateName(String newName) = _UpdateName; + const factory CreateFieldEvent.updateName(String name) = _UpdateName; + const factory CreateFieldEvent.switchField(Field field, Uint8List typeOptionData) = _SwitchField; const factory CreateFieldEvent.done() = _Done; } @freezed class CreateFieldState with _$CreateFieldState { const factory CreateFieldState({ + required String fieldName, + required String gridId, required String errorText, - required Option editContext, + required Option field, + required List typeOptionData, }) = _CreateFieldState; - factory CreateFieldState.initial() => CreateFieldState( - editContext: none(), + factory CreateFieldState.initial(String gridId) => CreateFieldState( + gridId: gridId, + fieldName: '', + field: none(), errorText: '', + typeOptionData: List.empty(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index e3dfdf3ce9..f9d7ea9f09 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -21,66 +21,19 @@ class FieldService { return GridEventCreateEditFieldContext(payload).send(); } - Future> createTextField( - String gridId, - Field field, - RichTextTypeOption typeOption, + Future> createField({ + required Field field, + List? typeOptionData, String? startFieldId, - ) { - final typeOptionData = typeOption.writeToBuffer(); - return createField(field, typeOptionData, startFieldId); - } - - Future> createSingleSelectField( - String gridId, - Field field, - SingleSelectTypeOption typeOption, - String? startFieldId, - ) { - final typeOptionData = typeOption.writeToBuffer(); - return createField(field, typeOptionData, startFieldId); - } - - Future> createMultiSelectField( - String gridId, - Field field, - MultiSelectTypeOption typeOption, - String? startFieldId, - ) { - final typeOptionData = typeOption.writeToBuffer(); - return createField(field, typeOptionData, startFieldId); - } - - Future> createNumberField( - String gridId, - Field field, - NumberTypeOption typeOption, - String? startFieldId, - ) { - final typeOptionData = typeOption.writeToBuffer(); - return createField(field, typeOptionData, startFieldId); - } - - Future> createDateField( - String gridId, - Field field, - DateTypeOption typeOption, - String? startFieldId, - ) { - final typeOptionData = typeOption.writeToBuffer(); - return createField(field, typeOptionData, startFieldId); - } - - Future> createField( - Field field, - Uint8List? typeOptionData, - String? startFieldId, - ) { - final payload = CreateFieldPayload.create() + }) { + var payload = CreateFieldPayload.create() ..gridId = gridId ..field_2 = field - ..typeOptionData = typeOptionData ?? Uint8List.fromList([]) - ..startFieldId = startFieldId ?? ""; + ..typeOptionData = typeOptionData ?? []; + + if (startFieldId != null) { + payload.startFieldId = startFieldId; + } return GridEventCreateField(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart index a6042c52e3..7f5417a396 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -10,7 +10,7 @@ import 'field_service.dart'; part 'switch_field_type_bloc.freezed.dart'; class SwitchFieldTypeBloc extends Bloc { - SwitchFieldTypeBloc(EditFieldContext editContext) : super(SwitchFieldTypeState.initial(editContext)) { + SwitchFieldTypeBloc(SwitchFieldContext editContext) : super(SwitchFieldTypeState.initial(editContext)) { on( (event, emit) async { await event.map( @@ -53,9 +53,17 @@ class SwitchFieldTypeState with _$SwitchFieldTypeState { required Uint8List typeOptionData, }) = _SwitchFieldTypeState; - factory SwitchFieldTypeState.initial(EditFieldContext editContext) => SwitchFieldTypeState( - gridId: editContext.gridId, - field: editContext.gridField, - typeOptionData: Uint8List.fromList(editContext.typeOptionData), + factory SwitchFieldTypeState.initial(SwitchFieldContext switchContext) => SwitchFieldTypeState( + gridId: switchContext.gridId, + field: switchContext.field, + typeOptionData: Uint8List.fromList(switchContext.typeOptionData), ); } + +class SwitchFieldContext { + final String gridId; + final Field field; + final List typeOptionData; + + SwitchFieldContext(this.gridId, this.field, this.typeOptionData); +} 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 ea090a086a..b155126a72 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -6,6 +6,7 @@ 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 'package:equatable/equatable.dart'; import 'grid_block_service.dart'; import 'grid_listenr.dart'; import 'grid_service.dart'; @@ -63,6 +64,20 @@ class GridBloc extends Bloc { await _loadGrid(emit); } + Future _initGridBlock(Grid grid) async { + _blockService = GridBlockService( + gridId: grid.id, + blockOrders: grid.blockOrders, + ); + + _blockService.blocksUpdateNotifier?.addPublishListener((result) { + result.fold( + (blockMap) => add(GridEvent.rowsDidUpdate(_buildRows(blockMap))), + (err) => Log.error('$err'), + ); + }); + } + Future _loadGrid(Emitter emit) async { final result = await service.openGrid(gridId: view.id); return Future( @@ -78,7 +93,7 @@ class GridBloc extends Bloc { return Future( () => result.fold( (fields) { - _initGridBlockService(grid); + _initGridBlock(grid); emit(state.copyWith( grid: Some(grid), fields: fields.items, @@ -90,29 +105,12 @@ class GridBloc extends Bloc { ); } - Future _initGridBlockService(Grid grid) async { - _blockService = GridBlockService( - gridId: grid.id, - blockOrders: grid.blockOrders, - ); - - _blockService.blocksUpdateNotifier.addPublishListener((result) { - result.fold( - (blockMap) => add(GridEvent.rowsDidUpdate(_buildRows(blockMap))), - (err) => Log.error('$err'), - ); - }); - - _gridListener.start(); - } - - List _buildRows(GridBlockMap blockMap) { - List rows = []; + List _buildRows(GridBlockMap blockMap) { + List rows = []; blockMap.forEach((_, GridBlock gridBlock) { rows.addAll(gridBlock.rowOrders.map( - (rowOrder) => GridRowData( + (rowOrder) => GridBlockRow( gridId: view.id, - fields: state.fields, blockId: gridBlock.id, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), @@ -130,7 +128,7 @@ class GridEvent with _$GridEvent { const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; - const factory GridEvent.rowsDidUpdate(List rows) = _RowsDidUpdate; + const factory GridEvent.rowsDidUpdate(List rows) = _RowsDidUpdate; const factory GridEvent.fieldsDidUpdate(List fields) = _FieldsDidUpdate; } @@ -139,7 +137,7 @@ class GridState with _$GridState { const factory GridState({ required GridLoadingState loadingState, required List fields, - required List rows, + required List rows, required Option grid, }) = _GridState; @@ -156,3 +154,46 @@ class GridLoadingState with _$GridLoadingState { const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.finish(Either successOrFail) = _Finish; } + +class GridBlockRow { + final String gridId; + final String rowId; + final String blockId; + final double height; + + const GridBlockRow({ + required this.gridId, + required this.rowId, + required this.blockId, + required this.height, + }); +} + +class GridRowData extends Equatable { + final String gridId; + final String rowId; + final String blockId; + final List fields; + final double height; + + const GridRowData({ + required this.gridId, + required this.rowId, + required this.blockId, + required this.fields, + required this.height, + }); + + factory GridRowData.fromBlockRow(GridBlockRow row, List fields) { + return GridRowData( + gridId: row.gridId, + rowId: row.rowId, + blockId: row.blockId, + fields: fields, + height: row.height, + ); + } + + @override + List get props => [rowId, fields]; +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart index 151b587d16..668b523c74 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart @@ -19,7 +19,7 @@ class GridBlockService { String gridId; GridBlockMap blockMap = GridBlockMap(); late GridBlockListener _blockListener; - PublishNotifier blocksUpdateNotifier = PublishNotifier(); + PublishNotifier? blocksUpdateNotifier = PublishNotifier(); GridBlockService({required this.gridId, required List blockOrders}) { _loadGridBlocks(blockOrders); @@ -36,6 +36,8 @@ class GridBlockService { Future stop() async { await _blockListener.stop(); + blocksUpdateNotifier?.dispose(); + blocksUpdateNotifier = null; } void _loadGridBlocks(List blockOrders) { @@ -49,9 +51,9 @@ class GridBlockService { for (final gridBlock in repeatedBlocks.items) { blockMap[gridBlock.id] = gridBlock; } - blocksUpdateNotifier.value = left(blockMap); + blocksUpdateNotifier?.value = left(blockMap); }, - (err) => blocksUpdateNotifier.value = right(err), + (err) => blocksUpdateNotifier?.value = right(err), ); }); } @@ -61,7 +63,7 @@ class GridBlockListener { final String gridId; PublishNotifier, FlowyError>> blockUpdateNotifier = PublishNotifier(comparable: null); StreamSubscription? _subscription; - late GridNotificationParser _parser; + GridNotificationParser? _parser; GridBlockListener({required this.gridId}); @@ -73,7 +75,7 @@ class GridBlockListener { }, ); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _handleObservableType(GridNotification ty, Either result) { @@ -91,6 +93,7 @@ class GridBlockListener { } Future stop() async { + _parser = null; await _subscription?.cancel(); blockUpdateNotifier.dispose(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart index e110491912..4afaa54601 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart @@ -13,9 +13,9 @@ import 'package:app_flowy/core/notification_helper.dart'; class GridListener { final String gridId; - PublishNotifier, FlowyError>> fieldsUpdateNotifier = PublishNotifier(comparable: null); + PublishNotifier, FlowyError>> fieldsUpdateNotifier = PublishNotifier(); StreamSubscription? _subscription; - late GridNotificationParser _parser; + GridNotificationParser? _parser; GridListener({required this.gridId}); void start() { @@ -26,7 +26,7 @@ class GridListener { }, ); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _handleObservableType(GridNotification ty, Either result) { @@ -43,6 +43,7 @@ class GridListener { } Future stop() async { + _parser = null; await _subscription?.cancel(); fieldsUpdateNotifier.dispose(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 2aafd02fba..9bb2e36e5f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -3,7 +3,6 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:dartz/dartz.dart'; -import 'package:equatable/equatable.dart'; class GridService { Future> openGrid({required String gridId}) async { @@ -34,22 +33,3 @@ class GridService { return GridEventGetFields(payload).send(); } } - -class GridRowData extends Equatable { - final String gridId; - final String rowId; - final String blockId; - final List fields; - final double height; - - const GridRowData({ - required this.gridId, - required this.rowId, - required this.blockId, - required this.fields, - required this.height, - }); - - @override - List get props => [rowId]; -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index b7e4f40c5d..ba6b64f602 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -1,4 +1,6 @@ -import 'package:app_flowy/workspace/application/grid/grid_service.dart'; +import 'dart:collection'; + +import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -6,20 +8,34 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'row_listener.dart'; import 'row_service.dart'; +import 'package:dartz/dartz.dart'; part 'row_bloc.freezed.dart'; +typedef CellDataMap = HashMap; + class RowBloc extends Bloc { final RowService rowService; - final RowListener listener; + final RowListener rowlistener; + final RowFieldListener fieldListener; - RowBloc({required this.rowService, required this.listener}) : super(RowState.initial(rowService.rowData)) { + RowBloc({required GridRowData rowData, required this.rowlistener}) + : rowService = RowService( + gridId: rowData.gridId, + blockId: rowData.blockId, + rowId: rowData.rowId, + ), + fieldListener = RowFieldListener( + gridId: rowData.gridId, + ), + super(RowState.initial(rowData)) { on( (event, emit) async { await event.map( initial: (_InitialRow value) async { - _startRowListening(); + _startListening(); await _loadRow(emit); + add(const RowEvent.didUpdateCell()); }, createRow: (_CreateRow value) { rowService.createRow(); @@ -30,6 +46,19 @@ class RowBloc extends Bloc { disactiveRow: (_DisactiveRow value) { emit(state.copyWith(active: false)); }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(fields: value.fields)); + add(const RowEvent.didUpdateCell()); + }, + didUpdateCell: (_DidUpdateCell value) { + final Future cellDataMap = state.row.then( + (someRow) => someRow.fold( + () => HashMap.identity(), + (row) => _makeCellDatas(row), + ), + ); + emit(state.copyWith(cellDataMap: cellDataMap)); + }, ); }, ); @@ -37,53 +66,66 @@ class RowBloc extends Bloc { @override Future close() async { - await listener.close(); + await rowlistener.close(); + await fieldListener.close(); return super.close(); } - Future _startRowListening() async { - listener.updateRowNotifier.addPublishListener((result) { - result.fold((row) { - // - }, (err) => null); + Future _startListening() async { + rowlistener.updateRowNotifier.addPublishListener((result) { + result.fold( + (row) { + // + }, + (err) => Log.error(err), + ); }); - listener.updateCellNotifier.addPublishListener((result) { - result.fold((repeatedCvell) { - // - Log.info("$repeatedCvell"); - }, (r) => null); + rowlistener.updateCellNotifier.addPublishListener((result) { + result.fold( + (repeatedCell) { + Log.info("$repeatedCell"); + }, + (err) => Log.error(err), + ); }); - listener.start(); + fieldListener.updateFieldNotifier.addPublishListener((result) { + result.fold( + (fields) => add(RowEvent.didReceiveFieldUpdate(fields)), + (err) => Log.error(err), + ); + }); + + rowlistener.start(); + fieldListener.start(); } Future _loadRow(Emitter emit) async { - final Future> cellDatas = rowService.getRow().then((result) { + final Future> row = rowService.getRow().then((result) { return result.fold( - (row) => _makeCellDatas(row), - (e) { - Log.error(e); - return []; + (row) => Some(row), + (err) { + Log.error(err); + return none(); }, ); }); - emit(state.copyWith(cellDatas: cellDatas)); + emit(state.copyWith(row: row)); } - List _makeCellDatas(Row row) { - return rowService.rowData.fields.map((field) { - final cell = row.cellByFieldId[field.id]; - final rowData = rowService.rowData; - - return GridCellData( + CellDataMap _makeCellDatas(Row row) { + var map = CellDataMap.new(); + for (final field in state.fields) { + map[field.id] = GridCellData( rowId: row.id, - gridId: rowData.gridId, - blockId: rowData.blockId, - cell: cell, + gridId: rowService.gridId, + blockId: rowService.blockId, + cell: row.cellByFieldId[field.id], field: field, ); - }).toList(); + } + return map; } } @@ -93,21 +135,27 @@ class RowEvent with _$RowEvent { const factory RowEvent.createRow() = _CreateRow; const factory RowEvent.activeRow() = _ActiveRow; const factory RowEvent.disactiveRow() = _DisactiveRow; + const factory RowEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; + const factory RowEvent.didUpdateCell() = _DidUpdateCell; } @freezed class RowState with _$RowState { const factory RowState({ required String rowId, - required double rowHeight, - required Future> cellDatas, required bool active, + required double rowHeight, + required List fields, + required Future> row, + required Future cellDataMap, }) = _RowState; factory RowState.initial(GridRowData data) => RowState( rowId: data.rowId, - rowHeight: data.height, - cellDatas: Future(() => []), active: false, + rowHeight: data.height, + fields: data.fields, + row: Future(() => none()), + cellDataMap: Future(() => CellDataMap.identity()), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart index 76a2ba617d..c5084f4164 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart @@ -11,13 +11,14 @@ import 'package:dartz/dartz.dart'; typedef UpdateCellNotifiedValue = Either; typedef UpdateRowNotifiedValue = Either; +typedef UpdateFieldNotifiedValue = Either, FlowyError>; class RowListener { final String rowId; - PublishNotifier updateCellNotifier = PublishNotifier(); - PublishNotifier updateRowNotifier = PublishNotifier(); + PublishNotifier updateCellNotifier = PublishNotifier(); + PublishNotifier updateRowNotifier = PublishNotifier(); StreamSubscription? _subscription; - late GridNotificationParser _parser; + GridNotificationParser? _parser; RowListener({required this.rowId}); @@ -29,7 +30,7 @@ class RowListener { }, ); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _handleObservableType(GridNotification ty, Either result) { @@ -40,15 +41,54 @@ class RowListener { (error) => updateCellNotifier.value = right(error), ); break; - default: break; } } Future close() async { + _parser = null; await _subscription?.cancel(); updateCellNotifier.dispose(); updateRowNotifier.dispose(); } } + +class RowFieldListener { + final String gridId; + PublishNotifier updateFieldNotifier = PublishNotifier(); + StreamSubscription? _subscription; + GridNotificationParser? _parser; + + RowFieldListener({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.DidUpdateFields: + result.fold( + (payload) => updateFieldNotifier.value = left(RepeatedField.fromBuffer(payload).items), + (error) => updateFieldNotifier.value = right(error), + ); + break; + default: + break; + } + } + + Future close() async { + _parser = null; + await _subscription?.cancel(); + updateFieldNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 6819a9a40e..7c77c0de64 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -1,45 +1,51 @@ import 'package:dartz/dartz.dart'; +import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; - class RowService { - final GridRowData rowData; + final String gridId; + final String rowId; + final String blockId; - RowService(this.rowData); + RowService({required this.gridId, required this.rowId, required this.blockId}); Future> createRow() { CreateRowPayload payload = CreateRowPayload.create() - ..gridId = rowData.gridId - ..startRowId = rowData.rowId; + ..gridId = gridId + ..startRowId = rowId; return GridEventCreateRow(payload).send(); } Future> getRow() { QueryRowPayload payload = QueryRowPayload.create() - ..gridId = rowData.gridId - ..blockId = rowData.blockId - ..rowId = rowData.rowId; + ..gridId = gridId + ..blockId = blockId + ..rowId = rowId; return GridEventGetRow(payload).send(); } } -class GridCellData { +typedef FutureCellData = Future; + +class GridCellData extends Equatable { final String gridId; final String rowId; final String blockId; final Field field; final Cell? cell; - GridCellData({ + const GridCellData({ required this.rowId, required this.gridId, required this.blockId, required this.field, required this.cell, }); + + @override + List get props => [cell, field]; } diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart index dd0b1f58aa..36dc982466 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_listener.dart @@ -13,12 +13,12 @@ typedef TrashUpdatedCallback = void Function(Either, FlowyError> tra class TrashListener { StreamSubscription? _subscription; TrashUpdatedCallback? _trashUpdated; - late FolderNotificationParser _parser; + FolderNotificationParser? _parser; void start({TrashUpdatedCallback? trashUpdated}) { _trashUpdated = trashUpdated; _parser = FolderNotificationParser(callback: _bservableCallback); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _bservableCallback(FolderNotification ty, Either result) { @@ -40,6 +40,7 @@ class TrashListener { } Future close() async { + _parser = null; await _subscription?.cancel(); _trashUpdated = null; } 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 f400124805..ee27d55139 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_listener.dart @@ -18,7 +18,7 @@ class ViewListener { PublishNotifier updatedNotifier = PublishNotifier(); PublishNotifier deletedNotifier = PublishNotifier(); PublishNotifier restoredNotifier = PublishNotifier(); - late FolderNotificationParser _parser; + FolderNotificationParser? _parser; View view; ViewListener({ @@ -33,7 +33,7 @@ class ViewListener { }, ); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _handleObservableType(FolderNotification ty, Either result) { @@ -62,6 +62,7 @@ class ViewListener { } Future close() async { + _parser = null; await _subscription?.cancel(); updatedNotifier.dispose(); deletedNotifier.dispose(); diff --git a/frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart b/frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart index e5959d1562..9ac51e36f8 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/workspace_listener.dart @@ -12,7 +12,6 @@ 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/rust_stream.dart'; - typedef WorkspaceAppsChangedCallback = void Function(Either, FlowyError> appsOrFail); typedef WorkspaceUpdatedCallback = void Function(String name, String desc); @@ -31,12 +30,11 @@ class WorkspaceListener { } } - class WorkspaceListenerService { StreamSubscription? _subscription; WorkspaceAppsChangedCallback? _appsChanged; WorkspaceUpdatedCallback? _update; - late FolderNotificationParser _parser; + FolderNotificationParser? _parser; final UserProfile user; final String workspaceId; @@ -59,7 +57,7 @@ class WorkspaceListenerService { }, ); - _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } void _handleObservableType(FolderNotification ty, Either result) { @@ -91,6 +89,7 @@ class WorkspaceListenerService { } Future close() async { + _parser = null; await _subscription?.cancel(); // _appsChanged = null; // _update = null; 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 1b79a7a0b4..5cd23accc6 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 @@ -1,15 +1,13 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; -import 'package:styled_widget/styled_widget.dart'; - import 'controller/grid_scroll.dart'; import 'layout/layout.dart'; import 'layout/sizes.dart'; @@ -92,16 +90,33 @@ class _FlowyGridState extends State { return const Center(child: CircularProgressIndicator.adaptive()); } - return _wrapScrollbar(state.fields, [ - _buildHeader(gridId, state.fields), - _buildRows(context), - const GridFooter(), - ]); + final child = BlocBuilder( + builder: (context, state) { + return SizedBox( + width: GridLayout.headerWidth(state.fields), + child: ScrollConfiguration( + behavior: const ScrollBehavior().copyWith(scrollbars: false), + child: CustomScrollView( + shrinkWrap: true, + physics: StyledScrollPhysics(), + controller: _scrollController.verticalController, + slivers: [ + _buildHeader(gridId), + _buildRows(context), + const GridFooter(), + ], + ), + ), + ); + }, + ); + + return _wrapScrollbar(child); }, ); } - Widget _wrapScrollbar(List fields, List children) { + Widget _wrapScrollbar(Widget child) { return ScrollbarListStack( axis: Axis.vertical, controller: _scrollController.verticalController, @@ -109,38 +124,39 @@ class _FlowyGridState extends State { child: StyledSingleChildScrollView( controller: _scrollController.horizontalController, axis: Axis.horizontal, - child: SizedBox( - width: GridLayout.headerWidth(fields), - child: ScrollConfiguration( - behavior: const ScrollBehavior().copyWith(scrollbars: false), - child: CustomScrollView( - physics: StyledScrollPhysics(), - controller: _scrollController.verticalController, - slivers: [...children], - ), - ), - ), + child: child, ), - ).padding(right: 0, top: GridSize.headerHeight, bottom: GridSize.scrollBarSize); + ); } - Widget _buildHeader(String gridId, List fields) { - return SliverPersistentHeader( - delegate: GridHeaderDelegate(gridId: gridId, fields: fields), - floating: true, - pinned: true, + Widget _buildHeader(String gridId) { + return BlocBuilder( + buildWhen: (previous, current) => previous.fields.length != current.fields.length, + builder: (context, state) { + return SliverPersistentHeader( + delegate: GridHeaderDelegate(gridId: gridId, fields: state.fields), + floating: true, + pinned: true, + ); + }, ); } Widget _buildRows(BuildContext context) { return BlocBuilder( - buildWhen: (previous, current) => previous.rows.length != current.rows.length, + buildWhen: (previous, current) { + final rowChanged = previous.rows.length != current.rows.length; + // final fieldChanged = previous.fields.length != current.fields.length; + return rowChanged; + }, builder: (context, state) { return SliverList( delegate: SliverChildBuilderDelegate( (context, index) { - final rowData = context.read().state.rows[index]; - return GridRowWidget(data: rowData); + final blockRow = context.read().state.rows[index]; + final fields = context.read().state.fields; + final rowData = GridRowData.fromBlockRow(blockRow, fields); + return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)); }, childCount: context.read().state.rows.length, addRepaintBoundaries: true, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart index d612110ecb..fc9eb9b80b 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart @@ -7,20 +7,20 @@ import 'number_cell.dart'; import 'selection_cell.dart'; import 'text_cell.dart'; -Widget buildGridCell(GridCellData cellData) { - switch (cellData.field.fieldType) { +Widget buildGridCell(FieldType fieldType, FutureCellData cellData) { + switch (fieldType) { case FieldType.Checkbox: - return CheckboxCell(cellData: cellData); + return CheckboxCell(cellData: cellData, key: ObjectKey(cellData)); case FieldType.DateTime: - return DateCell(cellData: cellData); + return DateCell(cellData: cellData, key: ObjectKey(cellData)); case FieldType.MultiSelect: - return MultiSelectCell(cellContext: cellData); + return MultiSelectCell(cellData: cellData, key: ObjectKey(cellData)); case FieldType.Number: - return NumberCell(cellData: cellData); + return NumberCell(cellData: cellData, key: ObjectKey(cellData)); case FieldType.RichText: - return GridTextCell(cellData: cellData); + return GridTextCell(cellData: cellData, key: ObjectKey(cellData)); case FieldType.SingleSelect: - return SingleSelectCell(cellContext: cellData); + return SingleSelectCell(cellData: cellData, key: ObjectKey(cellData)); default: throw UnimplementedError; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart index 2f067ab1fa..dc8f757e36 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CheckboxCell extends StatefulWidget { - final GridCellData cellData; + final FutureCellData cellData; const CheckboxCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart index 5d69783fc5..ec1babd799 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class DateCell extends StatefulWidget { - final GridCellData cellData; + final FutureCellData cellData; const DateCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index 3efc47d33c..735143a35a 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -4,61 +4,38 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; import 'cell_container.dart'; -class GridRowWidget extends StatefulWidget { +class GridRowWidget extends StatelessWidget { final GridRowData data; - GridRowWidget({required this.data, Key? key}) : super(key: ValueKey(data.rowId)); - - @override - State createState() => _GridRowWidgetState(); -} - -class _GridRowWidgetState extends State { - late RowBloc _rowBloc; - - @override - void initState() { - _rowBloc = getIt(param1: widget.data)..add(const RowEvent.initial()); - super.initState(); - } + const GridRowWidget({required this.data, Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return BlocProvider.value( - value: _rowBloc, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), - onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: _rowBloc.state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: const [ - _RowLeading(), - _RowCells(), - _RowTrailing(), - ], - ), - ); - }, - ), + return BlocProvider( + create: (context) => getIt(param1: data)..add(const RowEvent.initial()), + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, ), ); } - - @override - Future dispose() async { - _rowBloc.close(); - super.dispose(); - } } class _RowLeading extends StatelessWidget { @@ -115,30 +92,19 @@ class _RowCells extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: (previous, current) => previous.cellDatas != current.cellDatas, builder: (context, state) { - return FutureBuilder( - future: state.cellDatas, - builder: builder, - ); + return Row(children: [ + ...state.fields.map( + (field) { + final cellData = state.cellDataMap.then((fut) => fut[field.id]); + return CellContainer( + width: field.width.toDouble(), + child: buildGridCell(field.fieldType, cellData), + ); + }, + ), + ]); }, ); } - - Widget builder(context, AsyncSnapshot snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.done: - List cellDatas = snapshot.data; - return Row(children: cellDatas.map(_toCell).toList()); - default: - return const SizedBox(); - } - } - - Widget _toCell(GridCellData data) { - return CellContainer( - width: data.field.width.toDouble(), - child: buildGridCell(data), - ); - } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart index 0402b85b12..6983cc1015 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class NumberCell extends StatefulWidget { - final GridCellData cellData; + final FutureCellData cellData; const NumberCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart index 94891924cd..0b1b1828f3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart @@ -3,10 +3,10 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flutter/material.dart'; class SingleSelectCell extends StatefulWidget { - final GridCellData cellContext; + final FutureCellData cellData; const SingleSelectCell({ - required this.cellContext, + required this.cellData, Key? key, }) : super(key: key); @@ -19,7 +19,7 @@ class _SingleSelectCellState extends State { @override void initState() { - _cellBloc = getIt(param1: widget.cellContext); + _cellBloc = getIt(param1: widget.cellData); super.initState(); } @@ -37,10 +37,10 @@ class _SingleSelectCellState extends State { //---------------------------------------------------------------- class MultiSelectCell extends StatefulWidget { - final GridCellData cellContext; + final FutureCellData cellData; const MultiSelectCell({ - required this.cellContext, + required this.cellData, Key? key, }) : super(key: key); @@ -53,7 +53,7 @@ class _MultiSelectCellState extends State { @override void initState() { - _cellBloc = getIt(param1: widget.cellContext); + _cellBloc = getIt(param1: widget.cellData); super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart index d3a9e88c2e..0a8ea79771 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart @@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; /// The interface of base cell. class GridTextCell extends StatefulWidget { - final GridCellData cellData; + final FutureCellData cellData; const GridTextCell({ required this.cellData, Key? key, @@ -36,9 +36,11 @@ class _GridTextCellState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _cellBloc!, - child: BlocBuilder( - buildWhen: (previous, current) { - return _controller.text != current.content; + child: BlocConsumer( + listener: (context, state) { + if (_controller.text != state.content) { + _controller.text = state.content; + } }, builder: (context, state) { return TextField( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 8ac70b3741..6a7c6d05ef 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -1,10 +1,10 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/create_field_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/switch_field_type_bloc.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_name_input.dart'; @@ -21,7 +21,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: _CreateFieldPannelWidget(_createFieldBloc), - constraints: BoxConstraints.loose(const Size(220, 200)), + constraints: BoxConstraints.loose(const Size(220, 400)), ), identifier: identifier(), anchorContext: context, @@ -36,7 +36,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate { } @override - void didRemove() async { + void didRemove() { _createFieldBloc.add(const CreateFieldEvent.done()); } } @@ -51,16 +51,16 @@ class _CreateFieldPannelWidget extends StatelessWidget { value: createFieldBloc, child: BlocBuilder( builder: (context, state) { - return state.editContext.fold( + return state.field.fold( () => const SizedBox(), - (editContext) => ListView( + (field) => ListView( shrinkWrap: true, children: [ const FlowyText.medium("Edit property", fontSize: 12), const VSpace(10), - _FieldNameTextField(editContext.gridField), + const _FieldNameTextField(), const VSpace(10), - _FieldTypeSwitcher(editContext), + _FieldTypeSwitcher(SwitchFieldContext(state.gridId, field, state.typeOptionData)), const VSpace(10), ], ), @@ -72,26 +72,35 @@ class _CreateFieldPannelWidget extends StatelessWidget { } class _FieldTypeSwitcher extends StatelessWidget { - final EditFieldContext editContext; - const _FieldTypeSwitcher(this.editContext, {Key? key}) : super(key: key); + final SwitchFieldContext switchContext; + const _FieldTypeSwitcher(this.switchContext, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return FieldTypeSwitcher(editContext: editContext); - } -} - -class _FieldNameTextField extends StatelessWidget { - final Field field; - const _FieldNameTextField(this.field, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return FieldNameTextField( - name: field.name, - errorText: context.read().state.errorText, - onNameChanged: (newName) { - context.read().add(CreateFieldEvent.updateName(newName)); + return FieldTypeSwitcher( + switchContext: switchContext, + onSelected: (field, typeOptionData) { + context.read().add(CreateFieldEvent.switchField(field, typeOptionData)); + }, + ); + } +} + +class _FieldNameTextField extends StatelessWidget { + const _FieldNameTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) => previous.fieldName != current.fieldName, + builder: (context, state) { + return FieldNameTextField( + name: state.fieldName, + errorText: context.read().state.errorText, + onNameChanged: (newName) { + context.read().add(CreateFieldEvent.updateName(newName)); + }, + ); }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index ed26ecbd64..5362250b95 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -60,7 +60,12 @@ class _FieldTypeSwitcher extends StatelessWidget { return BlocBuilder( builder: (context, state) { final editContext = context.read().state.editContext; - return FieldTypeSwitcher(editContext: editContext); + final switchContext = SwitchFieldContext( + editContext.gridId, + editContext.gridField, + editContext.typeOptionData, + ); + return FieldTypeSwitcher(switchContext: switchContext, onSelected: (field, typeOptionData) {}); }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index df6ecf0d6a..cd9adbd928 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -17,20 +17,22 @@ import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -typedef SelectFieldCallback = void Function(FieldType); +typedef SelectFieldCallback = void Function(Field, Uint8List); class FieldTypeSwitcher extends StatelessWidget { - final EditFieldContext editContext; + final SwitchFieldContext switchContext; + final SelectFieldCallback onSelected; const FieldTypeSwitcher({ - required this.editContext, + required this.switchContext, + required this.onSelected, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: editContext), + create: (context) => getIt(param1: switchContext), child: BlocBuilder( builder: (context, state) { List children = [ @@ -133,7 +135,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(), + child: Container(height: 30, color: Colors.green), ); } } @@ -157,7 +159,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(), + child: Container(height: 80, color: Colors.red), ); } } @@ -194,7 +196,7 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(), + child: Container(height: 100, color: Colors.yellow), ); } } @@ -219,7 +221,7 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(), + child: Container(height: 100, color: Colors.blue), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart index cfac576cd5..dbebb311b9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart @@ -20,7 +20,7 @@ class GridHeaderDelegate extends SliverPersistentHeaderDelegate { @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return GridHeader(gridId: gridId, fields: fields); + return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields)); } @override diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart index 3df1fea4c7..ed960a1c12 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart @@ -63,13 +63,11 @@ class _StyledSingleChildScrollViewState extends State { - impl std::convert::Into for $target { - fn into(self) -> Box { - Box::new(self) + impl std::convert::From<$target> for BoxTypeOptionBuilder { + fn from(target: $target) -> BoxTypeOptionBuilder { + Box::new(target) } } }; 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 d6289dc958..65e80136c3 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 @@ -6,8 +6,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - FieldMeta, GridBlockId, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, - RowMetaChangeset, RowOrder, + FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{ @@ -71,7 +70,7 @@ impl GridBlockMetaEditorManager { .insert(row_meta.id.clone(), row_meta.block_id.clone()); let editor = self.get_editor(&row_meta.block_id).await?; let row_count = editor.create_row(row_meta, start_row_id).await?; - self.notify_block_did_update_row(&block_id).await?; + self.notify_block_did_update_row(block_id).await?; Ok(row_count) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index e150b9f96d..f6e07c831a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -69,20 +69,20 @@ fn string_to_bool(bool_str: &str) -> bool { #[cfg(test)] mod tests { - use crate::services::cell::CheckboxTypeOption; + use crate::services::field::CheckboxTypeOption; use crate::services::row::CellDataSerde; #[test] fn checkout_box_description_test() { let type_option = CheckboxTypeOption::default(); - assert_eq!(description.serialize_cell_data("true").unwrap(), "1".to_owned()); - assert_eq!(description.serialize_cell_data("1").unwrap(), "1".to_owned()); - assert_eq!(description.serialize_cell_data("yes").unwrap(), "1".to_owned()); + assert_eq!(type_option.serialize_cell_data("true").unwrap(), "1".to_owned()); + assert_eq!(type_option.serialize_cell_data("1").unwrap(), "1".to_owned()); + assert_eq!(type_option.serialize_cell_data("yes").unwrap(), "1".to_owned()); - assert_eq!(description.serialize_cell_data("false").unwrap(), "0".to_owned()); - assert_eq!(description.serialize_cell_data("no").unwrap(), "0".to_owned()); - assert_eq!(description.serialize_cell_data("123").unwrap(), "0".to_owned()); + assert_eq!(type_option.serialize_cell_data("false").unwrap(), "0".to_owned()); + assert_eq!(type_option.serialize_cell_data("no").unwrap(), "0".to_owned()); + assert_eq!(type_option.serialize_cell_data("123").unwrap(), "0".to_owned()); - assert_eq!(description.deserialize_cell_data("1".to_owned()), "1".to_owned()); + assert_eq!(type_option.deserialize_cell_data("1".to_owned()), "1".to_owned()); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 4e2a50ea33..dca1654b3e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -177,7 +177,7 @@ impl std::default::Default for TimeFormat { #[cfg(test)] mod tests { - use crate::services::cell::{DateFormat, DateTypeOption, TimeFormat}; + use crate::services::field::{DateFormat, DateTypeOption, TimeFormat}; use crate::services::row::CellDataSerde; use strum::IntoEnumIterator; @@ -267,6 +267,6 @@ mod tests { #[should_panic] fn date_description_invalid_data_test() { let type_option = DateTypeOption::default(); - description.serialize_cell_data("he").unwrap(); + type_option.serialize_cell_data("he").unwrap(); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index f3b546fcc9..67de271309 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -192,41 +192,41 @@ fn make_strip_symbol() -> Vec { #[cfg(test)] mod tests { - use crate::services::cell::{NumberFormat, NumberTypeOption}; + use crate::services::field::{NumberFormat, NumberTypeOption}; use crate::services::row::CellDataSerde; use strum::IntoEnumIterator; #[test] fn number_description_test() { - let mut description = NumberTypeOption::default(); - assert_eq!(description.serialize_cell_data("Â¥18,443").unwrap(), "18443".to_owned()); - assert_eq!(description.serialize_cell_data("$18,443").unwrap(), "18443".to_owned()); - assert_eq!(description.serialize_cell_data("€18.443").unwrap(), "18443".to_owned()); + let mut type_option = NumberTypeOption::default(); + assert_eq!(type_option.serialize_cell_data("Â¥18,443").unwrap(), "18443".to_owned()); + assert_eq!(type_option.serialize_cell_data("$18,443").unwrap(), "18443".to_owned()); + assert_eq!(type_option.serialize_cell_data("€18.443").unwrap(), "18443".to_owned()); for format in NumberFormat::iter() { - description.format = format; + type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "$18,443".to_owned() ); } NumberFormat::CNY => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "€18.443".to_owned() ); } @@ -236,35 +236,35 @@ mod tests { #[test] fn number_description_scale_test() { - let mut description = NumberTypeOption { + let mut type_option = NumberTypeOption { scale: 1, ..Default::default() }; for format in NumberFormat::iter() { - description.format = format; + type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "$1,844.3".to_owned() ); } NumberFormat::CNY => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "Â¥1,844.3".to_owned() ); } NumberFormat::EUR => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "€1.844,3".to_owned() ); } @@ -274,35 +274,35 @@ mod tests { #[test] fn number_description_sign_test() { - let mut description = NumberTypeOption { + let mut type_option = NumberTypeOption { sign_positive: false, ..Default::default() }; for format in NumberFormat::iter() { - description.format = format; + type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "-$18,443".to_owned() ); } NumberFormat::CNY => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "-Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - description.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data("18443".to_owned()), "-€18.443".to_owned() ); } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 84feb9e051..73dd3bd432 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -166,16 +166,16 @@ impl SelectOption { #[cfg(test)] mod tests { - use crate::services::cell::{MultiSelectDescription, SingleSelectTypeOption}; + use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; use crate::services::row::CellDataSerde; #[test] #[should_panic] fn selection_description_test() { let type_option = SingleSelectTypeOption::default(); - assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1".to_owned()); + assert_eq!(type_option.serialize_cell_data("1,2,3").unwrap(), "1".to_owned()); - let type_option = MultiSelectDescription::default(); - assert_eq!(description.serialize_cell_data("1,2,3").unwrap(), "1,2,3".to_owned()); + let type_option = MultiSelectTypeOption::default(); + assert_eq!(type_option.serialize_cell_data("1,2,3").unwrap(), "1,2,3".to_owned()); } } 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 6978705592..6a27fdbb72 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{default_type_option_builder_from_type, type_option_json_str_from_bytes, FieldBuilder}; +use crate::services::field::{type_option_json_str_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; @@ -78,8 +78,8 @@ impl ClientGridEditor { } pub async fn default_field_meta(&self, field_type: &FieldType) -> FlowyResult { - let name = format!("Property {}", self.pad.read().await.fields().len()); - let field_meta = FieldBuilder::from_field_type(&field_type).name(&name).build(); + let name = format!("Property {}", self.pad.read().await.fields().len() + 1); + let field_meta = FieldBuilder::from_field_type(field_type).name(&name).build(); Ok(field_meta) } diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 1638060f61..9cc8e078e0 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -1,5 +1,5 @@ use crate::services::field::*; -use flowy_grid_data_model::entities::{BuildGridContext, FieldType}; +use flowy_grid_data_model::entities::BuildGridContext; use flowy_sync::client_grid::GridBuilder; pub fn make_default_grid() -> BuildGridContext { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 5881c7ee84..3f18e5a9c0 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -254,19 +254,19 @@ async fn grid_row_add_cells_test() { } FieldType::SingleSelect => { let type_option = SingleSelectTypeOption::from(field); - let options = description.options.first().unwrap(); - let data = description.serialize_cell_data(&options.id).unwrap(); + let options = type_option.options.first().unwrap(); + let data = type_option.serialize_cell_data(&options.id).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::MultiSelect => { let type_option = MultiSelectTypeOption::from(field); - let options = description + let options = type_option .options .iter() .map(|option| option.id.clone()) .collect::>() .join(SELECTION_IDS_SEPARATOR); - let data = description.serialize_cell_data(&options).unwrap(); + let data = type_option.serialize_cell_data(&options).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::Checkbox => { @@ -383,11 +383,11 @@ async fn grid_cell_update() { FieldType::DateTime => "123".to_string(), FieldType::SingleSelect => { let type_option = SingleSelectTypeOption::from(field_meta); - description.options.first().unwrap().id.clone() + type_option.options.first().unwrap().id.clone() } FieldType::MultiSelect => { let type_option = MultiSelectTypeOption::from(field_meta); - description.options.first().unwrap().id.clone() + type_option.options.first().unwrap().id.clone() } FieldType::Checkbox => "1".to_string(), }; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index b2dbc2c7a9..7739356531 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -3,8 +3,8 @@ use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, CreateFieldPayload, Field, FieldChangeset, FieldMeta, FieldType, - GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, + BuildGridContext, CellMetaChangeset, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, + GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_grid_data_model::parser::CreateFieldParams; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs index d1c6f94380..f9ed7c72ac 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs @@ -4,6 +4,7 @@ mod op_test; mod serde_test; mod undo_redo_test; +use derive_more::Display; use flowy_sync::client_document::{ClientDocument, InitialDocumentText}; use lib_ot::{ core::*, 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 6d17fbca0f..a52d507c87 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -39,20 +39,6 @@ pub struct Field { pub width: i32, } -#[derive(Debug, Clone, Default, ProtoBuf)] -pub struct FieldOrder { - #[pb(index = 1)] - pub field_id: String, -} - -impl std::convert::From<&FieldMeta> for FieldOrder { - fn from(field_meta: &FieldMeta) -> Self { - Self { - field_id: field_meta.id.clone(), - } - } -} - impl std::convert::From for Field { fn from(field_meta: FieldMeta) -> Self { Self { @@ -67,6 +53,20 @@ impl std::convert::From for Field { } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct FieldOrder { + #[pb(index = 1)] + pub field_id: String, +} + +impl std::convert::From<&FieldMeta> for FieldOrder { + fn from(field_meta: &FieldMeta) -> Self { + Self { + field_id: field_meta.id.clone(), + } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct CreateEditFieldContextParams { #[pb(index = 1)] diff --git a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs b/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs index f2eb8423bb..5003ab2ce4 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs @@ -4,12 +4,11 @@ use uuid::Uuid; pub struct NotEmptyUuid(pub String); impl NotEmptyUuid { - pub fn parse(s: String) -> Result { - debug_assert!(Uuid::parse_str(&s).is_ok()); - + pub fn parse(s: String) -> Result { if s.trim().is_empty() { - return Err(()); + return Err("Input string is empty".to_owned()); } + debug_assert!(Uuid::parse_str(&s).is_ok()); Ok(Self(s)) } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 44b848a275..9375f80ed0 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -5,7 +5,7 @@ use bytes::Bytes; use flowy_grid_data_model::entities::{ FieldChangeset, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, }; -use flowy_grid_data_model::parser::CreateFieldParams; + use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::collections::HashMap; @@ -43,12 +43,7 @@ impl GridMetaPad { ) -> CollaborateResult> { self.modify_grid(|grid| { // Check if the field exists or not - if grid - .fields - .iter() - .find(|field_meta| field_meta.id == new_field_meta.id) - .is_some() - { + if grid.fields.iter().any(|field_meta| field_meta.id == new_field_meta.id) { tracing::warn!("Duplicate grid field"); return Ok(None); } From b65b4796d2d3da694d2332b9220c0f59bd803369 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 26 Mar 2022 21:03:54 +0800 Subject: [PATCH 11/47] fix: add event after bloc close --- .../lib/startup/tasks/app_widget.dart | 2 +- .../grid/cell_bloc/checkbox_cell_bloc.dart | 2 - .../grid/cell_bloc/text_cell_bloc.dart | 15 ++-- .../application/grid/row/row_bloc.dart | 15 ++-- .../application/grid/row/row_service.dart | 2 +- .../src/widgets/content/cell_builder.dart | 21 +++-- .../grid/src/widgets/content/grid_row.dart | 85 ++++++++++++------- .../grid/src/widgets/content/text_cell.dart | 15 ++-- 8 files changed, 91 insertions(+), 66 deletions(-) diff --git a/frontend/app_flowy/lib/startup/tasks/app_widget.dart b/frontend/app_flowy/lib/startup/tasks/app_widget.dart index 78672193da..9f5493b256 100644 --- a/frontend/app_flowy/lib/startup/tasks/app_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/app_widget.dart @@ -112,7 +112,7 @@ class ApplicationBlocObserver extends BlocObserver { // ignore: unnecessary_overrides void onTransition(Bloc bloc, Transition transition) { // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}"); - Log.debug("${transition.nextState}"); + // Log.debug("${transition.nextState}"); super.onTransition(bloc, transition); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index 3e3c1b37bc..3609f39de7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -15,8 +15,6 @@ class CheckboxCellBloc extends Bloc { required this.service, required FutureCellData cellData, }) : super(CheckboxCellState.initial()) { - cellData.then((a) {}); - on( (event, emit) async { await event.map( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index 73c2e8e03d..985fad03be 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -12,13 +12,7 @@ class TextCellBloc extends Bloc { TextCellBloc({ required this.service, required FutureCellData cellData, - }) : super(TextCellState.initial()) { - cellData.then((cellData) { - if (cellData != null) { - add(TextCellEvent.didReceiveCellData(cellData)); - } - }); - + }) : super(TextCellState.initial(cellData)) { on( (event, emit) async { await event.map( @@ -69,8 +63,11 @@ class TextCellEvent with _$TextCellEvent { class TextCellState with _$TextCellState { const factory TextCellState({ required String content, - GridCellData? cellData, + required FutureCellData cellData, }) = _TextCellState; - factory TextCellState.initial() => const TextCellState(content: ""); + factory TextCellState.initial(FutureCellData cellData) => TextCellState( + content: cellData?.cell?.content ?? "", + cellData: cellData, + ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index ba6b64f602..2bb78799f0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -50,12 +50,11 @@ class RowBloc extends Bloc { emit(state.copyWith(fields: value.fields)); add(const RowEvent.didUpdateCell()); }, - didUpdateCell: (_DidUpdateCell value) { - final Future cellDataMap = state.row.then( - (someRow) => someRow.fold( - () => HashMap.identity(), - (row) => _makeCellDatas(row), - ), + didUpdateCell: (_DidUpdateCell value) async { + final optionRow = await state.row; + final CellDataMap cellDataMap = optionRow.fold( + () => HashMap.identity(), + (row) => _makeCellDatas(row), ); emit(state.copyWith(cellDataMap: cellDataMap)); }, @@ -147,7 +146,7 @@ class RowState with _$RowState { required double rowHeight, required List fields, required Future> row, - required Future cellDataMap, + required CellDataMap? cellDataMap, }) = _RowState; factory RowState.initial(GridRowData data) => RowState( @@ -156,6 +155,6 @@ class RowState with _$RowState { rowHeight: data.height, fields: data.fields, row: Future(() => none()), - cellDataMap: Future(() => CellDataMap.identity()), + cellDataMap: null, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 7c77c0de64..d30a22b7d0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -29,7 +29,7 @@ class RowService { } } -typedef FutureCellData = Future; +typedef FutureCellData = GridCellData?; class GridCellData extends Equatable { final String gridId; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart index fc9eb9b80b..856338aea4 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; @@ -7,20 +8,24 @@ import 'number_cell.dart'; import 'selection_cell.dart'; import 'text_cell.dart'; -Widget buildGridCell(FieldType fieldType, FutureCellData cellData) { - switch (fieldType) { +Widget buildGridCell(String rowId, Field field, FutureCellData cellData) { + if (cellData == null) { + return const SizedBox(); + } + final key = ValueKey(field.id + rowId); + switch (field.fieldType) { case FieldType.Checkbox: - return CheckboxCell(cellData: cellData, key: ObjectKey(cellData)); + return CheckboxCell(cellData: cellData, key: key); case FieldType.DateTime: - return DateCell(cellData: cellData, key: ObjectKey(cellData)); + return DateCell(cellData: cellData, key: key); case FieldType.MultiSelect: - return MultiSelectCell(cellData: cellData, key: ObjectKey(cellData)); + return MultiSelectCell(cellData: cellData, key: key); case FieldType.Number: - return NumberCell(cellData: cellData, key: ObjectKey(cellData)); + return NumberCell(cellData: cellData, key: key); case FieldType.RichText: - return GridTextCell(cellData: cellData, key: ObjectKey(cellData)); + return GridTextCell(cellData: cellData, key: key); case FieldType.SingleSelect: - return SingleSelectCell(cellData: cellData, key: ObjectKey(cellData)); + return SingleSelectCell(cellData: cellData, key: key); default: throw UnimplementedError; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index 735143a35a..b8834cd213 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -4,38 +4,61 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; import 'cell_container.dart'; -class GridRowWidget extends StatelessWidget { +class GridRowWidget extends StatefulWidget { final GridRowData data; const GridRowWidget({required this.data, Key? key}) : super(key: key); + @override + State createState() => _GridRowWidgetState(); +} + +class _GridRowWidgetState extends State { + late RowBloc _rowBloc; + + @override + void initState() { + _rowBloc = getIt(param1: widget.data)..add(const RowEvent.initial()); + super.initState(); + } + @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: data)..add(const RowEvent.initial()), - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: const [ - _RowLeading(), - _RowCells(), - _RowTrailing(), - ], - ), - ); - }, + return BlocProvider.value( + value: _rowBloc, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), + onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: _rowBloc.state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, + ), ), ); } + + @override + Future dispose() async { + _rowBloc.close(); + super.dispose(); + } } class _RowLeading extends StatelessWidget { @@ -92,18 +115,20 @@ class _RowCells extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( + buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap, builder: (context, state) { - return Row(children: [ - ...state.fields.map( - (field) { - final cellData = state.cellDataMap.then((fut) => fut[field.id]); - return CellContainer( - width: field.width.toDouble(), - child: buildGridCell(field.fieldType, cellData), - ); - }, - ), - ]); + final children = state.fields + .map((field) => CellContainer( + width: field.width.toDouble(), + child: buildGridCell( + state.rowId, + field, + state.cellDataMap?[field.id], + ), + )) + .toList(); + + return Row(children: children); }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart index 0a8ea79771..e8c571bded 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart @@ -22,12 +22,12 @@ class _GridTextCellState extends State { late TextEditingController _controller; Timer? _delayOperation; final _focusNode = FocusNode(); - TextCellBloc? _cellBloc; + late TextCellBloc _cellBloc; @override void initState() { _cellBloc = getIt(param1: widget.cellData); - _controller = TextEditingController(text: _cellBloc!.state.content); + _controller = TextEditingController(text: _cellBloc.state.content); _focusNode.addListener(save); super.initState(); } @@ -35,7 +35,7 @@ class _GridTextCellState extends State { @override Widget build(BuildContext context) { return BlocProvider.value( - value: _cellBloc!, + value: _cellBloc, child: BlocConsumer( listener: (context, state) { if (_controller.text != state.content) { @@ -71,8 +71,7 @@ class _GridTextCellState extends State { @override Future dispose() async { - _cellBloc?.close(); - _cellBloc = null; + _cellBloc.close(); _focusNode.removeListener(save); _focusNode.dispose(); super.dispose(); @@ -80,8 +79,10 @@ class _GridTextCellState extends State { Future save() async { _delayOperation?.cancel(); - _delayOperation = Timer(const Duration(seconds: 2), () { - _cellBloc?.add(TextCellEvent.updateText(_controller.text)); + _delayOperation = Timer(const Duration(milliseconds: 300), () { + if (_cellBloc.isClosed == false) { + _cellBloc.add(TextCellEvent.updateText(_controller.text)); + } }); // and later, before the timer goes off... } From c7bba01fe54f31e8f410a52c00aa220df950413e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 27 Mar 2022 09:35:10 +0800 Subject: [PATCH 12/47] chore: delete field --- .../grid/field/create_field_bloc.dart | 7 +- .../grid/field/edit_field_bloc.dart | 2 + .../application/grid/field/field_service.dart | 39 ++- ...eld_editor.dart => edit_field_pannel.dart} | 6 +- .../grid/src/widgets/header/header_cell.dart | 4 +- .../dart_event/flowy-grid/dart_event.dart | 17 + .../flowy-error-code/code.pbenum.dart | 6 +- .../flowy-error-code/code.pbjson.dart | 5 +- .../flowy-grid-data-model/meta.pb.dart | 116 +++---- .../flowy-grid-data-model/meta.pbjson.dart | 14 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 4 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 5 +- .../rust-lib/flowy-grid/src/event_handler.rs | 24 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 6 +- .../src/protobuf/model/event_map.rs | 16 +- .../src/protobuf/proto/event_map.proto | 3 +- .../flowy-grid/src/services/grid_editor.rs | 19 +- .../flowy-grid/tests/grid/grid_test.rs | 4 +- shared-lib/flowy-error-code/src/code.rs | 7 +- .../src/protobuf/model/code.rs | 15 +- .../src/protobuf/proto/code.proto | 3 +- .../src/entities/grid.rs | 108 ++++++ .../src/entities/meta.rs | 46 ++- .../src/parser/grid_params.rs | 112 ------ .../flowy-grid-data-model/src/parser/mod.rs | 2 - .../src/protobuf/model/meta.rs | 325 +++++++++--------- .../src/protobuf/proto/meta.proto | 4 +- .../src/client_grid/grid_meta_pad.rs | 18 +- 28 files changed, 540 insertions(+), 397 deletions(-) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{field_editor.dart => edit_field_pannel.dart} (93%) delete mode 100644 shared-lib/flowy-grid-data-model/src/parser/grid_params.rs diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart index 0fd0fb0a83..29f7187c2f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -44,7 +44,12 @@ class CreateFieldBloc extends Bloc { await state.field.fold( () async => null, (field) async { - final result = await service.createField(field: field, typeOptionData: state.typeOptionData); + field.name = state.fieldName; + + final result = await service.createField( + field: field, + typeOptionData: state.typeOptionData, + ); result.fold((l) => null, (r) => null); }, ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart index 75a0a7c9bc..11dbe765fc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -21,6 +21,7 @@ class EditFieldBloc extends Bloc { hideField: (_HideField value) {}, deleteField: (_DeleteField value) {}, duplicateField: (_DuplicateField value) {}, + saveField: (_SaveField value) {}, ); }, ); @@ -39,6 +40,7 @@ class EditFieldEvent with _$EditFieldEvent { const factory EditFieldEvent.hideField() = _HideField; const factory EditFieldEvent.duplicateField() = _DuplicateField; const factory EditFieldEvent.deleteField() = _DeleteField; + const factory EditFieldEvent.saveField() = _SaveField; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index f9d7ea9f09..84566da604 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -6,7 +6,6 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; class FieldService { final String gridId; @@ -21,6 +20,44 @@ class FieldService { return GridEventCreateEditFieldContext(payload).send(); } + Future> updateField({ + required Field field, + String? name, + FieldType? fieldType, + bool? frozen, + bool? visibility, + double? width, + List? typeOptionData, + }) { + var payload = FieldChangesetPayload.create()..gridId = gridId; + + if (name != null) { + payload.name = name; + } + + if (fieldType != null) { + payload.fieldType = fieldType; + } + + if (frozen != null) { + payload.frozen = frozen; + } + + if (visibility != null) { + payload.visibility = visibility; + } + + if (width != null) { + payload.width = width.toInt(); + } + + if (typeOptionData != null) { + payload.typeOptionData = typeOptionData; + } + + return GridEventUpdateField(payload).send(); + } + Future> createField({ required Field field, List? typeOptionData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart similarity index 93% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart index 5362250b95..47affb67e8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart @@ -10,12 +10,12 @@ import 'field_name_input.dart'; import 'field_operation_list.dart'; import 'field_tyep_switcher.dart'; -class FieldEditor extends StatelessWidget { +class EditFieldPannel extends StatelessWidget { final GridFieldData fieldData; - const FieldEditor({required this.fieldData, Key? key}) : super(key: key); + const EditFieldPannel({required this.fieldData, Key? key}) : super(key: key); static void show(BuildContext context, GridFieldData fieldData) { - final editor = FieldEditor(fieldData: fieldData); + final editor = EditFieldPannel(fieldData: fieldData); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: editor, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index d6e0faff47..52e7e38d75 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'field_editor.dart'; +import 'edit_field_pannel.dart'; class HeaderCell extends StatelessWidget { final GridFieldData fieldData; @@ -18,7 +18,7 @@ class HeaderCell extends StatelessWidget { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => FieldEditor.show(context, fieldData), + onTap: () => EditFieldPannel.show(context, fieldData), rightIcon: svg("editor/details", color: theme.iconColor), text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 88f404d4f6..0c3d242c37 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -86,6 +86,23 @@ class GridEventCreateField { } } +class GridEventDeleteField { + FieldOrder request; + GridEventDeleteField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.DeleteField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateEditFieldContext { CreateEditFieldContextParams request; GridEventCreateEditFieldContext(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart index d7119ad727..307b9f86f2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -46,7 +46,8 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode BlockIdIsEmpty = ErrorCode._(420, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockIdIsEmpty'); static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty'); static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty'); - static const ErrorCode TypeOptionIsEmpty = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionIsEmpty'); + static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist'); + static const ErrorCode TypeOptionDataIsEmpty = ErrorCode._(450, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionDataIsEmpty'); static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData'); static const $core.List values = [ @@ -86,7 +87,8 @@ class ErrorCode extends $pb.ProtobufEnum { BlockIdIsEmpty, RowIdIsEmpty, FieldIdIsEmpty, - TypeOptionIsEmpty, + FieldDoesNotExist, + TypeOptionDataIsEmpty, InvalidData, ]; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart index 41815194f2..9345118baa 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -48,10 +48,11 @@ const ErrorCode$json = const { const {'1': 'BlockIdIsEmpty', '2': 420}, const {'1': 'RowIdIsEmpty', '2': 430}, const {'1': 'FieldIdIsEmpty', '2': 440}, - const {'1': 'TypeOptionIsEmpty', '2': 441}, + const {'1': 'FieldDoesNotExist', '2': 441}, + const {'1': 'TypeOptionDataIsEmpty', '2': 450}, const {'1': 'InvalidData', '2': 500}, ], }; /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFUeXBlT3B0aW9uSXNFbXB0eRC5AxIQCgtJbnZhbGlkRGF0YRD0Aw=='); +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index d76dac347c..bc29686021 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -351,71 +351,71 @@ class FieldMeta extends $pb.GeneratedMessage { void clearTypeOptionJson() => clearField(8); } -enum FieldChangeset_OneOfName { +enum FieldChangesetPayload_OneOfName { name, notSet } -enum FieldChangeset_OneOfDesc { +enum FieldChangesetPayload_OneOfDesc { desc, notSet } -enum FieldChangeset_OneOfFieldType { +enum FieldChangesetPayload_OneOfFieldType { fieldType, notSet } -enum FieldChangeset_OneOfFrozen { +enum FieldChangesetPayload_OneOfFrozen { frozen, notSet } -enum FieldChangeset_OneOfVisibility { +enum FieldChangesetPayload_OneOfVisibility { visibility, notSet } -enum FieldChangeset_OneOfWidth { +enum FieldChangesetPayload_OneOfWidth { width, notSet } -enum FieldChangeset_OneOfTypeOptions { - typeOptions, +enum FieldChangesetPayload_OneOfTypeOptionData { + typeOptionData, notSet } -class FieldChangeset extends $pb.GeneratedMessage { - static const $core.Map<$core.int, FieldChangeset_OneOfName> _FieldChangeset_OneOfNameByTag = { - 3 : FieldChangeset_OneOfName.name, - 0 : FieldChangeset_OneOfName.notSet +class FieldChangesetPayload extends $pb.GeneratedMessage { + static const $core.Map<$core.int, FieldChangesetPayload_OneOfName> _FieldChangesetPayload_OneOfNameByTag = { + 3 : FieldChangesetPayload_OneOfName.name, + 0 : FieldChangesetPayload_OneOfName.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfDesc> _FieldChangeset_OneOfDescByTag = { - 4 : FieldChangeset_OneOfDesc.desc, - 0 : FieldChangeset_OneOfDesc.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfDesc> _FieldChangesetPayload_OneOfDescByTag = { + 4 : FieldChangesetPayload_OneOfDesc.desc, + 0 : FieldChangesetPayload_OneOfDesc.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfFieldType> _FieldChangeset_OneOfFieldTypeByTag = { - 5 : FieldChangeset_OneOfFieldType.fieldType, - 0 : FieldChangeset_OneOfFieldType.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfFieldType> _FieldChangesetPayload_OneOfFieldTypeByTag = { + 5 : FieldChangesetPayload_OneOfFieldType.fieldType, + 0 : FieldChangesetPayload_OneOfFieldType.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfFrozen> _FieldChangeset_OneOfFrozenByTag = { - 6 : FieldChangeset_OneOfFrozen.frozen, - 0 : FieldChangeset_OneOfFrozen.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfFrozen> _FieldChangesetPayload_OneOfFrozenByTag = { + 6 : FieldChangesetPayload_OneOfFrozen.frozen, + 0 : FieldChangesetPayload_OneOfFrozen.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfVisibility> _FieldChangeset_OneOfVisibilityByTag = { - 7 : FieldChangeset_OneOfVisibility.visibility, - 0 : FieldChangeset_OneOfVisibility.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfVisibility> _FieldChangesetPayload_OneOfVisibilityByTag = { + 7 : FieldChangesetPayload_OneOfVisibility.visibility, + 0 : FieldChangesetPayload_OneOfVisibility.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfWidth> _FieldChangeset_OneOfWidthByTag = { - 8 : FieldChangeset_OneOfWidth.width, - 0 : FieldChangeset_OneOfWidth.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfWidth> _FieldChangesetPayload_OneOfWidthByTag = { + 8 : FieldChangesetPayload_OneOfWidth.width, + 0 : FieldChangesetPayload_OneOfWidth.notSet }; - static const $core.Map<$core.int, FieldChangeset_OneOfTypeOptions> _FieldChangeset_OneOfTypeOptionsByTag = { - 9 : FieldChangeset_OneOfTypeOptions.typeOptions, - 0 : FieldChangeset_OneOfTypeOptions.notSet + static const $core.Map<$core.int, FieldChangesetPayload_OneOfTypeOptionData> _FieldChangesetPayload_OneOfTypeOptionDataByTag = { + 9 : FieldChangesetPayload_OneOfTypeOptionData.typeOptionData, + 0 : FieldChangesetPayload_OneOfTypeOptionData.notSet }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangeset', createEmptyInstance: create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangesetPayload', createEmptyInstance: create) ..oo(0, [3]) ..oo(1, [4]) ..oo(2, [5]) @@ -431,12 +431,12 @@ class FieldChangeset extends $pb.GeneratedMessage { ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions') + ..a<$core.List<$core.int>>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY) ..hasRequiredFields = false ; - FieldChangeset._() : super(); - factory FieldChangeset({ + FieldChangesetPayload._() : super(); + factory FieldChangesetPayload({ $core.String? fieldId, $core.String? gridId, $core.String? name, @@ -445,7 +445,7 @@ class FieldChangeset extends $pb.GeneratedMessage { $core.bool? frozen, $core.bool? visibility, $core.int? width, - $core.String? typeOptions, + $core.List<$core.int>? typeOptionData, }) { final _result = create(); if (fieldId != null) { @@ -472,52 +472,52 @@ class FieldChangeset extends $pb.GeneratedMessage { if (width != null) { _result.width = width; } - if (typeOptions != null) { - _result.typeOptions = typeOptions; + if (typeOptionData != null) { + _result.typeOptionData = typeOptionData; } return _result; } - factory FieldChangeset.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory FieldChangeset.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory FieldChangesetPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FieldChangesetPayload.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') - FieldChangeset clone() => FieldChangeset()..mergeFromMessage(this); + FieldChangesetPayload clone() => FieldChangesetPayload()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - FieldChangeset copyWith(void Function(FieldChangeset) updates) => super.copyWith((message) => updates(message as FieldChangeset)) as FieldChangeset; // ignore: deprecated_member_use + FieldChangesetPayload copyWith(void Function(FieldChangesetPayload) updates) => super.copyWith((message) => updates(message as FieldChangesetPayload)) as FieldChangesetPayload; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static FieldChangeset create() => FieldChangeset._(); - FieldChangeset createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static FieldChangesetPayload create() => FieldChangesetPayload._(); + FieldChangesetPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static FieldChangeset getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static FieldChangeset? _defaultInstance; + static FieldChangesetPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FieldChangesetPayload? _defaultInstance; - FieldChangeset_OneOfName whichOneOfName() => _FieldChangeset_OneOfNameByTag[$_whichOneof(0)]!; + FieldChangesetPayload_OneOfName whichOneOfName() => _FieldChangesetPayload_OneOfNameByTag[$_whichOneof(0)]!; void clearOneOfName() => clearField($_whichOneof(0)); - FieldChangeset_OneOfDesc whichOneOfDesc() => _FieldChangeset_OneOfDescByTag[$_whichOneof(1)]!; + FieldChangesetPayload_OneOfDesc whichOneOfDesc() => _FieldChangesetPayload_OneOfDescByTag[$_whichOneof(1)]!; void clearOneOfDesc() => clearField($_whichOneof(1)); - FieldChangeset_OneOfFieldType whichOneOfFieldType() => _FieldChangeset_OneOfFieldTypeByTag[$_whichOneof(2)]!; + FieldChangesetPayload_OneOfFieldType whichOneOfFieldType() => _FieldChangesetPayload_OneOfFieldTypeByTag[$_whichOneof(2)]!; void clearOneOfFieldType() => clearField($_whichOneof(2)); - FieldChangeset_OneOfFrozen whichOneOfFrozen() => _FieldChangeset_OneOfFrozenByTag[$_whichOneof(3)]!; + FieldChangesetPayload_OneOfFrozen whichOneOfFrozen() => _FieldChangesetPayload_OneOfFrozenByTag[$_whichOneof(3)]!; void clearOneOfFrozen() => clearField($_whichOneof(3)); - FieldChangeset_OneOfVisibility whichOneOfVisibility() => _FieldChangeset_OneOfVisibilityByTag[$_whichOneof(4)]!; + FieldChangesetPayload_OneOfVisibility whichOneOfVisibility() => _FieldChangesetPayload_OneOfVisibilityByTag[$_whichOneof(4)]!; void clearOneOfVisibility() => clearField($_whichOneof(4)); - FieldChangeset_OneOfWidth whichOneOfWidth() => _FieldChangeset_OneOfWidthByTag[$_whichOneof(5)]!; + FieldChangesetPayload_OneOfWidth whichOneOfWidth() => _FieldChangesetPayload_OneOfWidthByTag[$_whichOneof(5)]!; void clearOneOfWidth() => clearField($_whichOneof(5)); - FieldChangeset_OneOfTypeOptions whichOneOfTypeOptions() => _FieldChangeset_OneOfTypeOptionsByTag[$_whichOneof(6)]!; - void clearOneOfTypeOptions() => clearField($_whichOneof(6)); + FieldChangesetPayload_OneOfTypeOptionData whichOneOfTypeOptionData() => _FieldChangesetPayload_OneOfTypeOptionDataByTag[$_whichOneof(6)]!; + void clearOneOfTypeOptionData() => clearField($_whichOneof(6)); @$pb.TagNumber(1) $core.String get fieldId => $_getSZ(0); @@ -592,13 +592,13 @@ class FieldChangeset extends $pb.GeneratedMessage { void clearWidth() => clearField(8); @$pb.TagNumber(9) - $core.String get typeOptions => $_getSZ(8); + $core.List<$core.int> get typeOptionData => $_getN(8); @$pb.TagNumber(9) - set typeOptions($core.String v) { $_setString(8, v); } + set typeOptionData($core.List<$core.int> v) { $_setBytes(8, v); } @$pb.TagNumber(9) - $core.bool hasTypeOptions() => $_has(8); + $core.bool hasTypeOptionData() => $_has(8); @$pb.TagNumber(9) - void clearTypeOptions() => clearField(9); + void clearTypeOptionData() => clearField(9); } class AnyData extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index cec14f8af9..7c690f7b1e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -75,9 +75,9 @@ const FieldMeta$json = const { /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSKAoQdHlwZV9vcHRpb25fanNvbhgIIAEoCVIOdHlwZU9wdGlvbkpzb24='); -@$core.Deprecated('Use fieldChangesetDescriptor instead') -const FieldChangeset$json = const { - '1': 'FieldChangeset', +@$core.Deprecated('Use fieldChangesetPayloadDescriptor instead') +const FieldChangesetPayload$json = const { + '1': 'FieldChangesetPayload', '2': const [ const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, @@ -87,7 +87,7 @@ const FieldChangeset$json = const { const {'1': 'frozen', '3': 6, '4': 1, '5': 8, '9': 3, '10': 'frozen'}, const {'1': 'visibility', '3': 7, '4': 1, '5': 8, '9': 4, '10': 'visibility'}, const {'1': 'width', '3': 8, '4': 1, '5': 5, '9': 5, '10': 'width'}, - const {'1': 'type_options', '3': 9, '4': 1, '5': 9, '9': 6, '10': 'typeOptions'}, + const {'1': 'type_option_data', '3': 9, '4': 1, '5': 12, '9': 6, '10': 'typeOptionData'}, ], '8': const [ const {'1': 'one_of_name'}, @@ -96,12 +96,12 @@ const FieldChangeset$json = const { const {'1': 'one_of_frozen'}, const {'1': 'one_of_visibility'}, const {'1': 'one_of_width'}, - const {'1': 'one_of_type_options'}, + const {'1': 'one_of_type_option_data'}, ], }; -/// Descriptor for `FieldChangeset`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIXCgdncmlkX2lkGAIgASgJUgZncmlkSWQSFAoEbmFtZRgDIAEoCUgAUgRuYW1lEhQKBGRlc2MYBCABKAlIAVIEZGVzYxIrCgpmaWVsZF90eXBlGAUgASgOMgouRmllbGRUeXBlSAJSCWZpZWxkVHlwZRIYCgZmcm96ZW4YBiABKAhIA1IGZnJvemVuEiAKCnZpc2liaWxpdHkYByABKAhIBFIKdmlzaWJpbGl0eRIWCgV3aWR0aBgIIAEoBUgFUgV3aWR0aBIjCgx0eXBlX29wdGlvbnMYCSABKAlIBlILdHlwZU9wdGlvbnNCDQoLb25lX29mX25hbWVCDQoLb25lX29mX2Rlc2NCEwoRb25lX29mX2ZpZWxkX3R5cGVCDwoNb25lX29mX2Zyb3plbkITChFvbmVfb2ZfdmlzaWJpbGl0eUIOCgxvbmVfb2Zfd2lkdGhCFQoTb25lX29mX3R5cGVfb3B0aW9ucw=='); +/// Descriptor for `FieldChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List fieldChangesetPayloadDescriptor = $convert.base64Decode('ChVGaWVsZENoYW5nZXNldFBheWxvYWQSGQoIZmllbGRfaWQYASABKAlSB2ZpZWxkSWQSFwoHZ3JpZF9pZBgCIAEoCVIGZ3JpZElkEhQKBG5hbWUYAyABKAlIAFIEbmFtZRIUCgRkZXNjGAQgASgJSAFSBGRlc2MSKwoKZmllbGRfdHlwZRgFIAEoDjIKLkZpZWxkVHlwZUgCUglmaWVsZFR5cGUSGAoGZnJvemVuGAYgASgISANSBmZyb3plbhIgCgp2aXNpYmlsaXR5GAcgASgISARSCnZpc2liaWxpdHkSFgoFd2lkdGgYCCABKAVIBVIFd2lkdGgSKgoQdHlwZV9vcHRpb25fZGF0YRgJIAEoDEgGUg50eXBlT3B0aW9uRGF0YUINCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0ITChFvbmVfb2ZfZmllbGRfdHlwZUIPCg1vbmVfb2ZfZnJvemVuQhMKEW9uZV9vZl92aXNpYmlsaXR5Qg4KDG9uZV9vZl93aWR0aEIZChdvbmVfb2ZfdHlwZV9vcHRpb25fZGF0YQ=='); @$core.Deprecated('Use anyDataDescriptor instead') const AnyData$json = const { '1': 'AnyData', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 74cb74e42e..755b1c1ed1 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -15,7 +15,8 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields'); static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); - static const GridEvent CreateEditFieldContext = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); + static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); + static const GridEvent CreateEditFieldContext = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); @@ -26,6 +27,7 @@ class GridEvent extends $pb.ProtobufEnum { GetFields, UpdateField, CreateField, + DeleteField, CreateEditFieldContext, CreateRow, GetRow, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 386cdd5bcb..9441a03bea 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -17,7 +17,8 @@ const GridEvent$json = const { const {'1': 'GetFields', '2': 10}, const {'1': 'UpdateField', '2': 11}, const {'1': 'CreateField', '2': 12}, - const {'1': 'CreateEditFieldContext', '2': 13}, + const {'1': 'DeleteField', '2': 13}, + const {'1': 'CreateEditFieldContext', '2': 14}, const {'1': 'CreateRow', '2': 21}, const {'1': 'GetRow', '2': 22}, const {'1': 'UpdateCell', '2': 30}, @@ -25,4 +26,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhoKFkNyZWF0ZUVkaXRGaWVsZENvbnRleHQQDRINCglDcmVhdGVSb3cQFRIKCgZHZXRSb3cQFhIOCgpVcGRhdGVDZWxsEB4='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SGgoWQ3JlYXRlRWRpdEZpZWxkQ29udGV4dBAOEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 84a526c164..e16c761cb2 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,14 +1,7 @@ use crate::manager::GridManager; use crate::services::field::type_option_data_from_str; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{ - CellMetaChangeset, CreateEditFieldContextParams, CreateFieldPayload, CreateRowPayload, EditFieldContext, Field, - FieldChangeset, Grid, GridId, QueryFieldPayload, QueryGridBlocksPayload, QueryRowPayload, RepeatedField, - RepeatedGridBlock, Row, -}; -use flowy_grid_data_model::parser::{ - CreateFieldParams, CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams, -}; +use flowy_grid_data_model::entities::*; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; @@ -53,10 +46,10 @@ pub(crate) async fn get_fields_handler( #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn update_field_handler( - data: Data, + data: Data, manager: AppData>, ) -> Result<(), FlowyError> { - let changeset: FieldChangeset = data.into_inner(); + let changeset: FieldChangesetParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(&changeset.grid_id)?; let _ = editor.update_field(changeset).await?; Ok(()) @@ -73,6 +66,17 @@ pub(crate) async fn create_field_handler( Ok(()) } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn delete_field_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let field_order: FieldOrder = data.into_inner(); + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.delete_field(&field_order.field_id).await?; + Ok(()) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn create_edit_field_context_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 054e1f2328..9819f2142e 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -13,6 +13,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) + .event(GridEvent::DeleteField, create_field_handler) .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) @@ -39,8 +40,11 @@ pub enum GridEvent { #[event(input = "CreateFieldPayload")] CreateField = 12, + #[event(input = "FieldOrder")] + DeleteField = 13, + #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")] - CreateEditFieldContext = 13, + CreateEditFieldContext = 14, #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 21, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index fb0e652790..dfa0f30b74 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -30,7 +30,8 @@ pub enum GridEvent { GetFields = 10, UpdateField = 11, CreateField = 12, - CreateEditFieldContext = 13, + DeleteField = 13, + CreateEditFieldContext = 14, CreateRow = 21, GetRow = 22, UpdateCell = 30, @@ -48,7 +49,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { 10 => ::std::option::Option::Some(GridEvent::GetFields), 11 => ::std::option::Option::Some(GridEvent::UpdateField), 12 => ::std::option::Option::Some(GridEvent::CreateField), - 13 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), + 13 => ::std::option::Option::Some(GridEvent::DeleteField), + 14 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), 21 => ::std::option::Option::Some(GridEvent::CreateRow), 22 => ::std::option::Option::Some(GridEvent::GetRow), 30 => ::std::option::Option::Some(GridEvent::UpdateCell), @@ -63,6 +65,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::GetFields, GridEvent::UpdateField, GridEvent::CreateField, + GridEvent::DeleteField, GridEvent::CreateEditFieldContext, GridEvent::CreateRow, GridEvent::GetRow, @@ -95,11 +98,12 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xa7\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xb8\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ - \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x1a\n\x16Cr\ - eateEditFieldContext\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\ - \x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ + \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ + leteField\x10\r\x12\x1a\n\x16CreateEditFieldContext\x10\x0e\x12\r\n\tCre\ + ateRow\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\ + \x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index f6a07a0119..36e5b81d12 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -6,7 +6,8 @@ enum GridEvent { GetFields = 10; UpdateField = 11; CreateField = 12; - CreateEditFieldContext = 13; + DeleteField = 13; + CreateEditFieldContext = 14; CreateRow = 21; GetRow = 22; UpdateCell = 30; 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 6a27fdbb72..022dc3bbfa 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -4,9 +4,8 @@ use crate::services::block_meta_editor::GridBlockMetaEditorManager; use crate::services::field::{type_option_json_str_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; -use flowy_error::{FlowyError, FlowyResult}; +use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; -use flowy_grid_data_model::parser::CreateFieldParams; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridChangeset, GridMetaPad}; use flowy_sync::entities::revision::Revision; @@ -87,8 +86,20 @@ impl ClientGridEditor { self.pad.read().await.contain_field(field_id) } - pub async fn update_field(&self, change: FieldChangeset) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.update_field(change)?)).await?; + pub async fn update_field(&self, mut params: FieldChangesetParams) -> FlowyResult<()> { + if let Some(type_option_data) = params.type_option_data { + match self.pad.read().await.get_field(¶ms.field_id) { + None => return Err(ErrorCode::FieldDoesNotExist.into()), + Some(field_meta) => { + // The type_option_data is serialized by protobuf. But the type_option_data should be + // serialized by utf-8 encoding. So we must transform the data here. + let type_option_json = type_option_json_str_from_bytes(type_option_data, &field_meta.field_type); + params.type_option_data = Some(type_option_json.as_bytes().to_vec()); + } + } + } + + let _ = self.modify(|grid| Ok(grid.update_field(params)?)).await?; let _ = self.notify_did_update_fields().await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 3f18e5a9c0..31ee76712e 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -64,7 +64,7 @@ async fn grid_update_field_with_empty_change() { frozen: None, visibility: None, width: None, - type_options: None, + type_option_data: None, }; let scripts = vec![ @@ -95,7 +95,7 @@ async fn grid_update_field() { frozen: Some(true), visibility: None, width: Some(1000), - type_options: Some(single_select_type_options.clone().into()), + type_option_data: Some(single_select_type_options.clone().into()), }; cloned_field.frozen = true; diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index d3e5f2e909..7c813bd1e0 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -97,8 +97,11 @@ pub enum ErrorCode { RowIdIsEmpty = 430, #[display(fmt = "Field id is empty")] FieldIdIsEmpty = 440, - #[display(fmt = "Field's type option should not be empty")] - TypeOptionIsEmpty = 441, + #[display(fmt = "Field doesn't exist")] + FieldDoesNotExist = 441, + + #[display(fmt = "Field's type option data should not be empty")] + TypeOptionDataIsEmpty = 450, #[display(fmt = "Invalid data")] InvalidData = 500, diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs index ffe8d5e0bc..8e6e1b9621 100644 --- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -61,7 +61,8 @@ pub enum ErrorCode { BlockIdIsEmpty = 420, RowIdIsEmpty = 430, FieldIdIsEmpty = 440, - TypeOptionIsEmpty = 441, + FieldDoesNotExist = 441, + TypeOptionDataIsEmpty = 450, InvalidData = 500, } @@ -108,7 +109,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode { 420 => ::std::option::Option::Some(ErrorCode::BlockIdIsEmpty), 430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty), 440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty), - 441 => ::std::option::Option::Some(ErrorCode::TypeOptionIsEmpty), + 441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist), + 450 => ::std::option::Option::Some(ErrorCode::TypeOptionDataIsEmpty), 500 => ::std::option::Option::Some(ErrorCode::InvalidData), _ => ::std::option::Option::None } @@ -152,7 +154,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode { ErrorCode::BlockIdIsEmpty, ErrorCode::RowIdIsEmpty, ErrorCode::FieldIdIsEmpty, - ErrorCode::TypeOptionIsEmpty, + ErrorCode::FieldDoesNotExist, + ErrorCode::TypeOptionDataIsEmpty, ErrorCode::InvalidData, ]; values @@ -182,7 +185,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ncode.proto*\xe4\x06\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\ncode.proto*\x80\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\ \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\ @@ -202,8 +205,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\ erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\ ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\ \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\ - \x12\x16\n\x11TypeOptionIsEmpty\x10\xb9\x03\x12\x10\n\x0bInvalidData\x10\ - \xf4\x03b\x06proto3\ + \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1a\n\x15TypeOptionDataI\ + sEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto index 1d3d6ed94c..e01c42aa8b 100644 --- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto +++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto @@ -37,6 +37,7 @@ enum ErrorCode { BlockIdIsEmpty = 420; RowIdIsEmpty = 430; FieldIdIsEmpty = 440; - TypeOptionIsEmpty = 441; + FieldDoesNotExist = 441; + TypeOptionDataIsEmpty = 450; InvalidData = 500; } 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 a52d507c87..22d03a5993 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -1,5 +1,7 @@ use crate::entities::{FieldMeta, FieldType, RowMeta}; +use crate::parser::NotEmptyUuid; use flowy_derive::ProtoBuf; +use flowy_error_code::ErrorCode; use std::collections::HashMap; use std::sync::Arc; @@ -311,6 +313,24 @@ pub struct CreateRowPayload { pub start_row_id: Option, } +#[derive(Default)] +pub struct CreateRowParams { + pub grid_id: String, + pub start_row_id: Option, +} + +impl TryInto for CreateRowPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(CreateRowParams { + grid_id: grid_id.0, + start_row_id: self.start_row_id, + }) + } +} + #[derive(ProtoBuf, Default)] pub struct CreateFieldPayload { #[pb(index = 1)] @@ -326,6 +346,35 @@ pub struct CreateFieldPayload { pub start_field_id: Option, } +#[derive(Default, Clone)] +pub struct CreateFieldParams { + pub grid_id: String, + pub field: Field, + pub type_option_data: Vec, + pub start_field_id: Option, +} + +impl TryInto for CreateFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let _ = NotEmptyUuid::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + + let start_field_id = match self.start_field_id { + None => None, + Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), + }; + + Ok(CreateFieldParams { + grid_id: grid_id.0, + field: self.field, + type_option_data: self.type_option_data, + start_field_id, + }) + } +} + #[derive(ProtoBuf, Default)] pub struct QueryFieldPayload { #[pb(index = 1)] @@ -335,6 +384,24 @@ pub struct QueryFieldPayload { pub field_orders: RepeatedFieldOrder, } +#[derive(Default)] +pub struct QueryFieldParams { + pub grid_id: String, + pub field_orders: RepeatedFieldOrder, +} + +impl TryInto for QueryFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(QueryFieldParams { + grid_id: grid_id.0, + field_orders: self.field_orders, + }) + } +} + #[derive(ProtoBuf, Default)] pub struct QueryGridBlocksPayload { #[pb(index = 1)] @@ -344,6 +411,24 @@ pub struct QueryGridBlocksPayload { pub block_orders: Vec, } +#[derive(Default)] +pub struct QueryGridBlocksParams { + pub grid_id: String, + pub block_orders: Vec, +} + +impl TryInto for QueryGridBlocksPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + Ok(QueryGridBlocksParams { + grid_id: grid_id.0, + block_orders: self.block_orders, + }) + } +} + #[derive(ProtoBuf, Default)] pub struct QueryRowPayload { #[pb(index = 1)] @@ -355,3 +440,26 @@ pub struct QueryRowPayload { #[pb(index = 3)] pub row_id: String, } + +#[derive(Default)] +pub struct QueryRowParams { + pub grid_id: String, + pub block_id: String, + pub row_id: String, +} + +impl TryInto for QueryRowPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + + Ok(QueryRowParams { + grid_id: grid_id.0, + block_id: block_id.0, + row_id: row_id.0, + }) + } +} diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 24258c2d0c..90074cadff 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -1,4 +1,6 @@ +use crate::parser::NotEmptyUuid; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use flowy_error_code::ErrorCode; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; @@ -117,7 +119,7 @@ impl FieldMeta { } #[derive(Debug, Clone, Default, ProtoBuf)] -pub struct FieldChangeset { +pub struct FieldChangesetPayload { #[pb(index = 1)] pub field_id: String, @@ -143,7 +145,47 @@ pub struct FieldChangeset { pub width: Option, #[pb(index = 9, one_of)] - pub type_options: Option, + pub type_option_data: Option>, +} + +#[derive(Debug, Clone, Default)] +pub struct FieldChangesetParams { + pub field_id: String, + pub grid_id: String, + pub name: Option, + pub desc: Option, + pub field_type: Option, + pub frozen: Option, + pub visibility: Option, + pub width: Option, + pub type_option_data: Option>, +} + +impl TryInto for FieldChangesetPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + + if let Some(type_option_data) = self.type_option_data.as_ref() { + if type_option_data.is_empty() { + return Err(ErrorCode::TypeOptionDataIsEmpty); + } + } + + Ok(FieldChangesetParams { + field_id: field_id.0, + grid_id: grid_id.0, + name: self.name, + desc: self.desc, + field_type: self.field_type, + frozen: self.frozen, + visibility: self.visibility, + width: self.width, + type_option_data: self.type_option_data, + }) + } } #[derive( diff --git a/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs b/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs deleted file mode 100644 index 83f0395f53..0000000000 --- a/shared-lib/flowy-grid-data-model/src/parser/grid_params.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::entities::{ - CreateFieldPayload, CreateRowPayload, Field, GridBlockOrder, QueryFieldPayload, QueryGridBlocksPayload, - QueryRowPayload, RepeatedFieldOrder, -}; -use crate::parser::NotEmptyUuid; -use flowy_error_code::ErrorCode; - -#[derive(Default)] -pub struct CreateRowParams { - pub grid_id: String, - pub start_row_id: Option, -} - -impl TryInto for CreateRowPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(CreateRowParams { - grid_id: grid_id.0, - start_row_id: self.start_row_id, - }) - } -} - -#[derive(Default)] -pub struct QueryFieldParams { - pub grid_id: String, - pub field_orders: RepeatedFieldOrder, -} - -impl TryInto for QueryFieldPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(QueryFieldParams { - grid_id: grid_id.0, - field_orders: self.field_orders, - }) - } -} - -#[derive(Default)] -pub struct QueryGridBlocksParams { - pub grid_id: String, - pub block_orders: Vec, -} - -impl TryInto for QueryGridBlocksPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - Ok(QueryGridBlocksParams { - grid_id: grid_id.0, - block_orders: self.block_orders, - }) - } -} - -#[derive(Default)] -pub struct QueryRowParams { - pub grid_id: String, - pub block_id: String, - pub row_id: String, -} - -impl TryInto for QueryRowPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?; - let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - - Ok(QueryRowParams { - grid_id: grid_id.0, - block_id: block_id.0, - row_id: row_id.0, - }) - } -} - -#[derive(Default, Clone)] -pub struct CreateFieldParams { - pub grid_id: String, - pub field: Field, - pub type_option_data: Vec, - pub start_field_id: Option, -} - -impl TryInto for CreateFieldPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let _ = NotEmptyUuid::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?; - - let start_field_id = match self.start_field_id { - None => None, - Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), - }; - - Ok(CreateFieldParams { - grid_id: grid_id.0, - field: self.field, - type_option_data: self.type_option_data, - start_field_id, - }) - } -} diff --git a/shared-lib/flowy-grid-data-model/src/parser/mod.rs b/shared-lib/flowy-grid-data-model/src/parser/mod.rs index 710464f814..7cb72eb859 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/mod.rs @@ -1,5 +1,3 @@ -mod grid_params; mod id_parser; -pub use grid_params::*; pub use id_parser::*; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index eaea731897..f22a7c00a2 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -1139,66 +1139,66 @@ impl ::protobuf::reflect::ProtobufValue for FieldMeta { } #[derive(PartialEq,Clone,Default)] -pub struct FieldChangeset { +pub struct FieldChangesetPayload { // message fields pub field_id: ::std::string::String, pub grid_id: ::std::string::String, // message oneof groups - pub one_of_name: ::std::option::Option, - pub one_of_desc: ::std::option::Option, - pub one_of_field_type: ::std::option::Option, - pub one_of_frozen: ::std::option::Option, - pub one_of_visibility: ::std::option::Option, - pub one_of_width: ::std::option::Option, - pub one_of_type_options: ::std::option::Option, + pub one_of_name: ::std::option::Option, + pub one_of_desc: ::std::option::Option, + pub one_of_field_type: ::std::option::Option, + pub one_of_frozen: ::std::option::Option, + pub one_of_visibility: ::std::option::Option, + pub one_of_width: ::std::option::Option, + pub one_of_type_option_data: ::std::option::Option, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a FieldChangeset { - fn default() -> &'a FieldChangeset { - ::default_instance() +impl<'a> ::std::default::Default for &'a FieldChangesetPayload { + fn default() -> &'a FieldChangesetPayload { + ::default_instance() } } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_name { +pub enum FieldChangesetPayload_oneof_one_of_name { name(::std::string::String), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_desc { +pub enum FieldChangesetPayload_oneof_one_of_desc { desc(::std::string::String), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_field_type { +pub enum FieldChangesetPayload_oneof_one_of_field_type { field_type(FieldType), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_frozen { +pub enum FieldChangesetPayload_oneof_one_of_frozen { frozen(bool), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_visibility { +pub enum FieldChangesetPayload_oneof_one_of_visibility { visibility(bool), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_width { +pub enum FieldChangesetPayload_oneof_one_of_width { width(i32), } #[derive(Clone,PartialEq,Debug)] -pub enum FieldChangeset_oneof_one_of_type_options { - type_options(::std::string::String), +pub enum FieldChangesetPayload_oneof_one_of_type_option_data { + type_option_data(::std::vec::Vec), } -impl FieldChangeset { - pub fn new() -> FieldChangeset { +impl FieldChangesetPayload { + pub fn new() -> FieldChangesetPayload { ::std::default::Default::default() } @@ -1259,7 +1259,7 @@ impl FieldChangeset { pub fn get_name(&self) -> &str { match self.one_of_name { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(ref v)) => v, _ => "", } } @@ -1269,24 +1269,24 @@ impl FieldChangeset { pub fn has_name(&self) -> bool { match self.one_of_name { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_name(&mut self, v: ::std::string::String) { - self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v)) + self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(v)) } // Mutable pointer to the field. pub fn mut_name(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(_)) = self.one_of_name { + if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(_)) = self.one_of_name { } else { - self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(::std::string::String::new())); + self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(::std::string::String::new())); } match self.one_of_name { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref mut v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(ref mut v)) => v, _ => panic!(), } } @@ -1295,7 +1295,7 @@ impl FieldChangeset { pub fn take_name(&mut self) -> ::std::string::String { if self.has_name() { match self.one_of_name.take() { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(v)) => v, _ => panic!(), } } else { @@ -1308,7 +1308,7 @@ impl FieldChangeset { pub fn get_desc(&self) -> &str { match self.one_of_desc { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(ref v)) => v, _ => "", } } @@ -1318,24 +1318,24 @@ impl FieldChangeset { pub fn has_desc(&self) -> bool { match self.one_of_desc { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_desc(&mut self, v: ::std::string::String) { - self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v)) + self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(v)) } // Mutable pointer to the field. pub fn mut_desc(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(_)) = self.one_of_desc { + if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(_)) = self.one_of_desc { } else { - self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(::std::string::String::new())); + self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(::std::string::String::new())); } match self.one_of_desc { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref mut v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(ref mut v)) => v, _ => panic!(), } } @@ -1344,7 +1344,7 @@ impl FieldChangeset { pub fn take_desc(&mut self) -> ::std::string::String { if self.has_desc() { match self.one_of_desc.take() { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(v)) => v, _ => panic!(), } } else { @@ -1357,7 +1357,7 @@ impl FieldChangeset { pub fn get_field_type(&self) -> FieldType { match self.one_of_field_type { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(v)) => v, _ => FieldType::RichText, } } @@ -1367,14 +1367,14 @@ impl FieldChangeset { pub fn has_field_type(&self) -> bool { match self.one_of_field_type { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_field_type(&mut self, v: FieldType) { - self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v)) + self.one_of_field_type = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(v)) } // bool frozen = 6; @@ -1382,7 +1382,7 @@ impl FieldChangeset { pub fn get_frozen(&self) -> bool { match self.one_of_frozen { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(v)) => v, _ => false, } } @@ -1392,14 +1392,14 @@ impl FieldChangeset { pub fn has_frozen(&self) -> bool { match self.one_of_frozen { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_frozen(&mut self, v: bool) { - self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v)) + self.one_of_frozen = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(v)) } // bool visibility = 7; @@ -1407,7 +1407,7 @@ impl FieldChangeset { pub fn get_visibility(&self) -> bool { match self.one_of_visibility { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(v)) => v, _ => false, } } @@ -1417,14 +1417,14 @@ impl FieldChangeset { pub fn has_visibility(&self) -> bool { match self.one_of_visibility { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_visibility(&mut self, v: bool) { - self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v)) + self.one_of_visibility = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(v)) } // int32 width = 8; @@ -1432,7 +1432,7 @@ impl FieldChangeset { pub fn get_width(&self) -> i32 { match self.one_of_width { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v)) => v, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(v)) => v, _ => 0, } } @@ -1442,67 +1442,67 @@ impl FieldChangeset { pub fn has_width(&self) -> bool { match self.one_of_width { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(..)) => true, + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_width(&mut self, v: i32) { - self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v)) + self.one_of_width = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(v)) } - // string type_options = 9; + // bytes type_option_data = 9; - pub fn get_type_options(&self) -> &str { - match self.one_of_type_options { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref v)) => v, - _ => "", + pub fn get_type_option_data(&self) -> &[u8] { + match self.one_of_type_option_data { + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v)) => v, + _ => &[], } } - pub fn clear_type_options(&mut self) { - self.one_of_type_options = ::std::option::Option::None; + pub fn clear_type_option_data(&mut self) { + self.one_of_type_option_data = ::std::option::Option::None; } - pub fn has_type_options(&self) -> bool { - match self.one_of_type_options { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(..)) => true, + pub fn has_type_option_data(&self) -> bool { + match self.one_of_type_option_data { + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(..)) => true, _ => false, } } // Param is passed by value, moved - pub fn set_type_options(&mut self, v: ::std::string::String) { - self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v)) + pub fn set_type_option_data(&mut self, v: ::std::vec::Vec) { + self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(v)) } // Mutable pointer to the field. - pub fn mut_type_options(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(_)) = self.one_of_type_options { + pub fn mut_type_option_data(&mut self) -> &mut ::std::vec::Vec { + if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(_)) = self.one_of_type_option_data { } else { - self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(::std::string::String::new())); + self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(::std::vec::Vec::new())); } - match self.one_of_type_options { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref mut v)) => v, + match self.one_of_type_option_data { + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref mut v)) => v, _ => panic!(), } } // Take field - pub fn take_type_options(&mut self) -> ::std::string::String { - if self.has_type_options() { - match self.one_of_type_options.take() { - ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v)) => v, + pub fn take_type_option_data(&mut self) -> ::std::vec::Vec { + if self.has_type_option_data() { + match self.one_of_type_option_data.take() { + ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(v)) => v, _ => panic!(), } } else { - ::std::string::String::new() + ::std::vec::Vec::new() } } } -impl ::protobuf::Message for FieldChangeset { +impl ::protobuf::Message for FieldChangesetPayload { fn is_initialized(&self) -> bool { true } @@ -1521,43 +1521,43 @@ impl ::protobuf::Message for FieldChangeset { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(is.read_string()?)); + self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(is.read_string()?)); }, 4 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(is.read_string()?)); + self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(is.read_string()?)); }, 5 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(is.read_enum()?)); + self.one_of_field_type = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(is.read_enum()?)); }, 6 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(is.read_bool()?)); + self.one_of_frozen = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(is.read_bool()?)); }, 7 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(is.read_bool()?)); + self.one_of_visibility = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(is.read_bool()?)); }, 8 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(is.read_int32()?)); + self.one_of_width = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(is.read_int32()?)); }, 9 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(is.read_string()?)); + self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(is.read_bytes()?)); }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -1579,50 +1579,50 @@ impl ::protobuf::Message for FieldChangeset { } if let ::std::option::Option::Some(ref v) = self.one_of_name { match v { - &FieldChangeset_oneof_one_of_name::name(ref v) => { + &FieldChangesetPayload_oneof_one_of_name::name(ref v) => { my_size += ::protobuf::rt::string_size(3, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_desc { match v { - &FieldChangeset_oneof_one_of_desc::desc(ref v) => { + &FieldChangesetPayload_oneof_one_of_desc::desc(ref v) => { my_size += ::protobuf::rt::string_size(4, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_field_type { match v { - &FieldChangeset_oneof_one_of_field_type::field_type(v) => { + &FieldChangesetPayload_oneof_one_of_field_type::field_type(v) => { my_size += ::protobuf::rt::enum_size(5, v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_frozen { match v { - &FieldChangeset_oneof_one_of_frozen::frozen(v) => { + &FieldChangesetPayload_oneof_one_of_frozen::frozen(v) => { my_size += 2; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_visibility { match v { - &FieldChangeset_oneof_one_of_visibility::visibility(v) => { + &FieldChangesetPayload_oneof_one_of_visibility::visibility(v) => { my_size += 2; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_width { match v { - &FieldChangeset_oneof_one_of_width::width(v) => { + &FieldChangesetPayload_oneof_one_of_width::width(v) => { my_size += ::protobuf::rt::value_size(8, v, ::protobuf::wire_format::WireTypeVarint); }, }; } - if let ::std::option::Option::Some(ref v) = self.one_of_type_options { + if let ::std::option::Option::Some(ref v) = self.one_of_type_option_data { match v { - &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => { - my_size += ::protobuf::rt::string_size(9, &v); + &FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v) => { + my_size += ::protobuf::rt::bytes_size(9, &v); }, }; } @@ -1640,50 +1640,50 @@ impl ::protobuf::Message for FieldChangeset { } if let ::std::option::Option::Some(ref v) = self.one_of_name { match v { - &FieldChangeset_oneof_one_of_name::name(ref v) => { + &FieldChangesetPayload_oneof_one_of_name::name(ref v) => { os.write_string(3, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_desc { match v { - &FieldChangeset_oneof_one_of_desc::desc(ref v) => { + &FieldChangesetPayload_oneof_one_of_desc::desc(ref v) => { os.write_string(4, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_field_type { match v { - &FieldChangeset_oneof_one_of_field_type::field_type(v) => { + &FieldChangesetPayload_oneof_one_of_field_type::field_type(v) => { os.write_enum(5, ::protobuf::ProtobufEnum::value(&v))?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_frozen { match v { - &FieldChangeset_oneof_one_of_frozen::frozen(v) => { + &FieldChangesetPayload_oneof_one_of_frozen::frozen(v) => { os.write_bool(6, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_visibility { match v { - &FieldChangeset_oneof_one_of_visibility::visibility(v) => { + &FieldChangesetPayload_oneof_one_of_visibility::visibility(v) => { os.write_bool(7, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_width { match v { - &FieldChangeset_oneof_one_of_width::width(v) => { + &FieldChangesetPayload_oneof_one_of_width::width(v) => { os.write_int32(8, v)?; }, }; } - if let ::std::option::Option::Some(ref v) = self.one_of_type_options { + if let ::std::option::Option::Some(ref v) = self.one_of_type_option_data { match v { - &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => { - os.write_string(9, v)?; + &FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v) => { + os.write_bytes(9, v)?; }, }; } @@ -1717,8 +1717,8 @@ impl ::protobuf::Message for FieldChangeset { Self::descriptor_static() } - fn new() -> FieldChangeset { - FieldChangeset::new() + fn new() -> FieldChangesetPayload { + FieldChangesetPayload::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -1727,64 +1727,64 @@ impl ::protobuf::Message for FieldChangeset { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", - |m: &FieldChangeset| { &m.field_id }, - |m: &mut FieldChangeset| { &mut m.field_id }, + |m: &FieldChangesetPayload| { &m.field_id }, + |m: &mut FieldChangesetPayload| { &mut m.field_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "grid_id", - |m: &FieldChangeset| { &m.grid_id }, - |m: &mut FieldChangeset| { &mut m.grid_id }, + |m: &FieldChangesetPayload| { &m.grid_id }, + |m: &mut FieldChangesetPayload| { &mut m.grid_id }, )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "name", - FieldChangeset::has_name, - FieldChangeset::get_name, + FieldChangesetPayload::has_name, + FieldChangesetPayload::get_name, )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "desc", - FieldChangeset::has_desc, - FieldChangeset::get_desc, + FieldChangesetPayload::has_desc, + FieldChangesetPayload::get_desc, )); fields.push(::protobuf::reflect::accessor::make_singular_enum_accessor::<_, FieldType>( "field_type", - FieldChangeset::has_field_type, - FieldChangeset::get_field_type, + FieldChangesetPayload::has_field_type, + FieldChangesetPayload::get_field_type, )); fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>( "frozen", - FieldChangeset::has_frozen, - FieldChangeset::get_frozen, + FieldChangesetPayload::has_frozen, + FieldChangesetPayload::get_frozen, )); fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>( "visibility", - FieldChangeset::has_visibility, - FieldChangeset::get_visibility, + FieldChangesetPayload::has_visibility, + FieldChangesetPayload::get_visibility, )); fields.push(::protobuf::reflect::accessor::make_singular_i32_accessor::<_>( "width", - FieldChangeset::has_width, - FieldChangeset::get_width, + FieldChangesetPayload::has_width, + FieldChangesetPayload::get_width, )); - fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( - "type_options", - FieldChangeset::has_type_options, - FieldChangeset::get_type_options, + fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor::<_>( + "type_option_data", + FieldChangesetPayload::has_type_option_data, + FieldChangesetPayload::get_type_option_data, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "FieldChangeset", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FieldChangesetPayload", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static FieldChangeset { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(FieldChangeset::new) + fn default_instance() -> &'static FieldChangesetPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FieldChangesetPayload::new) } } -impl ::protobuf::Clear for FieldChangeset { +impl ::protobuf::Clear for FieldChangesetPayload { fn clear(&mut self) { self.field_id.clear(); self.grid_id.clear(); @@ -1794,18 +1794,18 @@ impl ::protobuf::Clear for FieldChangeset { self.one_of_frozen = ::std::option::Option::None; self.one_of_visibility = ::std::option::Option::None; self.one_of_width = ::std::option::Option::None; - self.one_of_type_options = ::std::option::Option::None; + self.one_of_type_option_data = ::std::option::Option::None; self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for FieldChangeset { +impl ::std::fmt::Debug for FieldChangesetPayload { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for FieldChangeset { +impl ::protobuf::reflect::ProtobufValue for FieldChangesetPayload { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -3514,43 +3514,44 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ idth\x12(\n\x10type_option_json\x18\x08\x20\x01(\tR\x0etypeOptionJson\"\ - \x96\x03\n\x0eFieldChangeset\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\ - \x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\ - \x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\ - \x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTy\ - peH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06fr\ - ozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\ - \x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12#\n\x0ctype_optio\ - ns\x18\t\x20\x01(\tH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\r\n\x0bone\ - _of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one\ - _of_visibilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type_options\"8\n\ - \x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\ - \x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\ - \n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01\ - (\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.Row\ - Meta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\ - \x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibi\ - lity\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\ - \x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\ - \x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\ - \x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06he\ - ight\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\ - \x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByField\ - IdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ + \xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\ + \x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\ + \x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\ + \x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n\ + .FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\ + \x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibi\ + lity\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\x10ty\ + pe_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\r\n\x0bone_of\ + _nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_fro\ + zenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x19\n\x17one_of_\ + type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\t\ + R\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\ + \n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08blo\ + ck_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\ + \x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\ + \x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\ + \x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ \x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.C\ - ellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visib\ - ility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fiel\ - dId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\x11CellMet\ - aChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\ - \x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\ - \x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\x04data\ - B\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bfield_met\ - as\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bblock_metas\ - \x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fblock_me\ - ta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\rblockMetaData*d\n\ - \tFieldType\x12\x0c\n\x08RichText\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\ + ellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\ + \x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\ + \x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\ + \nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaCh\ + angeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\ + \x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\ + \x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\ + \n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\ + \x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\ + \x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ + \x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\ + \x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\ + \x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridCont\ + ext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\ + \x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMe\ + tas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSer\ + deR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\ + \x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSele\ + ct\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\ + \x05b\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/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 44ed367956..2c5bd41f86 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -24,7 +24,7 @@ message FieldMeta { int32 width = 7; string type_option_json = 8; } -message FieldChangeset { +message FieldChangesetPayload { string field_id = 1; string grid_id = 2; oneof one_of_name { string name = 3; }; @@ -33,7 +33,7 @@ message FieldChangeset { oneof one_of_frozen { bool frozen = 6; }; oneof one_of_visibility { bool visibility = 7; }; oneof one_of_width { int32 width = 8; }; - oneof one_of_type_options { string type_options = 9; }; + oneof one_of_type_option_data { bytes type_option_data = 9; }; } message AnyData { string type_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 9375f80ed0..e1712d2584 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -3,12 +3,13 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; use flowy_grid_data_model::entities::{ - FieldChangeset, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, + FieldChangesetParams, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, }; use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::collections::HashMap; +use std::string::FromUtf8Error; use std::sync::Arc; pub type GridMetaDelta = PlainTextDelta; @@ -109,7 +110,7 @@ impl GridMetaPad { } } - pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult> { + pub fn update_field(&mut self, changeset: FieldChangesetParams) -> CollaborateResult> { let field_id = changeset.field_id.clone(); self.modify_field(&field_id, |field| { let mut is_changed = None; @@ -143,9 +144,16 @@ impl GridMetaPad { is_changed = Some(()) } - if let Some(type_options) = changeset.type_options { - field.type_option_json = type_options; - is_changed = Some(()) + if let Some(type_option_data) = changeset.type_option_data { + match String::from_utf8(type_option_data) { + Ok(type_option_json) => { + field.type_option_json = type_option_json; + is_changed = Some(()) + } + Err(err) => { + tracing::error!("Deserialize data to type option json failed: {}", err); + } + } } Ok(is_changed) From 8b7eee46bb32dca090548f5f36baa7d4db0bcf4c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 27 Mar 2022 11:14:21 +0800 Subject: [PATCH 13/47] chore: duplicate and hide field --- .../grid/field/create_field_bloc.dart | 1 + .../grid/field/edit_field_bloc.dart | 31 +- .../application/grid/field/field_service.dart | 26 +- .../plugins/grid/src/grid_page.dart | 2 +- .../src/widgets/header/edit_field_pannel.dart | 26 +- .../widgets/header/field_operation_list.dart | 31 +- .../grid/src/widgets/header/header.dart | 123 ----- .../grid/src/widgets/header/header_cell.dart | 36 -- .../lib/style_widget/button.dart | 3 +- .../dart_event/flowy-grid/dart_event.dart | 21 +- .../flowy-grid-data-model/grid.pb.dart | 122 +++++ .../flowy-grid-data-model/grid.pbjson.dart | 22 + .../protobuf/flowy-grid/event_map.pbenum.dart | 4 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 5 +- .../rust-lib/flowy-grid/src/event_handler.rs | 17 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 12 +- .../src/protobuf/model/event_map.rs | 15 +- .../src/protobuf/proto/event_map.proto | 3 +- .../flowy-grid/src/services/grid_editor.rs | 11 +- .../src/entities/grid.rs | 31 ++ .../src/protobuf/model/grid.rs | 489 ++++++++++++++++-- .../src/protobuf/proto/grid.proto | 8 + .../src/client_grid/grid_meta_pad.rs | 83 +-- 23 files changed, 835 insertions(+), 287 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart delete mode 100755 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart index 29f7187c2f..6a5a276214 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart @@ -62,6 +62,7 @@ class CreateFieldBloc extends Bloc { emit(state.copyWith( field: Some(editContext.gridField), typeOptionData: editContext.typeOptionData, + fieldName: editContext.gridField.name, )); }, (err) => Log.error(err), diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart index 11dbe765fc..6b92b0d0d5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -1,3 +1,4 @@ +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -18,9 +19,27 @@ class EditFieldBloc extends Bloc { updateFieldName: (_UpdateFieldName value) { // }, - hideField: (_HideField value) {}, - deleteField: (_DeleteField value) {}, - duplicateField: (_DuplicateField value) {}, + hideField: (_HideField value) async { + final result = await service.updateField(fieldId: value.fieldId, visibility: false); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + deleteField: (_DeleteField value) async { + final result = await service.deleteField(fieldId: value.fieldId); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + duplicateField: (_DuplicateField value) async { + final result = await service.duplicateField(fieldId: value.fieldId); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, saveField: (_SaveField value) {}, ); }, @@ -37,9 +56,9 @@ class EditFieldBloc extends Bloc { class EditFieldEvent with _$EditFieldEvent { const factory EditFieldEvent.initial() = _InitialField; const factory EditFieldEvent.updateFieldName(String name) = _UpdateFieldName; - const factory EditFieldEvent.hideField() = _HideField; - const factory EditFieldEvent.duplicateField() = _DuplicateField; - const factory EditFieldEvent.deleteField() = _DeleteField; + const factory EditFieldEvent.hideField(String fieldId) = _HideField; + const factory EditFieldEvent.duplicateField(String fieldId) = _DuplicateField; + const factory EditFieldEvent.deleteField(String fieldId) = _DeleteField; const factory EditFieldEvent.saveField() = _SaveField; } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 84566da604..6824ce0b1b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -21,7 +21,7 @@ class FieldService { } Future> updateField({ - required Field field, + required String fieldId, String? name, FieldType? fieldType, bool? frozen, @@ -29,7 +29,9 @@ class FieldService { double? width, List? typeOptionData, }) { - var payload = FieldChangesetPayload.create()..gridId = gridId; + var payload = FieldChangesetPayload.create() + ..gridId = gridId + ..fieldId = fieldId; if (name != null) { payload.name = name; @@ -74,6 +76,26 @@ class FieldService { return GridEventCreateField(payload).send(); } + + Future> deleteField({ + required String fieldId, + }) { + final payload = FieldIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId; + + return GridEventDeleteField(payload).send(); + } + + Future> duplicateField({ + required String fieldId, + }) { + final payload = FieldIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId; + + return GridEventDuplicateField(payload).send(); + } } class GridFieldData extends Equatable { 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 5cd23accc6..e1c44c253b 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 @@ -13,7 +13,7 @@ import 'layout/layout.dart'; import 'layout/sizes.dart'; import 'widgets/content/grid_row.dart'; import 'widgets/footer/grid_footer.dart'; -import 'widgets/header/header.dart'; +import 'widgets/header/grid_header.dart'; class GridPage extends StatefulWidget { final View view; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart index 47affb67e8..ce542b6760 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart @@ -2,7 +2,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -38,9 +37,7 @@ class EditFieldPannel extends StatelessWidget { const VSpace(6), const _FieldTypeSwitcher(), const VSpace(6), - FieldOperationList( - onDismiss: () => FlowyOverlay.of(context).remove(identifier()), - ), + _FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())), ], ), ), @@ -52,6 +49,27 @@ class EditFieldPannel extends StatelessWidget { } } +class _FieldOperationList extends StatelessWidget { + final GridFieldData fieldData; + final VoidCallback onDismissed; + const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final actions = FieldAction.values + .map( + (action) => FieldActionItem( + fieldId: fieldData.field.id, + action: action, + onTap: onDismissed, + ), + ) + .toList(); + + return FieldOperationList(actions: actions); + } +} + class _FieldTypeSwitcher extends StatelessWidget { const _FieldTypeSwitcher({Key? key}) : super(key: key); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart index fb639e5f5b..ddf5eb7660 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -9,17 +9,11 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class FieldOperationList extends StatelessWidget { - final VoidCallback onDismiss; - const FieldOperationList({required this.onDismiss, Key? key}) : super(key: key); + final List actions; + const FieldOperationList({required this.actions, Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final children = FieldAction.values - .map((action) => FieldActionItem( - action: action, - onTap: onDismiss, - )) - .toList(); return GridView( // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html shrinkWrap: true, @@ -28,15 +22,22 @@ class FieldOperationList extends StatelessWidget { childAspectRatio: 4.0, mainAxisSpacing: 8, ), - children: children, + children: actions, ); } } class FieldActionItem extends StatelessWidget { + final String fieldId; final VoidCallback onTap; final FieldAction action; - const FieldActionItem({required this.action, required this.onTap, Key? key}) : super(key: key); + + const FieldActionItem({ + required this.fieldId, + required this.action, + required this.onTap, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -45,7 +46,7 @@ class FieldActionItem extends StatelessWidget { text: FlowyText.medium(action.title(), fontSize: 12), hoverColor: theme.hover, onTap: () { - action.run(context); + action.run(context, fieldId); onTap(); }, leftIcon: svg(action.iconName(), color: theme.iconColor), @@ -82,16 +83,16 @@ extension _FieldActionExtension on FieldAction { } } - void run(BuildContext context) { + void run(BuildContext context, String fieldId) { switch (this) { case FieldAction.hide: - context.read().add(const EditFieldEvent.hideField()); + context.read().add(EditFieldEvent.hideField(fieldId)); break; case FieldAction.duplicate: - context.read().add(const EditFieldEvent.duplicateField()); + context.read().add(EditFieldEvent.duplicateField(fieldId)); break; case FieldAction.delete: - context.read().add(const EditFieldEvent.deleteField()); + context.read().add(EditFieldEvent.deleteField(fieldId)); break; } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart deleted file mode 100644 index dbebb311b9..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header.dart +++ /dev/null @@ -1,123 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'create_field_pannel.dart'; -import 'header_cell.dart'; - -class GridHeaderDelegate extends SliverPersistentHeaderDelegate { - final String gridId; - final List fields; - - GridHeaderDelegate({required this.gridId, required this.fields}); - - @override - Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields)); - } - - @override - double get maxExtent => GridSize.headerHeight; - - @override - double get minExtent => GridSize.headerHeight; - - @override - bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { - if (oldDelegate is GridHeaderDelegate) { - return fields != oldDelegate.fields; - } - return false; - } -} - -class GridHeader extends StatelessWidget { - final List fields; - final String gridId; - const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return BlocProvider( - create: (context) { - final bloc = getIt(param1: gridId, param2: fields); - bloc.add(const GridHeaderEvent.initial()); - return bloc; - }, - child: BlocBuilder( - builder: (context, state) { - final cells = state.fields.map( - (field) => HeaderCell( - GridFieldData(gridId: gridId, field: field), - ), - ); - - final row = Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const _HeaderLeading(), - ...cells, - _HeaderTrailing(gridId: gridId), - ], - ); - - return Container(color: theme.surface, child: row); - }, - ), - ); - } -} - -class _HeaderLeading extends StatelessWidget { - const _HeaderLeading({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return SizedBox( - width: GridSize.leadingHeaderPadding, - ); - } -} - -class _HeaderTrailing extends StatelessWidget { - final String gridId; - const _HeaderTrailing({required this.gridId, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - return Container( - width: GridSize.trailHeaderPadding, - decoration: BoxDecoration( - border: Border(top: borderSide, bottom: borderSide), - ), - padding: GridSize.headerContentInsets, - child: CreateFieldButton(gridId: gridId), - ); - } -} - -class CreateFieldButton extends StatelessWidget { - final String gridId; - const CreateFieldButton({required this.gridId, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return FlowyButton( - text: const FlowyText.medium('New column', fontSize: 12), - hoverColor: theme.hover, - onTap: () => CreateFieldPannel(gridId: gridId).show(context, gridId), - leftIcon: svg("home/add"), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart deleted file mode 100755 index 52e7e38d75..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'edit_field_pannel.dart'; - -class HeaderCell extends StatelessWidget { - final GridFieldData fieldData; - const HeaderCell(this.fieldData, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - final button = FlowyButton( - hoverColor: theme.hover, - onTap: () => EditFieldPannel.show(context, fieldData), - rightIcon: svg("editor/details", color: theme.iconColor), - text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), - ); - - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); - - return Container( - width: fieldData.field.width.toDouble(), - decoration: decoration, - padding: GridSize.headerContentInsets, - child: button, - ); - } -} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index 78d65a9941..0bcd05f56e 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -40,10 +40,9 @@ class FlowyButton extends StatelessWidget { children.add(const HSpace(6)); } - children.add(text); + children.add(Expanded(child: text)); if (rightIcon != null) { - children.add(const Spacer()); children.add(SizedBox.fromSize(size: const Size.square(16), child: rightIcon!)); children.add(const HSpace(6)); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 0c3d242c37..7f25329284 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -53,7 +53,7 @@ class GridEventGetFields { } class GridEventUpdateField { - FieldChangeset request; + FieldChangesetPayload request; GridEventUpdateField(this.request); Future> send() { @@ -87,7 +87,7 @@ class GridEventCreateField { } class GridEventDeleteField { - FieldOrder request; + FieldIdentifierPayload request; GridEventDeleteField(this.request); Future> send() { @@ -103,6 +103,23 @@ class GridEventDeleteField { } } +class GridEventDuplicateField { + FieldIdentifierPayload request; + GridEventDuplicateField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.DuplicateField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateEditFieldContext { CreateEditFieldContextParams request; GridEventCreateEditFieldContext(this.request); 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 4ea447d729..bd9afe2243 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 @@ -205,6 +205,128 @@ class Field extends $pb.GeneratedMessage { void clearWidth() => clearField(7); } +class FieldIdentifierPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..hasRequiredFields = false + ; + + FieldIdentifierPayload._() : super(); + factory FieldIdentifierPayload({ + $core.String? fieldId, + $core.String? gridId, + }) { + final _result = create(); + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (gridId != null) { + _result.gridId = gridId; + } + return _result; + } + factory FieldIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FieldIdentifierPayload.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') + FieldIdentifierPayload clone() => FieldIdentifierPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + FieldIdentifierPayload copyWith(void Function(FieldIdentifierPayload) updates) => super.copyWith((message) => updates(message as FieldIdentifierPayload)) as FieldIdentifierPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static FieldIdentifierPayload create() => FieldIdentifierPayload._(); + FieldIdentifierPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static FieldIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FieldIdentifierPayload? _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.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); +} + +class FieldIdentifierParams extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierParams', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..hasRequiredFields = false + ; + + FieldIdentifierParams._() : super(); + factory FieldIdentifierParams({ + $core.String? fieldId, + $core.String? gridId, + }) { + final _result = create(); + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (gridId != null) { + _result.gridId = gridId; + } + return _result; + } + factory FieldIdentifierParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FieldIdentifierParams.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') + FieldIdentifierParams clone() => FieldIdentifierParams()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + FieldIdentifierParams copyWith(void Function(FieldIdentifierParams) updates) => super.copyWith((message) => updates(message as FieldIdentifierParams)) as FieldIdentifierParams; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static FieldIdentifierParams create() => FieldIdentifierParams._(); + FieldIdentifierParams createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static FieldIdentifierParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FieldIdentifierParams? _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.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); +} + 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') 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 a7dc3255c8..0b900d46f9 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 @@ -36,6 +36,28 @@ const Field$json = const { /// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aA=='); +@$core.Deprecated('Use fieldIdentifierPayloadDescriptor instead') +const FieldIdentifierPayload$json = const { + '1': 'FieldIdentifierPayload', + '2': const [ + const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, + ], +}; + +/// Descriptor for `FieldIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List fieldIdentifierPayloadDescriptor = $convert.base64Decode('ChZGaWVsZElkZW50aWZpZXJQYXlsb2FkEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZA=='); +@$core.Deprecated('Use fieldIdentifierParamsDescriptor instead') +const FieldIdentifierParams$json = const { + '1': 'FieldIdentifierParams', + '2': const [ + const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, + ], +}; + +/// Descriptor for `FieldIdentifierParams`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List fieldIdentifierParamsDescriptor = $convert.base64Decode('ChVGaWVsZElkZW50aWZpZXJQYXJhbXMSGQoIZmllbGRfaWQYASABKAlSB2ZpZWxkSWQSFwoHZ3JpZF9pZBgCIAEoCVIGZ3JpZElk'); @$core.Deprecated('Use fieldOrderDescriptor instead') const FieldOrder$json = const { '1': 'FieldOrder', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 755b1c1ed1..46291923e0 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -16,7 +16,8 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); - static const GridEvent CreateEditFieldContext = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); + static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); + static const GridEvent CreateEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); @@ -28,6 +29,7 @@ class GridEvent extends $pb.ProtobufEnum { UpdateField, CreateField, DeleteField, + DuplicateField, CreateEditFieldContext, CreateRow, GetRow, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 9441a03bea..278e0b14c3 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -18,7 +18,8 @@ const GridEvent$json = const { const {'1': 'UpdateField', '2': 11}, const {'1': 'CreateField', '2': 12}, const {'1': 'DeleteField', '2': 13}, - const {'1': 'CreateEditFieldContext', '2': 14}, + const {'1': 'DuplicateField', '2': 15}, + const {'1': 'CreateEditFieldContext', '2': 16}, const {'1': 'CreateRow', '2': 21}, const {'1': 'GetRow', '2': 22}, const {'1': 'UpdateCell', '2': 30}, @@ -26,4 +27,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SGgoWQ3JlYXRlRWRpdEZpZWxkQ29udGV4dBAOEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASDQoJQ3JlYXRlUm93EBUSCgoGR2V0Um93EBYSDgoKVXBkYXRlQ2VsbBAe'); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index e16c761cb2..97b91e5557 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -68,12 +68,23 @@ pub(crate) async fn create_field_handler( #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn delete_field_handler( - data: Data, + data: Data, manager: AppData>, ) -> Result<(), FlowyError> { - let field_order: FieldOrder = data.into_inner(); + let params: FieldIdentifierParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.delete_field(&field_order.field_id).await?; + let _ = editor.delete_field(¶ms.field_id).await?; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn duplicate_field_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let params: FieldIdentifierParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.duplicate_field(¶ms.field_id).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 9819f2142e..efe5ddc094 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -13,7 +13,8 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) - .event(GridEvent::DeleteField, create_field_handler) + .event(GridEvent::DeleteField, delete_field_handler) + .event(GridEvent::DuplicateField, duplicate_field_handler) .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) @@ -34,17 +35,20 @@ pub enum GridEvent { #[event(input = "QueryFieldPayload", output = "RepeatedField")] GetFields = 10, - #[event(input = "FieldChangeset")] + #[event(input = "FieldChangesetPayload")] UpdateField = 11, #[event(input = "CreateFieldPayload")] CreateField = 12, - #[event(input = "FieldOrder")] + #[event(input = "FieldIdentifierPayload")] DeleteField = 13, + #[event(input = "FieldIdentifierPayload")] + DuplicateField = 15, + #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")] - CreateEditFieldContext = 14, + CreateEditFieldContext = 16, #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 21, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index dfa0f30b74..13ee0705cc 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -31,7 +31,8 @@ pub enum GridEvent { UpdateField = 11, CreateField = 12, DeleteField = 13, - CreateEditFieldContext = 14, + DuplicateField = 15, + CreateEditFieldContext = 16, CreateRow = 21, GetRow = 22, UpdateCell = 30, @@ -50,7 +51,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { 11 => ::std::option::Option::Some(GridEvent::UpdateField), 12 => ::std::option::Option::Some(GridEvent::CreateField), 13 => ::std::option::Option::Some(GridEvent::DeleteField), - 14 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), + 15 => ::std::option::Option::Some(GridEvent::DuplicateField), + 16 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), 21 => ::std::option::Option::Some(GridEvent::CreateRow), 22 => ::std::option::Option::Some(GridEvent::GetRow), 30 => ::std::option::Option::Some(GridEvent::UpdateCell), @@ -66,6 +68,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::UpdateField, GridEvent::CreateField, GridEvent::DeleteField, + GridEvent::DuplicateField, GridEvent::CreateEditFieldContext, GridEvent::CreateRow, GridEvent::GetRow, @@ -98,12 +101,12 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xb8\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xcc\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ - leteField\x10\r\x12\x1a\n\x16CreateEditFieldContext\x10\x0e\x12\r\n\tCre\ - ateRow\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\ - \x06proto3\ + leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x1a\n\x16CreateE\ + ditFieldContext\x10\x10\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\ + \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 36e5b81d12..327a1e3aee 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -7,7 +7,8 @@ enum GridEvent { UpdateField = 11; CreateField = 12; DeleteField = 13; - CreateEditFieldContext = 14; + DuplicateField = 15; + CreateEditFieldContext = 16; CreateRow = 21; GetRow = 22; UpdateCell = 30; 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 022dc3bbfa..7ff089ff9b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -110,6 +110,12 @@ impl ClientGridEditor { Ok(()) } + pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> { + let _ = self.modify(|grid| Ok(grid.duplicate_field(field_id)?)).await?; + let _ = self.notify_did_update_fields().await?; + Ok(()) + } + pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?; Ok(()) @@ -254,8 +260,9 @@ impl ClientGridEditor { } pub async fn get_field_metas(&self, field_orders: Option) -> FlowyResult> { - let field_meta = self.pad.read().await.get_field_metas(field_orders)?; - Ok(field_meta) + let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?; + field_metas.retain(|field_meta| field_meta.visibility); + Ok(field_metas) } pub async fn get_block_meta_data_vec( 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 22d03a5993..dfd5dc397f 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -55,6 +55,37 @@ impl std::convert::From for Field { } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct FieldIdentifierPayload { + #[pb(index = 1)] + pub field_id: String, + + #[pb(index = 2)] + pub grid_id: String, +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct FieldIdentifierParams { + #[pb(index = 1)] + pub field_id: String, + + #[pb(index = 2)] + pub grid_id: String, +} + +impl TryInto for FieldIdentifierPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + Ok(FieldIdentifierParams { + grid_id: grid_id.0, + field_id: field_id.0, + }) + } +} + #[derive(Debug, Clone, Default, ProtoBuf)] pub struct FieldOrder { #[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 a6afa46d9a..c18043184f 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 @@ -659,6 +659,408 @@ impl ::protobuf::reflect::ProtobufValue for Field { } } +#[derive(PartialEq,Clone,Default)] +pub struct FieldIdentifierPayload { + // message fields + pub field_id: ::std::string::String, + pub grid_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a FieldIdentifierPayload { + fn default() -> &'a FieldIdentifierPayload { + ::default_instance() + } +} + +impl FieldIdentifierPayload { + pub fn new() -> FieldIdentifierPayload { + ::std::default::Default::default() + } + + // string field_id = 1; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string grid_id = 2; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for FieldIdentifierPayload { + 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.field_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; + }, + _ => { + ::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.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.field_id); + } + if !self.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.grid_id); + } + 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.field_id.is_empty() { + os.write_string(1, &self.field_id)?; + } + if !self.grid_id.is_empty() { + os.write_string(2, &self.grid_id)?; + } + 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() -> FieldIdentifierPayload { + FieldIdentifierPayload::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>( + "field_id", + |m: &FieldIdentifierPayload| { &m.field_id }, + |m: &mut FieldIdentifierPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "grid_id", + |m: &FieldIdentifierPayload| { &m.grid_id }, + |m: &mut FieldIdentifierPayload| { &mut m.grid_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FieldIdentifierPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static FieldIdentifierPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FieldIdentifierPayload::new) + } +} + +impl ::protobuf::Clear for FieldIdentifierPayload { + fn clear(&mut self) { + self.field_id.clear(); + self.grid_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for FieldIdentifierPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for FieldIdentifierPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct FieldIdentifierParams { + // message fields + pub field_id: ::std::string::String, + pub grid_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a FieldIdentifierParams { + fn default() -> &'a FieldIdentifierParams { + ::default_instance() + } +} + +impl FieldIdentifierParams { + pub fn new() -> FieldIdentifierParams { + ::std::default::Default::default() + } + + // string field_id = 1; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string grid_id = 2; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for FieldIdentifierParams { + 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.field_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; + }, + _ => { + ::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.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.field_id); + } + if !self.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.grid_id); + } + 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.field_id.is_empty() { + os.write_string(1, &self.field_id)?; + } + if !self.grid_id.is_empty() { + os.write_string(2, &self.grid_id)?; + } + 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() -> FieldIdentifierParams { + FieldIdentifierParams::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>( + "field_id", + |m: &FieldIdentifierParams| { &m.field_id }, + |m: &mut FieldIdentifierParams| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "grid_id", + |m: &FieldIdentifierParams| { &m.grid_id }, + |m: &mut FieldIdentifierParams| { &mut m.grid_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FieldIdentifierParams", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static FieldIdentifierParams { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FieldIdentifierParams::new) + } +} + +impl ::protobuf::Clear for FieldIdentifierParams { + fn clear(&mut self) { + self.field_id.clear(); + self.grid_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for FieldIdentifierParams { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for FieldIdentifierParams { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct FieldOrder { // message fields @@ -4865,48 +5267,51 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\ \x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\ \x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\ - \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\ - \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFiel\ - dContextParams\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\ - \nfield_type\x18\x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditF\ - ieldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ng\ - rid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_opt\ - ion_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\ - \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\ - edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\ - ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\ - \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\ - t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\ - \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\ - \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\ - \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ - \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ - .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ - \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ - items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ - \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ - \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ - \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ - \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\ - 2\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\ - RowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\ - \x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\ - \x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\ - \x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\ - \x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\ - \x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\ - \x0f.GridBlockOrderR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\ - \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\ - \x20\x01(\tR\x07blockId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\ - b\x06proto3\ + \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"L\n\x16FieldIdentifi\ + erPayload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\ + \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"K\n\x15FieldIdentifierParams\ + \x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\ + id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFieldContextParams\x12\ + \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\nfield_type\x18\ + \x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\x12\ + \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\x18\ + \x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\x18\ + \x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\x05it\ + ems\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\ + \x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\n\x08\ + RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\ + lock_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\x03\x20\ + \x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\ + \tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellB\ + yFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\ + \x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01\ + (\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\ + \x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\ + \x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05items\x18\x01\ + \x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\x19\n\ + \x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\x0e\n\ + \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ + 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ + \x01(\tR\x07fieldId\x12\x18\n\x07content\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(\t\ + R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ + lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ + \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ + idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ + \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ + rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ + \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ + \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ + \x0cstartFieldIdB\x17\n\x15one_of_start_field_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\"e\n\ + \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ + ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ + \x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ + \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ + kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowIdb\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 ec109f580f..3a74e23026 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 @@ -15,6 +15,14 @@ message Field { bool visibility = 6; int32 width = 7; } +message FieldIdentifierPayload { + string field_id = 1; + string grid_id = 2; +} +message FieldIdentifierParams { + string field_id = 1; + string grid_id = 2; +} message FieldOrder { string field_id = 1; } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index e1712d2584..78c0091b57 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -72,42 +72,17 @@ impl GridMetaPad { }) } - pub fn contain_field(&self, field_id: &str) -> bool { - self.grid_meta.fields.iter().any(|field| field.id == field_id) - } - - pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> { - self.grid_meta.fields.iter().find(|field| field.id == field_id) - } - - pub fn get_field_orders(&self) -> Vec { - self.grid_meta.fields.iter().map(FieldOrder::from).collect() - } - - pub fn get_field_metas(&self, field_orders: Option) -> CollaborateResult> { - match field_orders { - None => Ok(self.grid_meta.fields.clone()), - Some(field_orders) => { - let field_by_field_id = self - .grid_meta - .fields - .iter() - .map(|field| (&field.id, field)) - .collect::>(); - - let fields = field_orders - .iter() - .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) { - None => { - tracing::error!("Can't find the field with id: {}", field_order.field_id); - None - } - Some(field) => Some((*field).clone()), - }) - .collect::>(); - Ok(fields) + pub fn duplicate_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) => { + let mut duplicate_field_meta = grid.fields[index].clone(); + duplicate_field_meta.id = uuid(); + duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name); + grid.fields.insert(index + 1, duplicate_field_meta); + Ok(Some(())) } - } + }) } pub fn update_field(&mut self, changeset: FieldChangesetParams) -> CollaborateResult> { @@ -160,6 +135,44 @@ impl GridMetaPad { }) } + pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> { + self.grid_meta.fields.iter().find(|field| field.id == field_id) + } + + pub fn contain_field(&self, field_id: &str) -> bool { + self.grid_meta.fields.iter().any(|field| field.id == field_id) + } + + pub fn get_field_orders(&self) -> Vec { + self.grid_meta.fields.iter().map(FieldOrder::from).collect() + } + + pub fn get_field_metas(&self, field_orders: Option) -> CollaborateResult> { + match field_orders { + None => Ok(self.grid_meta.fields.clone()), + Some(field_orders) => { + let field_by_field_id = self + .grid_meta + .fields + .iter() + .map(|field| (&field.id, field)) + .collect::>(); + + let fields = field_orders + .iter() + .flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) { + None => { + tracing::error!("Can't find the field with id: {}", field_order.field_id); + None + } + Some(field) => Some((*field).clone()), + }) + .collect::>(); + Ok(fields) + } + } + } + pub fn create_block(&mut self, block: GridBlockMeta) -> CollaborateResult> { self.modify_grid(|grid| { if grid.block_metas.iter().any(|b| b.block_id == block.block_id) { From 35e27b579f3cbd07fc1a1e780d9675810acfa64e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 27 Mar 2022 22:38:50 +0800 Subject: [PATCH 14/47] chore: number field --- .../assets/images/grid/field/euro.svg | 3 + .../assets/images/grid/field/numbers.svg | 3 + .../assets/images/grid/field/us_dollar.svg | 3 + .../assets/images/grid/field/yen.svg | 3 + .../app_flowy/assets/translations/en.json | 5 +- .../app_flowy/lib/startup/deps_resolver.dart | 5 +- .../grid/field/edit_field_bloc.dart | 22 ++- .../grid/field/grid_header_bloc.dart | 26 ++- .../grid/field/grid_header_listener.dart | 0 .../grid/{ => field}/grid_listenr.dart | 14 +- .../grid/field/switch_field_type_bloc.dart | 4 + .../grid/field/type_option/number_bloc.dart | 23 ++- .../workspace/application/grid/grid_bloc.dart | 24 +-- .../application/grid/row/row_bloc.dart | 11 +- .../application/grid/row/row_listener.dart | 41 +---- .../plugins/grid/src/grid_page.dart | 2 - .../grid/src/widgets/content/grid_row.dart | 59 ++++--- .../widgets/header/create_field_pannel.dart | 2 +- .../src/widgets/header/edit_field_pannel.dart | 4 +- .../widgets/header/field_operation_list.dart | 10 +- .../widgets/header/field_tyep_switcher.dart | 71 +++----- .../grid/src/widgets/header/grid_header.dart | 123 +++++++++++++ .../src/widgets/header/grid_header_cell.dart | 36 ++++ .../widgets/header/type_option/number.dart | 165 ++++++++++++++++++ 24 files changed, 492 insertions(+), 167 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/field/euro.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/numbers.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/us_dollar.svg create mode 100644 frontend/app_flowy/assets/images/grid/field/yen.svg create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/grid_header_listener.dart rename frontend/app_flowy/lib/workspace/application/grid/{ => field}/grid_listenr.dart (75%) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart create mode 100755 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart diff --git a/frontend/app_flowy/assets/images/grid/field/euro.svg b/frontend/app_flowy/assets/images/grid/field/euro.svg new file mode 100644 index 0000000000..95f511f687 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/euro.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/images/grid/field/numbers.svg b/frontend/app_flowy/assets/images/grid/field/numbers.svg new file mode 100644 index 0000000000..9d8b98d10d --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/numbers.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/images/grid/field/us_dollar.svg b/frontend/app_flowy/assets/images/grid/field/us_dollar.svg new file mode 100644 index 0000000000..a8485cd6a1 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/us_dollar.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/images/grid/field/yen.svg b/frontend/app_flowy/assets/images/grid/field/yen.svg new file mode 100644 index 0000000000..8e9bf47c99 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/field/yen.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 5e5fc661ec..1031265da1 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -152,9 +152,10 @@ "textFieldName": "Text", "checkboxFieldName": "Checkbox", "dateFieldName": "Date", - "numberFieldName": "Number", + "numberFieldName": "Numbers", "singleSelectFieldName": "Select", - "multiSelectFieldName": "Multiselect" + "multiSelectFieldName": "Multiselect", + "numberFormat": " Number format" } } } diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 8293efd652..e277bc6a20 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -18,6 +18,7 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:get_it/get_it.dart'; @@ -221,7 +222,7 @@ void _resolveGridDeps(GetIt getIt) { () => DateTypeOptionBloc(), ); - getIt.registerFactory( - () => NumberTypeOptionBloc(), + getIt.registerFactoryParam( + (typeOption, _) => NumberTypeOptionBloc(typeOption: typeOption), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart index 6b92b0d0d5..525d5232d7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -16,25 +16,29 @@ class EditFieldBloc extends Bloc { (event, emit) async { await event.map( initial: (_InitialField value) {}, - updateFieldName: (_UpdateFieldName value) { - // + updateFieldName: (_UpdateFieldName value) async { + final result = await service.updateField(fieldId: field.id, name: value.name); + result.fold( + (l) => null, + (err) => Log.error(err), + ); }, hideField: (_HideField value) async { - final result = await service.updateField(fieldId: value.fieldId, visibility: false); + final result = await service.updateField(fieldId: field.id, visibility: false); result.fold( (l) => null, (err) => Log.error(err), ); }, deleteField: (_DeleteField value) async { - final result = await service.deleteField(fieldId: value.fieldId); + final result = await service.deleteField(fieldId: field.id); result.fold( (l) => null, (err) => Log.error(err), ); }, duplicateField: (_DuplicateField value) async { - final result = await service.duplicateField(fieldId: value.fieldId); + final result = await service.duplicateField(fieldId: field.id); result.fold( (l) => null, (err) => Log.error(err), @@ -56,9 +60,9 @@ class EditFieldBloc extends Bloc { class EditFieldEvent with _$EditFieldEvent { const factory EditFieldEvent.initial() = _InitialField; const factory EditFieldEvent.updateFieldName(String name) = _UpdateFieldName; - const factory EditFieldEvent.hideField(String fieldId) = _HideField; - const factory EditFieldEvent.duplicateField(String fieldId) = _DuplicateField; - const factory EditFieldEvent.deleteField(String fieldId) = _DeleteField; + const factory EditFieldEvent.hideField() = _HideField; + const factory EditFieldEvent.duplicateField() = _DuplicateField; + const factory EditFieldEvent.deleteField() = _DeleteField; const factory EditFieldEvent.saveField() = _SaveField; } @@ -67,10 +71,12 @@ class EditFieldState with _$EditFieldState { const factory EditFieldState({ required EditFieldContext editContext, required String errorText, + required String fieldName, }) = _EditFieldState; factory EditFieldState.initial(EditFieldContext editContext) => EditFieldState( editContext: editContext, errorText: '', + fieldName: editContext.gridField.name, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart index a5f3a8414a..d249e9b4c1 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -1,4 +1,6 @@ import 'package:app_flowy/workspace/application/grid/data.dart'; +import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -9,24 +11,43 @@ part 'grid_header_bloc.freezed.dart'; class GridHeaderBloc extends Bloc { final FieldService service; + final GridFieldsListener fieldListener; GridHeaderBloc({ required GridHeaderData data, required this.service, - }) : super(GridHeaderState.initial(data.fields)) { + }) : fieldListener = GridFieldsListener(gridId: data.gridId), + super(GridHeaderState.initial(data.fields)) { on( (event, emit) async { await event.map( - initial: (_InitialHeader value) async {}, + initial: (_InitialHeader value) async { + _startListening(); + }, createField: (_CreateField value) {}, insertField: (_InsertField value) {}, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(fields: value.fields)); + }, ); }, ); } + Future _startListening() async { + fieldListener.updateFieldsNotifier.addPublishListener((result) { + result.fold( + (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)), + (err) => Log.error(err), + ); + }); + + fieldListener.start(); + } + @override Future close() async { + await fieldListener.stop(); return super.close(); } } @@ -36,6 +57,7 @@ class GridHeaderEvent with _$GridHeaderEvent { const factory GridHeaderEvent.initial() = _InitialHeader; const factory GridHeaderEvent.createField() = _CreateField; const factory GridHeaderEvent.insertField({required bool onLeft}) = _InsertField; + const factory GridHeaderEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_listener.dart new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart similarity index 75% rename from frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart index 4afaa54601..60ff7dd415 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart @@ -9,14 +9,14 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:app_flowy/core/notification_helper.dart'; -// typedef RowsUpdateNotifierValue = Either, FlowyError>; +typedef UpdateFieldNotifiedValue = Either, FlowyError>; -class GridListener { +class GridFieldsListener { final String gridId; - PublishNotifier, FlowyError>> fieldsUpdateNotifier = PublishNotifier(); + PublishNotifier updateFieldsNotifier = PublishNotifier(); StreamSubscription? _subscription; GridNotificationParser? _parser; - GridListener({required this.gridId}); + GridFieldsListener({required this.gridId}); void start() { _parser = GridNotificationParser( @@ -33,8 +33,8 @@ class GridListener { switch (ty) { case GridNotification.DidUpdateFields: result.fold( - (payload) => fieldsUpdateNotifier.value = left(RepeatedField.fromBuffer(payload).items), - (error) => fieldsUpdateNotifier.value = right(error), + (payload) => updateFieldsNotifier.value = left(RepeatedField.fromBuffer(payload).items), + (error) => updateFieldsNotifier.value = right(error), ); break; default: @@ -45,6 +45,6 @@ class GridListener { Future stop() async { _parser = null; await _subscription?.cancel(); - fieldsUpdateNotifier.dispose(); + updateFieldsNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart index 7f5417a396..a2f7438434 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -29,6 +29,9 @@ class SwitchFieldTypeBloc extends Bloc Log.error(err), ); }, + didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) { + emit(state.copyWith(typeOptionData: value.typeOptionData)); + }, ); }, ); @@ -43,6 +46,7 @@ class SwitchFieldTypeBloc extends Bloc { - NumberTypeOptionBloc() : super(NumberTypeOptionState.initial()) { + NumberTypeOptionBloc({required NumberTypeOption typeOption}) : super(NumberTypeOptionState.initial(typeOption)) { on( (event, emit) async { await event.map( initial: (_InitialField value) async {}, + didSelectFormat: (_DidSelectFormat value) { + state.typeOption.format = value.format; + emit(state); + }, ); }, ); @@ -28,12 +28,17 @@ class NumberTypeOptionBloc extends Bloc NumberTypeOptionState(); + factory NumberTypeOptionState.initial(NumberTypeOption typeOption) => NumberTypeOptionState( + typeOption: typeOption, + ); } 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 b155126a72..00f90e0bfc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:equatable/equatable.dart'; import 'grid_block_service.dart'; -import 'grid_listenr.dart'; +import 'field/grid_listenr.dart'; import 'grid_service.dart'; part 'grid_bloc.freezed.dart'; @@ -16,11 +16,11 @@ part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final View view; final GridService service; - late GridListener _gridListener; + late GridFieldsListener _fieldListener; late GridBlockService _blockService; GridBloc({required this.view, required this.service}) : super(GridState.initial()) { - _gridListener = GridListener(gridId: view.id); + _fieldListener = GridFieldsListener(gridId: view.id); on( (event, emit) async { @@ -34,10 +34,10 @@ class GridBloc extends Bloc { delete: (_Delete value) {}, rename: (_Rename value) {}, updateDesc: (_Desc value) {}, - rowsDidUpdate: (_RowsDidUpdate value) { + didReceiveRowUpdate: (_DidReceiveRowUpdate value) { emit(state.copyWith(rows: value.rows)); }, - fieldsDidUpdate: (_FieldsDidUpdate value) { + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { emit(state.copyWith(fields: value.fields)); }, ); @@ -47,19 +47,19 @@ class GridBloc extends Bloc { @override Future close() async { - await _gridListener.stop(); + await _fieldListener.stop(); await _blockService.stop(); return super.close(); } Future _initGrid(Emitter emit) async { - _gridListener.fieldsUpdateNotifier.addPublishListener((result) { + _fieldListener.updateFieldsNotifier.addPublishListener((result) { result.fold( - (fields) => add(GridEvent.fieldsDidUpdate(fields)), + (fields) => add(GridEvent.didReceiveFieldUpdate(fields)), (err) => Log.error(err), ); }); - _gridListener.start(); + _fieldListener.start(); await _loadGrid(emit); } @@ -72,7 +72,7 @@ class GridBloc extends Bloc { _blockService.blocksUpdateNotifier?.addPublishListener((result) { result.fold( - (blockMap) => add(GridEvent.rowsDidUpdate(_buildRows(blockMap))), + (blockMap) => add(GridEvent.didReceiveRowUpdate(_buildRows(blockMap))), (err) => Log.error('$err'), ); }); @@ -128,8 +128,8 @@ class GridEvent with _$GridEvent { const factory GridEvent.updateDesc(String gridId, String desc) = _Desc; const factory GridEvent.delete(String gridId) = _Delete; const factory GridEvent.createRow() = _CreateRow; - const factory GridEvent.rowsDidUpdate(List rows) = _RowsDidUpdate; - const factory GridEvent.fieldsDidUpdate(List fields) = _FieldsDidUpdate; + const factory GridEvent.didReceiveRowUpdate(List rows) = _DidReceiveRowUpdate; + const factory GridEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 2bb78799f0..ac99eac67b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -1,5 +1,6 @@ import 'dart:collection'; +import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; @@ -17,7 +18,7 @@ typedef CellDataMap = HashMap; class RowBloc extends Bloc { final RowService rowService; final RowListener rowlistener; - final RowFieldListener fieldListener; + final GridFieldsListener fieldListener; RowBloc({required GridRowData rowData, required this.rowlistener}) : rowService = RowService( @@ -25,7 +26,7 @@ class RowBloc extends Bloc { blockId: rowData.blockId, rowId: rowData.rowId, ), - fieldListener = RowFieldListener( + fieldListener = GridFieldsListener( gridId: rowData.gridId, ), super(RowState.initial(rowData)) { @@ -65,8 +66,8 @@ class RowBloc extends Bloc { @override Future close() async { - await rowlistener.close(); - await fieldListener.close(); + await rowlistener.stop(); + await fieldListener.stop(); return super.close(); } @@ -89,7 +90,7 @@ class RowBloc extends Bloc { ); }); - fieldListener.updateFieldNotifier.addPublishListener((result) { + fieldListener.updateFieldsNotifier.addPublishListener((result) { result.fold( (fields) => add(RowEvent.didReceiveFieldUpdate(fields)), (err) => Log.error(err), diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart index c5084f4164..011dbd8636 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart @@ -46,49 +46,10 @@ class RowListener { } } - Future close() async { + Future stop() async { _parser = null; await _subscription?.cancel(); updateCellNotifier.dispose(); updateRowNotifier.dispose(); } } - -class RowFieldListener { - final String gridId; - PublishNotifier updateFieldNotifier = PublishNotifier(); - StreamSubscription? _subscription; - GridNotificationParser? _parser; - - RowFieldListener({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.DidUpdateFields: - result.fold( - (payload) => updateFieldNotifier.value = left(RepeatedField.fromBuffer(payload).items), - (error) => updateFieldNotifier.value = right(error), - ); - break; - default: - break; - } - } - - Future close() async { - _parser = null; - await _subscription?.cancel(); - updateFieldNotifier.dispose(); - } -} 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 e1c44c253b..984ed147a1 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 @@ -1,6 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/grid_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; @@ -97,7 +96,6 @@ class _FlowyGridState extends State { child: ScrollConfiguration( behavior: const ScrollBehavior().copyWith(scrollbars: false), child: CustomScrollView( - shrinkWrap: true, physics: StyledScrollPhysics(), controller: _scrollController.verticalController, slivers: [ diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index b8834cd213..a813a51dc0 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -30,28 +30,47 @@ class _GridRowWidgetState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _rowBloc, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), - onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: _rowBloc.state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: const [ - _RowLeading(), - _RowCells(), - _RowTrailing(), - ], - ), - ); - }, - ), + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: _rowBloc.state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, ), ); + // return BlocProvider.value( + // value: _rowBloc, + // child: MouseRegion( + // cursor: SystemMouseCursors.click, + // onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), + // onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), + // child: BlocBuilder( + // buildWhen: (p, c) => p.rowHeight != c.rowHeight, + // builder: (context, state) { + // return SizedBox( + // height: _rowBloc.state.rowHeight, + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.stretch, + // children: const [ + // _RowLeading(), + // _RowCells(), + // _RowTrailing(), + // ], + // ), + // ); + // }, + // ), + // ), + // ); } @override diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 6a7c6d05ef..dd477dd8bb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -52,7 +52,7 @@ class _CreateFieldPannelWidget extends StatelessWidget { child: BlocBuilder( builder: (context, state) { return state.field.fold( - () => const SizedBox(), + () => const SizedBox(width: 200), (field) => ListView( shrinkWrap: true, children: [ diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart index ce542b6760..cab5a51138 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart @@ -95,10 +95,10 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: ((previous, current) => previous.editContext.gridField.name == current.editContext.gridField.name), + buildWhen: ((previous, current) => previous.fieldName == current.fieldName), builder: (context, state) { return FieldNameTextField( - name: state.editContext.gridField.name, + name: state.fieldName, errorText: state.errorText, onNameChanged: (newName) { context.read().add(EditFieldEvent.updateFieldName(newName)); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart index ddf5eb7660..a4ccc94a94 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -46,7 +46,7 @@ class FieldActionItem extends StatelessWidget { text: FlowyText.medium(action.title(), fontSize: 12), hoverColor: theme.hover, onTap: () { - action.run(context, fieldId); + action.run(context); onTap(); }, leftIcon: svg(action.iconName(), color: theme.iconColor), @@ -83,16 +83,16 @@ extension _FieldActionExtension on FieldAction { } } - void run(BuildContext context, String fieldId) { + void run(BuildContext context) { switch (this) { case FieldAction.hide: - context.read().add(EditFieldEvent.hideField(fieldId)); + context.read().add(const EditFieldEvent.hideField()); break; case FieldAction.duplicate: - context.read().add(EditFieldEvent.duplicateField(fieldId)); + context.read().add(const EditFieldEvent.duplicateField()); break; case FieldAction.delete: - context.read().add(EditFieldEvent.deleteField(fieldId)); + context.read().add(const EditFieldEvent.deleteField()); break; } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index cd9adbd928..1fee89aecb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -11,12 +11,13 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'type_option/number.dart'; + typedef SelectFieldCallback = void Function(Field, Uint8List); class FieldTypeSwitcher extends StatelessWidget { @@ -40,8 +41,11 @@ class FieldTypeSwitcher extends StatelessWidget { ]; final builder = _makeTypeOptionBuild( - state.field.fieldType, - state.typeOptionData, + fieldType: state.field.fieldType, + typeOptionData: state.typeOptionData, + typeOptionDataCallback: (newTypeOptionData) { + context.read().add(SwitchFieldTypeEvent.didUpdateTypeOptionData(newTypeOptionData)); + }, ); final typeOptionWidget = builder.customWidget; @@ -77,7 +81,6 @@ class FieldTypeSwitcher extends StatelessWidget { } abstract class TypeOptionBuilder { - Uint8List? get typeOptionData; Widget? get customWidget; } @@ -85,7 +88,14 @@ abstract class TypeOptionWidget extends StatelessWidget { const TypeOptionWidget({Key? key}) : super(key: key); } -TypeOptionBuilder _makeTypeOptionBuild(FieldType fieldType, Uint8List typeOptionData) { +typedef TypeOptionData = Uint8List; +typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); + +TypeOptionBuilder _makeTypeOptionBuild({ + required FieldType fieldType, + required TypeOptionData typeOptionData, + required TypeOptionDataCallback typeOptionDataCallback, +}) { switch (fieldType) { case FieldType.Checkbox: return CheckboxTypeOptionBuilder(typeOptionData); @@ -94,7 +104,7 @@ TypeOptionBuilder _makeTypeOptionBuild(FieldType fieldType, Uint8List typeOption case FieldType.MultiSelect: return MultiSelectTypeOptionBuilder(typeOptionData); case FieldType.Number: - return NumberTypeOptionBuilder(typeOptionData); + return NumberTypeOptionBuilder(typeOptionData, typeOptionDataCallback); case FieldType.RichText: return RichTextTypeOptionBuilder(typeOptionData); case FieldType.SingleSelect: @@ -107,46 +117,16 @@ TypeOptionBuilder _makeTypeOptionBuild(FieldType fieldType, Uint8List typeOption class RichTextTypeOptionBuilder extends TypeOptionBuilder { RichTextTypeOption typeOption; - RichTextTypeOptionBuilder(Uint8List typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData); - - @override - Uint8List? get typeOptionData => typeOption.writeToBuffer(); + RichTextTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData); @override Widget? get customWidget => null; } -class NumberTypeOptionBuilder extends TypeOptionBuilder { - NumberTypeOption typeOption; - - NumberTypeOptionBuilder(Uint8List typeOptionData) : typeOption = NumberTypeOption.fromBuffer(typeOptionData); - - @override - Uint8List? get typeOptionData => typeOption.writeToBuffer(); - - @override - Widget? get customWidget => const NumberTypeOptionWidget(); -} - -class NumberTypeOptionWidget extends TypeOptionWidget { - const NumberTypeOptionWidget({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: Container(height: 30, color: Colors.green), - ); - } -} - class DateTypeOptionBuilder extends TypeOptionBuilder { DateTypeOption typeOption; - DateTypeOptionBuilder(Uint8List typeOptionData) : typeOption = DateTypeOption.fromBuffer(typeOptionData); - - @override - Uint8List? get typeOptionData => typeOption.writeToBuffer(); + DateTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = DateTypeOption.fromBuffer(typeOptionData); @override Widget? get customWidget => const DateTypeOptionWidget(); @@ -167,10 +147,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { class CheckboxTypeOptionBuilder extends TypeOptionBuilder { CheckboxTypeOption typeOption; - CheckboxTypeOptionBuilder(Uint8List typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData); - - @override - Uint8List? get typeOptionData => throw UnimplementedError(); + CheckboxTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData); @override Widget? get customWidget => null; @@ -179,12 +156,9 @@ class CheckboxTypeOptionBuilder extends TypeOptionBuilder { class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { SingleSelectTypeOption typeOption; - SingleSelectTypeOptionBuilder(Uint8List typeOptionData) + SingleSelectTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); - @override - Uint8List? get typeOptionData => typeOption.writeToBuffer(); - @override Widget? get customWidget => const SingleSelectTypeOptionWidget(); } @@ -204,12 +178,9 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { MultiSelectTypeOption typeOption; - MultiSelectTypeOptionBuilder(Uint8List typeOptionData) + MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); - @override - Uint8List? get typeOptionData => typeOption.writeToBuffer(); - @override Widget? get customWidget => const MultiSelectTypeOptionWidget(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart new file mode 100644 index 0000000000..6e07fec904 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -0,0 +1,123 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'create_field_pannel.dart'; +import 'grid_header_cell.dart'; + +class GridHeaderDelegate extends SliverPersistentHeaderDelegate { + final String gridId; + final List fields; + + GridHeaderDelegate({required this.gridId, required this.fields}); + + @override + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { + return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields)); + } + + @override + double get maxExtent => GridSize.headerHeight; + + @override + double get minExtent => GridSize.headerHeight; + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { + if (oldDelegate is GridHeaderDelegate) { + return fields != oldDelegate.fields; + } + return false; + } +} + +class GridHeader extends StatelessWidget { + final List fields; + final String gridId; + const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocProvider( + create: (context) { + final bloc = getIt(param1: gridId, param2: fields); + bloc.add(const GridHeaderEvent.initial()); + return bloc; + }, + child: BlocBuilder( + builder: (context, state) { + final cells = state.fields.map( + (field) => GridHeaderCell( + GridFieldData(gridId: gridId, field: field), + ), + ); + + final row = Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const _HeaderLeading(), + ...cells, + _HeaderTrailing(gridId: gridId), + ], + ); + + return Container(color: theme.surface, child: row); + }, + ), + ); + } +} + +class _HeaderLeading extends StatelessWidget { + const _HeaderLeading({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: GridSize.leadingHeaderPadding, + ); + } +} + +class _HeaderTrailing extends StatelessWidget { + final String gridId; + const _HeaderTrailing({required this.gridId, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + final borderSide = BorderSide(color: theme.shader4, width: 0.4); + return Container( + width: GridSize.trailHeaderPadding, + decoration: BoxDecoration( + border: Border(top: borderSide, bottom: borderSide), + ), + padding: GridSize.headerContentInsets, + child: CreateFieldButton(gridId: gridId), + ); + } +} + +class CreateFieldButton extends StatelessWidget { + final String gridId; + const CreateFieldButton({required this.gridId, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyButton( + text: const FlowyText.medium('New column', fontSize: 12), + hoverColor: theme.hover, + onTap: () => CreateFieldPannel(gridId: gridId).show(context, gridId), + leftIcon: svg("home/add"), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart new file mode 100755 index 0000000000..5e5dc5f4fd --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart @@ -0,0 +1,36 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'edit_field_pannel.dart'; + +class GridHeaderCell extends StatelessWidget { + final GridFieldData fieldData; + const GridHeaderCell(this.fieldData, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + final button = FlowyButton( + hoverColor: theme.hover, + onTap: () => EditFieldPannel.show(context, fieldData), + rightIcon: svg("editor/details", color: theme.iconColor), + text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), + ); + + final borderSide = BorderSide(color: theme.shader4, width: 0.4); + final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); + + return Container( + width: fieldData.field.width.toDouble(), + decoration: decoration, + padding: GridSize.headerContentInsets, + child: button, + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart new file mode 100644 index 0000000000..f7016510b7 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -0,0 +1,165 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/number_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart' hide NumberFormat; +import 'package:app_flowy/generated/locale_keys.g.dart'; + +class NumberTypeOptionBuilder extends TypeOptionBuilder { + NumberTypeOption typeOption; + TypeOptionDataCallback typeOptionDataCallback; + + NumberTypeOptionBuilder( + TypeOptionData typeOptionData, + this.typeOptionDataCallback, + ) : typeOption = NumberTypeOption.fromBuffer(typeOptionData); + + @override + Widget? get customWidget => NumberTypeOptionWidget( + typeOption: typeOption, + updateCallback: typeOptionDataCallback, + ); +} + +class NumberTypeOptionWidget extends TypeOptionWidget { + final TypeOptionDataCallback updateCallback; + final NumberTypeOption typeOption; + const NumberTypeOptionWidget({required this.typeOption, required this.updateCallback, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocProvider( + create: (context) => getIt(param1: typeOption), + child: SizedBox( + height: 36, + child: BlocConsumer( + listener: (context, state) => updateCallback(state.typeOption.writeToBuffer()), + builder: (context, state) { + return FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr(), fontSize: 12), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + hoverColor: theme.hover, + onTap: () { + NumberFormatList.show(context, (format) { + context.read().add(NumberTypeOptionEvent.didSelectFormat(format)); + }); + }, + rightIcon: svg("grid/more", color: theme.iconColor), + ); + }, + ), + ), + ); + } +} + +typedef _SelectNumberFormatCallback = Function(NumberFormat format); + +class NumberFormatList extends StatelessWidget { + final _SelectNumberFormatCallback onSelected; + const NumberFormatList({required this.onSelected, Key? key}) : super(key: key); + + static void show(BuildContext context, _SelectNumberFormatCallback onSelected) { + final list = NumberFormatList(onSelected: onSelected); + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: list, + constraints: BoxConstraints.loose(const Size(140, 300)), + ), + identifier: list.identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.leftWithCenterAligned, + style: FlowyOverlayStyle(blur: false), + anchorOffset: const Offset(-20, 0), + ); + } + + @override + Widget build(BuildContext context) { + final formatItems = NumberFormat.values.map((format) { + return NumberFormatItem( + format: format, + onSelected: (format) { + onSelected(format); + FlowyOverlay.of(context).remove(identifier()); + }); + }).toList(); + + return ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return const VSpace(10); + }, + itemCount: formatItems.length, + itemBuilder: (BuildContext context, int index) { + return formatItems[index]; + }, + ); + } + + String identifier() { + return toString(); + } +} + +class NumberFormatItem extends StatelessWidget { + final NumberFormat format; + final Function(NumberFormat format) onSelected; + const NumberFormatItem({required this.format, required this.onSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: 26, + child: FlowyButton( + text: FlowyText.medium(format.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () => onSelected(format), + leftIcon: svg(format.iconName(), color: theme.iconColor), + ), + ); + } +} + +extension NumberFormatExtension on NumberFormat { + String title() { + switch (this) { + case NumberFormat.CNY: + return "Yen"; + case NumberFormat.EUR: + return "Euro"; + case NumberFormat.Number: + return "Numbers"; + case NumberFormat.USD: + return "US Dollar"; + default: + throw UnimplementedError; + } + } + + String iconName() { + switch (this) { + case NumberFormat.CNY: + return "grid/field/yen"; + case NumberFormat.EUR: + return "grid/field/euro"; + case NumberFormat.Number: + return "grid/field/numbers"; + case NumberFormat.USD: + return "grid/field/us_dollar"; + default: + throw UnimplementedError; + } + } +} From d2080a6c03707953638f3c639c3a00fddd210819 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 28 Mar 2022 22:47:30 +0800 Subject: [PATCH 15/47] chore: date field --- .../app_flowy/assets/translations/en.json | 10 +- .../app_flowy/lib/startup/deps_resolver.dart | 9 +- .../grid/field/switch_field_type_bloc.dart | 20 +- .../grid/field/type_option/date_bloc.dart | 28 ++- .../grid/field/type_option/number_bloc.dart | 4 +- .../plugins/grid/src/layout/sizes.dart | 7 + .../widgets/header/create_field_pannel.dart | 2 - .../widgets/header/field_tyep_switcher.dart | 201 +++++++-------- .../src/widgets/header/field_type_list.dart | 13 +- .../src/widgets/header/type_option/date.dart | 229 ++++++++++++++++++ .../widgets/header/type_option/number.dart | 58 ++--- .../widgets/header/type_option/selection.dart | 50 ++++ .../lib/src/flowy_overlay/flowy_overlay.dart | 4 +- 13 files changed, 458 insertions(+), 177 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 1031265da1..0fe9008ee6 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -155,7 +155,15 @@ "numberFieldName": "Numbers", "singleSelectFieldName": "Select", "multiSelectFieldName": "Multiselect", - "numberFormat": " Number format" + "numberFormat": " Number format", + "dateFormat": " Date format", + "dateFormatFriendly": "Month Day,Year", + "dateFormatISO": "Year-Month-Day", + "dateFormatLocal": "Month/Month/Day", + "dateFormatUS": "Month/Month/Day", + "timeFormat": " Time format", + "timeFormatTwelveHour": "12 hour", + "timeFormatTwentyFourHour": "24 hour" } } } diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index e277bc6a20..5d78cbdf2a 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -18,6 +18,7 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:get_it/get_it.dart'; @@ -210,16 +211,16 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => SwitchFieldTypeBloc(context), + getIt.registerFactoryParam( + (context, _) => FieldTypeSwitchBloc(context), ); getIt.registerFactory( () => SelectionTypeOptionBloc(), ); - getIt.registerFactory( - () => DateTypeOptionBloc(), + getIt.registerFactoryParam( + (typeOption, _) => DateTypeOptionBloc(typeOption: typeOption), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart index a2f7438434..ba8371c3a3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -9,9 +9,9 @@ import 'field_service.dart'; part 'switch_field_type_bloc.freezed.dart'; -class SwitchFieldTypeBloc extends Bloc { - SwitchFieldTypeBloc(SwitchFieldContext editContext) : super(SwitchFieldTypeState.initial(editContext)) { - on( +class FieldTypeSwitchBloc extends Bloc { + FieldTypeSwitchBloc(SwitchFieldContext editContext) : super(FieldTypeSwitchState.initial(editContext)) { + on( (event, emit) async { await event.map( toFieldType: (_ToFieldType value) async { @@ -44,20 +44,20 @@ class SwitchFieldTypeBloc extends Bloc SwitchFieldTypeState( + factory FieldTypeSwitchState.initial(SwitchFieldContext switchContext) => FieldTypeSwitchState( gridId: switchContext.gridId, field: switchContext.field, typeOptionData: Uint8List.fromList(switchContext.typeOptionData), diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart index 78b22b078b..e2e7f2f0e2 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart @@ -1,20 +1,23 @@ -import 'dart:typed_data'; - -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'package:dartz/dartz.dart'; part 'date_bloc.freezed.dart'; class DateTypeOptionBloc extends Bloc { - DateTypeOptionBloc() : super(DateTypeOptionState.initial()) { + DateTypeOptionBloc({required DateTypeOption typeOption}) : super(DateTypeOptionState.initial(typeOption)) { on( (event, emit) async { - await event.map( - initial: (_InitialField value) async {}, + event.map( + didSelectDateFormat: (_DidSelectDateFormat value) { + state.typeOption.dateFormat = value.format; + emit(state); + }, + didSelectTimeFormat: (_DidSelectTimeFormat value) { + state.typeOption.timeFormat = value.format; + emit(state); + }, ); }, ); @@ -28,12 +31,15 @@ class DateTypeOptionBloc extends Bloc @freezed class DateTypeOptionEvent with _$DateTypeOptionEvent { - const factory DateTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField; + const factory DateTypeOptionEvent.didSelectDateFormat(DateFormat format) = _DidSelectDateFormat; + const factory DateTypeOptionEvent.didSelectTimeFormat(TimeFormat format) = _DidSelectTimeFormat; } @freezed class DateTypeOptionState with _$DateTypeOptionState { - const factory DateTypeOptionState() = _DateTypeOptionState; + const factory DateTypeOptionState({ + required DateTypeOption typeOption, + }) = _DateTypeOptionState; - factory DateTypeOptionState.initial() => DateTypeOptionState(); + factory DateTypeOptionState.initial(DateTypeOption typeOption) => DateTypeOptionState(typeOption: typeOption); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart index 5b63a7aee4..a396454671 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart @@ -9,8 +9,7 @@ class NumberTypeOptionBloc extends Bloc( (event, emit) async { - await event.map( - initial: (_InitialField value) async {}, + event.map( didSelectFormat: (_DidSelectFormat value) { state.typeOption.format = value.format; emit(state); @@ -28,7 +27,6 @@ class NumberTypeOptionBloc extends Bloc 140 * scale; static double get headerContainerPadding => 0 * scale; static double get cellContentPadding => 10 * scale; + static double get typeOptionItemHeight => 30 * scale; + static double get typeOptionSeparatorHeight => 6 * scale; // static EdgeInsets get headerContentInsets => EdgeInsets.symmetric( @@ -26,6 +28,11 @@ class GridSize { vertical: GridSize.cellContentPadding, ); + static EdgeInsets get typeOptionContentInsets => const EdgeInsets.symmetric( + horizontal: 6, + vertical: 2, + ); + static EdgeInsets get footerContentInsets => EdgeInsets.fromLTRB( 0, GridSize.headerContainerPadding, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index dd477dd8bb..8b2b74d9ae 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -4,7 +4,6 @@ import 'package:app_flowy/workspace/application/grid/field/switch_field_type_blo import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_name_input.dart'; @@ -61,7 +60,6 @@ class _CreateFieldPannelWidget extends StatelessWidget { const _FieldNameTextField(), const VSpace(10), _FieldTypeSwitcher(SwitchFieldContext(state.gridId, field, state.typeOptionData)), - const VSpace(10), ], ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index 1fee89aecb..6e03b4243d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -1,26 +1,29 @@ import 'dart:typed_data'; -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; + import 'type_option/number.dart'; typedef SelectFieldCallback = void Function(Field, Uint8List); -class FieldTypeSwitcher extends StatelessWidget { +class FieldTypeSwitcher extends StatefulWidget { final SwitchFieldContext switchContext; final SelectFieldCallback onSelected; @@ -30,25 +33,27 @@ class FieldTypeSwitcher extends StatelessWidget { Key? key, }) : super(key: key); + @override + State createState() => _FieldTypeSwitcherState(); +} + +class _FieldTypeSwitcherState extends State { + String? currentOverlayIdentifier; + @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: switchContext), - child: BlocBuilder( + create: (context) => getIt(param1: widget.switchContext), + child: BlocBuilder( builder: (context, state) { - List children = [ - _switchFieldTypeButton(context, state.field), - ]; + List children = [_switchFieldTypeButton(context, state.field)]; - final builder = _makeTypeOptionBuild( + final typeOptionWidget = _typeOptionWidget( + context: context, fieldType: state.field.fieldType, - typeOptionData: state.typeOptionData, - typeOptionDataCallback: (newTypeOptionData) { - context.read().add(SwitchFieldTypeEvent.didUpdateTypeOptionData(newTypeOptionData)); - }, + data: state.typeOptionData, ); - final typeOptionWidget = builder.customWidget; if (typeOptionWidget != null) { children.add(typeOptionWidget); } @@ -65,53 +70,100 @@ class FieldTypeSwitcher extends StatelessWidget { Widget _switchFieldTypeButton(BuildContext context, Field field) { final theme = context.watch(); return SizedBox( - height: 36, + height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(field.fieldType.title(), fontSize: 12), padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), hoverColor: theme.hover, - onTap: () => FieldTypeList.show(context, (fieldType) { - context.read().add(SwitchFieldTypeEvent.toFieldType(fieldType)); - }), + onTap: () { + final list = FieldTypeList(onSelectField: (fieldType) { + context.read().add(FieldTypeSwitchEvent.toFieldType(fieldType)); + }); + _showOverlay(context, FieldTypeList.identifier(), list); + }, leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), rightIcon: svg("grid/more", color: theme.iconColor), ), ); } + + Widget? _typeOptionWidget({ + required BuildContext context, + required FieldType fieldType, + required TypeOptionData data, + }) { + final delegate = TypeOptionOperationDelegate( + didUpdateTypeOptionData: (data) { + context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data)); + }, + requireToShowOverlay: _showOverlay, + ); + final builder = _makeTypeOptionBuild(fieldType: fieldType, data: data, delegate: delegate); + return builder.customWidget; + } + + void _showOverlay(BuildContext context, String identifier, Widget child) { + if (currentOverlayIdentifier != null) { + FlowyOverlay.of(context).remove(currentOverlayIdentifier!); + } + + currentOverlayIdentifier = identifier; + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: child, + constraints: BoxConstraints.loose(const Size(240, 400)), + ), + identifier: identifier, + anchorContext: context, + anchorDirection: AnchorDirection.leftWithCenterAligned, + style: FlowyOverlayStyle(blur: false), + anchorOffset: const Offset(-20, 0), + ); + } } abstract class TypeOptionBuilder { Widget? get customWidget; } +TypeOptionBuilder _makeTypeOptionBuild({ + required FieldType fieldType, + required TypeOptionData data, + required TypeOptionOperationDelegate delegate, +}) { + switch (fieldType) { + case FieldType.Checkbox: + return CheckboxTypeOptionBuilder(data); + case FieldType.DateTime: + return DateTypeOptionBuilder(data, delegate); + case FieldType.MultiSelect: + return MultiSelectTypeOptionBuilder(data); + case FieldType.Number: + return NumberTypeOptionBuilder(data, delegate); + case FieldType.RichText: + return RichTextTypeOptionBuilder(data); + case FieldType.SingleSelect: + return SingleSelectTypeOptionBuilder(data); + default: + throw UnimplementedError; + } +} + abstract class TypeOptionWidget extends StatelessWidget { const TypeOptionWidget({Key? key}) : super(key: key); } typedef TypeOptionData = Uint8List; typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); +typedef ShowOverlayCallback = void Function(BuildContext anchorContext, String overlayIdentifier, Widget child); -TypeOptionBuilder _makeTypeOptionBuild({ - required FieldType fieldType, - required TypeOptionData typeOptionData, - required TypeOptionDataCallback typeOptionDataCallback, -}) { - switch (fieldType) { - case FieldType.Checkbox: - return CheckboxTypeOptionBuilder(typeOptionData); - case FieldType.DateTime: - return DateTypeOptionBuilder(typeOptionData); - case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder(typeOptionData); - case FieldType.Number: - return NumberTypeOptionBuilder(typeOptionData, typeOptionDataCallback); - case FieldType.RichText: - return RichTextTypeOptionBuilder(typeOptionData); - case FieldType.SingleSelect: - return SingleSelectTypeOptionBuilder(typeOptionData); - default: - throw UnimplementedError; - } +class TypeOptionOperationDelegate { + TypeOptionDataCallback didUpdateTypeOptionData; + ShowOverlayCallback requireToShowOverlay; + TypeOptionOperationDelegate({ + required this.didUpdateTypeOptionData, + required this.requireToShowOverlay, + }); } class RichTextTypeOptionBuilder extends TypeOptionBuilder { @@ -123,27 +175,6 @@ class RichTextTypeOptionBuilder extends TypeOptionBuilder { Widget? get customWidget => null; } -class DateTypeOptionBuilder extends TypeOptionBuilder { - DateTypeOption typeOption; - - DateTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = DateTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => const DateTypeOptionWidget(); -} - -class DateTypeOptionWidget extends TypeOptionWidget { - const DateTypeOptionWidget({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: Container(height: 80, color: Colors.red), - ); - } -} - class CheckboxTypeOptionBuilder extends TypeOptionBuilder { CheckboxTypeOption typeOption; @@ -152,47 +183,3 @@ class CheckboxTypeOptionBuilder extends TypeOptionBuilder { @override Widget? get customWidget => null; } - -class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { - SingleSelectTypeOption typeOption; - - SingleSelectTypeOptionBuilder(TypeOptionData typeOptionData) - : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => const SingleSelectTypeOptionWidget(); -} - -class SingleSelectTypeOptionWidget extends TypeOptionWidget { - const SingleSelectTypeOptionWidget({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: Container(height: 100, color: Colors.yellow), - ); - } -} - -class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { - MultiSelectTypeOption typeOption; - - MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData) - : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => const MultiSelectTypeOptionWidget(); -} - -class MultiSelectTypeOptionWidget extends TypeOptionWidget { - const MultiSelectTypeOptionWidget({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: Container(height: 100, color: Colors.blue), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index 25481fce09..dfc5c007c6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -19,12 +19,13 @@ class FieldTypeList extends StatelessWidget { static void show(BuildContext context, SelectFieldCallback onSelectField) { final list = FieldTypeList(onSelectField: onSelectField); + FieldTypeList.hide(context); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: list, constraints: BoxConstraints.loose(const Size(140, 300)), ), - identifier: list.identifier(), + identifier: FieldTypeList.identifier(), anchorContext: context, anchorDirection: AnchorDirection.leftWithCenterAligned, style: FlowyOverlayStyle(blur: false), @@ -32,6 +33,10 @@ class FieldTypeList extends StatelessWidget { ); } + static void hide(BuildContext context) { + FlowyOverlay.of(context).remove(FieldTypeList.identifier()); + } + @override Widget build(BuildContext context) { final cells = FieldType.values.map((fieldType) { @@ -39,7 +44,7 @@ class FieldTypeList extends StatelessWidget { fieldType: fieldType, onSelectField: (fieldType) { onSelectField(fieldType); - FlowyOverlay.of(context).remove(identifier()); + FlowyOverlay.of(context).remove(FieldTypeList.identifier()); }, ); }).toList(); @@ -58,8 +63,8 @@ class FieldTypeList extends StatelessWidget { ); } - String identifier() { - return toString(); + static String identifier() { + return (FieldTypeList).toString(); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart new file mode 100644 index 0000000000..493ab0e02e --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -0,0 +1,229 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:easy_localization/easy_localization.dart' hide DateFormat; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class DateTypeOptionBuilder extends TypeOptionBuilder { + DateTypeOption typeOption; + TypeOptionOperationDelegate delegate; + + DateTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate) + : typeOption = DateTypeOption.fromBuffer(typeOptionData); + + @override + Widget? get customWidget => DateTypeOptionWidget( + typeOption: typeOption, + operationDelegate: delegate, + ); +} + +class DateTypeOptionWidget extends TypeOptionWidget { + final DateTypeOption typeOption; + final TypeOptionOperationDelegate operationDelegate; + const DateTypeOptionWidget({required this.typeOption, required this.operationDelegate, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: typeOption), + child: BlocConsumer( + listener: (context, state) => operationDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + builder: (context, state) { + return Column(children: [ + _dateFormatButton(context), + _timeFormatButton(context), + ]); + }, + ), + ); + } + + Widget _dateFormatButton(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr(), fontSize: 12), + padding: GridSize.typeOptionContentInsets, + hoverColor: theme.hover, + onTap: () { + final list = DateFormatList(onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); + }); + operationDelegate.requireToShowOverlay(context, list.identifier(), list); + }, + rightIcon: svg("grid/more", color: theme.iconColor), + ), + ); + } + + Widget _timeFormatButton(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr(), fontSize: 12), + padding: GridSize.typeOptionContentInsets, + hoverColor: theme.hover, + onTap: () { + final list = TimeFormatList(onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); + }); + operationDelegate.requireToShowOverlay(context, list.identifier(), list); + }, + rightIcon: svg("grid/more", color: theme.iconColor), + ), + ); + } +} + +class DateFormatList extends StatelessWidget { + final Function(DateFormat format) onSelected; + const DateFormatList({required this.onSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final formatItems = DateFormat.values.map((format) { + return DateFormatItem( + dateFormat: format, + onSelected: (format) { + onSelected(format); + FlowyOverlay.of(context).remove(identifier()); + }); + }).toList(); + + return SizedBox( + width: 180, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: formatItems.length, + itemBuilder: (BuildContext context, int index) { + return formatItems[index]; + }, + ), + ); + } + + String identifier() { + return toString(); + } +} + +class DateFormatItem extends StatelessWidget { + final DateFormat dateFormat; + final Function(DateFormat format) onSelected; + const DateFormatItem({required this.dateFormat, required this.onSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(dateFormat.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () => onSelected(dateFormat), + ), + ); + } +} + +extension DateFormatExtension on DateFormat { + String title() { + switch (this) { + case DateFormat.Friendly: + return LocaleKeys.grid_field_dateFormatFriendly.tr(); + case DateFormat.ISO: + return LocaleKeys.grid_field_dateFormatISO.tr(); + case DateFormat.Local: + return LocaleKeys.grid_field_dateFormatLocal.tr(); + case DateFormat.US: + return LocaleKeys.grid_field_dateFormatUS.tr(); + default: + throw UnimplementedError; + } + } +} + +class TimeFormatList extends StatelessWidget { + final Function(TimeFormat format) onSelected; + const TimeFormatList({required this.onSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final formatItems = TimeFormat.values.map((format) { + return TimeFormatItem( + timeFormat: format, + onSelected: (format) { + onSelected(format); + FlowyOverlay.of(context).remove(identifier()); + }); + }).toList(); + + return SizedBox( + width: 120, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: formatItems.length, + itemBuilder: (BuildContext context, int index) { + return formatItems[index]; + }, + ), + ); + } + + String identifier() { + return toString(); + } +} + +class TimeFormatItem extends StatelessWidget { + final TimeFormat timeFormat; + final Function(TimeFormat format) onSelected; + const TimeFormatItem({required this.timeFormat, required this.onSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(timeFormat.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () => onSelected(timeFormat), + ), + ); + } +} + +extension TimeFormatExtension on TimeFormat { + String title() { + switch (this) { + case TimeFormat.TwelveHour: + return LocaleKeys.grid_field_timeFormatTwelveHour.tr(); + case TimeFormat.TwentyFourHour: + return LocaleKeys.grid_field_timeFormatTwentyFourHour.tr(); + default: + throw UnimplementedError; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index f7016510b7..6aeb73ac48 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/number_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -15,24 +16,24 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; class NumberTypeOptionBuilder extends TypeOptionBuilder { NumberTypeOption typeOption; - TypeOptionDataCallback typeOptionDataCallback; + TypeOptionOperationDelegate delegate; NumberTypeOptionBuilder( TypeOptionData typeOptionData, - this.typeOptionDataCallback, + this.delegate, ) : typeOption = NumberTypeOption.fromBuffer(typeOptionData); @override Widget? get customWidget => NumberTypeOptionWidget( typeOption: typeOption, - updateCallback: typeOptionDataCallback, + operationDelegate: delegate, ); } class NumberTypeOptionWidget extends TypeOptionWidget { - final TypeOptionDataCallback updateCallback; + final TypeOptionOperationDelegate operationDelegate; final NumberTypeOption typeOption; - const NumberTypeOptionWidget({required this.typeOption, required this.updateCallback, Key? key}) : super(key: key); + const NumberTypeOptionWidget({required this.typeOption, required this.operationDelegate, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -40,18 +41,19 @@ class NumberTypeOptionWidget extends TypeOptionWidget { return BlocProvider( create: (context) => getIt(param1: typeOption), child: SizedBox( - height: 36, + height: GridSize.typeOptionItemHeight, child: BlocConsumer( - listener: (context, state) => updateCallback(state.typeOption.writeToBuffer()), + listener: (context, state) => operationDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return FlowyButton( text: FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr(), fontSize: 12), - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + padding: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { - NumberFormatList.show(context, (format) { + final list = NumberFormatList(onSelected: (format) { context.read().add(NumberTypeOptionEvent.didSelectFormat(format)); }); + operationDelegate.requireToShowOverlay(context, list.identifier(), list); }, rightIcon: svg("grid/more", color: theme.iconColor), ); @@ -68,21 +70,6 @@ class NumberFormatList extends StatelessWidget { final _SelectNumberFormatCallback onSelected; const NumberFormatList({required this.onSelected, Key? key}) : super(key: key); - static void show(BuildContext context, _SelectNumberFormatCallback onSelected) { - final list = NumberFormatList(onSelected: onSelected); - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: list, - constraints: BoxConstraints.loose(const Size(140, 300)), - ), - identifier: list.identifier(), - anchorContext: context, - anchorDirection: AnchorDirection.leftWithCenterAligned, - style: FlowyOverlayStyle(blur: false), - anchorOffset: const Offset(-20, 0), - ); - } - @override Widget build(BuildContext context) { final formatItems = NumberFormat.values.map((format) { @@ -94,16 +81,19 @@ class NumberFormatList extends StatelessWidget { }); }).toList(); - return ListView.separated( - shrinkWrap: true, - controller: ScrollController(), - separatorBuilder: (context, index) { - return const VSpace(10); - }, - itemCount: formatItems.length, - itemBuilder: (BuildContext context, int index) { - return formatItems[index]; - }, + return SizedBox( + width: 120, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: formatItems.length, + itemBuilder: (BuildContext context, int index) { + return formatItems[index]; + }, + ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart new file mode 100644 index 0000000000..b5737fd219 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart @@ -0,0 +1,50 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/selection_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { + SingleSelectTypeOption typeOption; + + SingleSelectTypeOptionBuilder(TypeOptionData typeOptionData) + : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); + + @override + Widget? get customWidget => const SingleSelectTypeOptionWidget(); +} + +class SingleSelectTypeOptionWidget extends TypeOptionWidget { + const SingleSelectTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(height: 100, color: Colors.yellow), + ); + } +} + +class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { + MultiSelectTypeOption typeOption; + + MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData) + : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); + + @override + Widget? get customWidget => const MultiSelectTypeOptionWidget(); +} + +class MultiSelectTypeOptionWidget extends TypeOptionWidget { + const MultiSelectTypeOptionWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(), + child: Container(height: 100, color: Colors.blue), + ); + } +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 26760dc411..651971d17f 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -182,7 +182,9 @@ class FlowyOverlayState extends State { void remove(String identifier) { setState(() { final index = _overlayList.indexWhere((ele) => ele.value2 == identifier); - _overlayList.removeAt(index).value3?.didRemove(); + if (index != -1) { + _overlayList.removeAt(index).value3?.didRemove(); + } }); } From 55b888e36443e06ca52835a607428085c7f95288 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 29 Mar 2022 11:29:21 +0800 Subject: [PATCH 16/47] chore: single selection field --- .../app_flowy/assets/translations/en.json | 5 +- .../field/type_option/option_pannel_bloc.dart | 56 ++++++ .../grid/src/widgets/content/grid_row.dart | 59 ++---- .../widgets/header/create_field_pannel.dart | 2 +- .../src/widgets/header/field_type_list.dart | 25 +-- .../widgets/header/type_option/number.dart | 2 +- .../widgets/header/type_option/selection.dart | 172 +++++++++++++++++- .../widgets/header/type_option/widget.dart | 65 +++++++ .../lib/widget/rounded_input_field.dart | 6 + 9 files changed, 333 insertions(+), 59 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 0fe9008ee6..fbd672c04f 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -163,7 +163,10 @@ "dateFormatUS": "Month/Month/Day", "timeFormat": " Time format", "timeFormatTwelveHour": "12 hour", - "timeFormatTwentyFourHour": "24 hour" + "timeFormatTwentyFourHour": "24 hour", + "addSelectOption": "Add an option", + "optionTitle": "Options", + "addOption": "Add option" } } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart new file mode 100644 index 0000000000..aacf06c98d --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart @@ -0,0 +1,56 @@ +import 'dart:typed_data'; + +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'option_pannel_bloc.freezed.dart'; + +class OptionPannelBloc extends Bloc { + OptionPannelBloc({required List options}) : super(OptionPannelState.initial(options)) { + on( + (event, emit) async { + await event.map( + createOption: (_CreateOption value) async { + emit(state.copyWith(isAddingOption: false)); + }, + beginAddingOption: (_BeginAddingOption value) { + emit(state.copyWith(isAddingOption: true)); + }, + endAddingOption: (_EndAddingOption value) { + emit(state.copyWith(isAddingOption: false)); + }, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class OptionPannelEvent with _$OptionPannelEvent { + const factory OptionPannelEvent.createOption(String optionName) = _CreateOption; + const factory OptionPannelEvent.beginAddingOption() = _BeginAddingOption; + const factory OptionPannelEvent.endAddingOption() = _EndAddingOption; +} + +@freezed +class OptionPannelState with _$OptionPannelState { + const factory OptionPannelState({ + required List options, + required bool isAddingOption, + }) = _OptionPannelState; + + factory OptionPannelState.initial(List options) => OptionPannelState( + options: options, + isAddingOption: false, + ); +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index a813a51dc0..b8834cd213 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -30,47 +30,28 @@ class _GridRowWidgetState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _rowBloc, - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: _rowBloc.state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: const [ - _RowLeading(), - _RowCells(), - _RowTrailing(), - ], - ), - ); - }, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), + onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: _rowBloc.state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, + ), ), ); - // return BlocProvider.value( - // value: _rowBloc, - // child: MouseRegion( - // cursor: SystemMouseCursors.click, - // onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), - // onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), - // child: BlocBuilder( - // buildWhen: (p, c) => p.rowHeight != c.rowHeight, - // builder: (context, state) { - // return SizedBox( - // height: _rowBloc.state.rowHeight, - // child: Row( - // crossAxisAlignment: CrossAxisAlignment.stretch, - // children: const [ - // _RowLeading(), - // _RowCells(), - // _RowTrailing(), - // ], - // ), - // ); - // }, - // ), - // ), - // ); } @override diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 8b2b74d9ae..c282f10b40 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -20,7 +20,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: _CreateFieldPannelWidget(_createFieldBloc), - constraints: BoxConstraints.loose(const Size(220, 400)), + constraints: BoxConstraints.loose(const Size(220, 500)), ), identifier: identifier(), anchorContext: context, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index dfc5c007c6..0019ffa979 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -49,17 +49,20 @@ class FieldTypeList extends StatelessWidget { ); }).toList(); - return ListView.separated( - shrinkWrap: true, - controller: ScrollController(), - itemCount: cells.length, - separatorBuilder: (context, index) { - return const VSpace(10); - }, - physics: StyledScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return cells[index]; - }, + return SizedBox( + width: 140, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + itemCount: cells.length, + separatorBuilder: (context, index) { + return const VSpace(10); + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index 6aeb73ac48..57a8254f2e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -111,7 +111,7 @@ class NumberFormatItem extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); return SizedBox( - height: 26, + height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(format.title(), fontSize: 12), hoverColor: theme.hover, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart index b5737fd219..2d5c963fc5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart @@ -1,9 +1,20 @@ import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/selection_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; + +import 'widget.dart'; class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { SingleSelectTypeOption typeOption; @@ -12,17 +23,18 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); @override - Widget? get customWidget => const SingleSelectTypeOptionWidget(); + Widget? get customWidget => SingleSelectTypeOptionWidget(typeOption); } class SingleSelectTypeOptionWidget extends TypeOptionWidget { - const SingleSelectTypeOptionWidget({Key? key}) : super(key: key); + final SingleSelectTypeOption typeOption; + const SingleSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(height: 100, color: Colors.yellow), + child: OptionPannel(options: typeOption.options), ); } } @@ -34,17 +46,165 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); @override - Widget? get customWidget => const MultiSelectTypeOptionWidget(); + Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption); } class MultiSelectTypeOptionWidget extends TypeOptionWidget { - const MultiSelectTypeOptionWidget({Key? key}) : super(key: key); + final MultiSelectTypeOption typeOption; + const MultiSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(), - child: Container(height: 100, color: Colors.blue), + child: OptionPannel(options: typeOption.options), ); } } + +class OptionPannel extends StatelessWidget { + final List options; + const OptionPannel({required this.options, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => OptionPannelBloc(options: options), + child: BlocBuilder( + builder: (context, state) { + List children = [const OptionTitle()]; + if (state.isAddingOption) { + children.add(const _AddOptionTextField()); + } + + if (state.options.isEmpty && !state.isAddingOption) { + children.add(const _AddOptionButton()); + } + + if (state.options.isNotEmpty) { + children.add(const _OptionList()); + } + + return Column(children: children); + }, + ), + ); + } +} + +class OptionTitle extends StatelessWidget { + const OptionTitle({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + return BlocBuilder( + buildWhen: (previous, current) => previous.options.length != current.options.length, + builder: (context, state) { + List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; + + if (state.options.isNotEmpty && state.isAddingOption == false) { + children.add(FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_addOption.tr(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + context.read().add(const OptionPannelEvent.beginAddingOption()); + }, + rightIcon: svg("grid/more", color: theme.iconColor), + )); + } + + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: Row(children: children), + ); + }, + ); + } +} + +class _OptionList extends StatelessWidget { + const _OptionList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + final optionItems = state.options.map((option) { + return _OptionItem(option: option); + }).toList(); + + return SizedBox( + width: 120, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: optionItems.length, + itemBuilder: (BuildContext context, int index) { + return optionItems[index]; + }, + ), + ); + }, + ); + } +} + +class _OptionItem extends StatelessWidget { + final SelectOption option; + const _OptionItem({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(option.name, fontSize: 12), + hoverColor: theme.hover, + onTap: () {}, + rightIcon: svg("grid/more", color: theme.iconColor), + ), + ); + } +} + +class _AddOptionButton extends StatelessWidget { + const _AddOptionButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + context.read().add(const OptionPannelEvent.beginAddingOption()); + }, + leftIcon: svg("home/add", color: theme.iconColor), + ), + ); + } +} + +class _AddOptionTextField extends StatelessWidget { + const _AddOptionTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return NameTextField( + name: "", + onCanceled: () { + context.read().add(const OptionPannelEvent.endAddingOption()); + }, + onDone: (optionName) { + context.read().add(OptionPannelEvent.createOption(optionName)); + }); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart new file mode 100644 index 0000000000..f357c9afea --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart @@ -0,0 +1,65 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class NameTextField extends StatefulWidget { + final void Function(String) onDone; + final void Function() onCanceled; + final String name; + + const NameTextField({ + required this.name, + required this.onDone, + required this.onCanceled, + Key? key, + }) : super(key: key); + + @override + State createState() => _NameTextFieldState(); +} + +class _NameTextFieldState extends State { + late FocusNode _focusNode; + late TextEditingController _controller; + + @override + void initState() { + _focusNode = FocusNode(); + _controller = TextEditingController(text: widget.name); + + _focusNode.addListener(notifyDidEndEditing); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return RoundedInputField( + controller: _controller, + focusNode: _focusNode, + height: 36, + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500), + normalBorderColor: theme.shader4, + errorBorderColor: theme.red, + focusBorderColor: theme.main1, + cursorColor: theme.main1, + onChanged: (text) { + print(text); + }); + } + + @override + void dispose() { + _focusNode.removeListener(notifyDidEndEditing); + super.dispose(); + } + + void notifyDidEndEditing() { + if (_controller.text.isEmpty) { + // widget.onCanceled(); + } else { + widget.onDone(_controller.text); + } + } +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart index 110cd29c73..b6bf1daf4b 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart @@ -20,6 +20,8 @@ class RoundedInputField extends StatefulWidget { final EdgeInsets padding; final EdgeInsets contentPadding; final double height; + final FocusNode? focusNode; + final TextEditingController? controller; const RoundedInputField({ Key? key, @@ -39,6 +41,8 @@ class RoundedInputField extends StatefulWidget { this.padding = EdgeInsets.zero, this.contentPadding = const EdgeInsets.symmetric(horizontal: 10), this.height = 48, + this.focusNode, + this.controller, }) : super(key: key); @override @@ -71,7 +75,9 @@ class _RoundedInputFieldState extends State { padding: widget.padding, height: widget.height, child: TextFormField( + controller: widget.controller, initialValue: widget.initialValue, + focusNode: widget.focusNode, onChanged: (value) { inputText = value; if (widget.onChanged != null) { From 065a72a8dad51cf58ea07e95562589042656897e Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 29 Mar 2022 22:58:38 +0800 Subject: [PATCH 17/47] chore: add option & color selection --- .../app_flowy/assets/images/grid/details.svg | 4 + .../app_flowy/assets/translations/en.json | 11 ++ .../app_flowy/lib/startup/deps_resolver.dart | 10 +- .../application/grid/field/field_service.dart | 2 - .../field/type_option/multi_select_bloc.dart | 42 +++++ .../field/type_option/option_pannel_bloc.dart | 17 +- .../field/type_option/selection_bloc.dart | 39 ----- .../field/type_option/single_select_bloc.dart | 57 ++++++ .../type_option/type_option_service.dart | 17 ++ .../workspace/application/grid/prelude.dart | 2 +- .../plugins/doc/src/document_page.dart | 1 + .../widgets/header/create_field_pannel.dart | 2 +- .../widgets/header/field_tyep_switcher.dart | 31 ++-- .../type_option/edit_option_pannel.dart | 115 ++++++++++++ .../header/type_option/multi_select.dart | 48 ++++++ .../{selection.dart => option_pannel.dart} | 137 ++++++--------- .../header/type_option/single_select.dart | 55 ++++++ .../widgets/header/type_option/widget.dart | 47 +++-- .../lib/style_widget/button.dart | 5 +- .../lib/widget/rounded_input_field.dart | 6 + .../dart_event/flowy-grid/dart_event.dart | 17 ++ .../flowy_sdk/lib/dispatch/dispatch.dart | 1 + .../flowy-error-code/code.pbenum.dart | 2 + .../flowy-error-code/code.pbjson.dart | 3 +- .../flowy-grid-data-model/grid.pb.dart | 47 +++++ .../flowy-grid-data-model/grid.pbjson.dart | 10 ++ .../protobuf/flowy-grid/event_map.pbenum.dart | 8 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 9 +- .../rust-lib/flowy-grid/src/event_handler.rs | 10 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 10 +- .../src/protobuf/model/event_map.rs | 22 ++- .../src/protobuf/proto/event_map.proto | 7 +- shared-lib/flowy-error-code/src/code.rs | 2 + .../src/protobuf/model/code.rs | 10 +- .../src/protobuf/proto/code.proto | 1 + .../src/entities/grid.rs | 23 ++- .../flowy-grid-data-model/src/parser/mod.rs | 4 +- .../parser/{id_parser.rs => str_parser.rs} | 18 ++ .../src/protobuf/model/grid.rs | 163 +++++++++++++++++- .../src/protobuf/proto/grid.proto | 3 + 40 files changed, 828 insertions(+), 190 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/details.svg create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/{selection.dart => option_pannel.dart} (55%) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart rename shared-lib/flowy-grid-data-model/src/parser/{id_parser.rs => str_parser.rs} (54%) diff --git a/frontend/app_flowy/assets/images/grid/details.svg b/frontend/app_flowy/assets/images/grid/details.svg new file mode 100644 index 0000000000..e4c9f58f27 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/details.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index fbd672c04f..b751bb6d3e 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -167,6 +167,17 @@ "addSelectOption": "Add an option", "optionTitle": "Options", "addOption": "Add option" + }, + "selectOption": { + "purpleColor": "Purple", + "pinkColor": "Pink", + "lightPinkColor": "Light Pink", + "orangeColor": "Orange", + "yellowColor": "Yellow", + "limeColor": "Lime", + "greenColor": "Green", + "aquaColor": "Aqua", + "blueColor": "Blue" } } } diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 5d78cbdf2a..8bab77150a 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -3,6 +3,7 @@ import 'package:app_flowy/user/application/user_listener.dart'; import 'package:app_flowy/user/application/user_service.dart'; import 'package:app_flowy/workspace/application/app/prelude.dart'; import 'package:app_flowy/workspace/application/doc/prelude.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/application/grid/row/row_listener.dart'; import 'package:app_flowy/workspace/application/trash/prelude.dart'; @@ -20,6 +21,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:get_it/get_it.dart'; @@ -215,8 +217,12 @@ void _resolveGridDeps(GetIt getIt) { (context, _) => FieldTypeSwitchBloc(context), ); - getIt.registerFactory( - () => SelectionTypeOptionBloc(), + getIt.registerFactoryParam( + (typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId), + ); + + getIt.registerFactoryParam( + (typeOption, _) => MultiSelectTypeOptionBloc(typeOption), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 6824ce0b1b..24644f0fae 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -1,5 +1,3 @@ -import 'dart:typed_data'; - import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart new file mode 100644 index 0000000000..75ac80c47c --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart @@ -0,0 +1,42 @@ +import 'dart:typed_data'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +part 'multi_select_bloc.freezed.dart'; + +class MultiSelectTypeOptionBloc extends Bloc { + MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption) : super(MultiSelectTypeOptionState.initial(typeOption)) { + on( + (event, emit) async { + await event.map( + createOption: (_CreateOption value) {}, + updateOptions: (_UpdateOptions value) async {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent { + const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption; + const factory MultiSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions; +} + +@freezed +class MultiSelectTypeOptionState with _$MultiSelectTypeOptionState { + const factory MultiSelectTypeOptionState({ + required MultiSelectTypeOption typeOption, + }) = _MultiSelectTypeOptionState; + + factory MultiSelectTypeOptionState.initial(MultiSelectTypeOption typeOption) => MultiSelectTypeOptionState( + typeOption: typeOption, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart index aacf06c98d..445db413c0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart @@ -1,13 +1,8 @@ -import 'dart:typed_data'; - -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; - part 'option_pannel_bloc.freezed.dart'; class OptionPannelBloc extends Bloc { @@ -16,13 +11,13 @@ class OptionPannelBloc extends Bloc { (event, emit) async { await event.map( createOption: (_CreateOption value) async { - emit(state.copyWith(isAddingOption: false)); + emit(state.copyWith(isEditingOption: false, newOptionName: Some(value.optionName))); }, beginAddingOption: (_BeginAddingOption value) { - emit(state.copyWith(isAddingOption: true)); + emit(state.copyWith(isEditingOption: true, newOptionName: none())); }, endAddingOption: (_EndAddingOption value) { - emit(state.copyWith(isAddingOption: false)); + emit(state.copyWith(isEditingOption: false, newOptionName: none())); }, ); }, @@ -46,11 +41,13 @@ class OptionPannelEvent with _$OptionPannelEvent { class OptionPannelState with _$OptionPannelState { const factory OptionPannelState({ required List options, - required bool isAddingOption, + required bool isEditingOption, + required Option newOptionName, }) = _OptionPannelState; factory OptionPannelState.initial(List options) => OptionPannelState( options: options, - isAddingOption: false, + isEditingOption: false, + newOptionName: none(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart deleted file mode 100644 index ac6d3fb6d4..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; -import 'package:dartz/dartz.dart'; - -part 'selection_bloc.freezed.dart'; - -class SelectionTypeOptionBloc extends Bloc { - SelectionTypeOptionBloc() : super(SelectionTypeOptionState.initial()) { - on( - (event, emit) async { - await event.map( - initial: (_InitialField value) async {}, - ); - }, - ); - } - - @override - Future close() async { - return super.close(); - } -} - -@freezed -class SelectionTypeOptionEvent with _$SelectionTypeOptionEvent { - const factory SelectionTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField; -} - -@freezed -class SelectionTypeOptionState with _$SelectionTypeOptionState { - const factory SelectionTypeOptionState() = _SelectionTypeOptionState; - - factory SelectionTypeOptionState.initial() => SelectionTypeOptionState(); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart new file mode 100644 index 0000000000..07a26439f3 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart @@ -0,0 +1,57 @@ +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +import 'type_option_service.dart'; + +part 'single_select_bloc.freezed.dart'; + +class SingleSelectTypeOptionBloc extends Bloc { + final TypeOptionService service; + + SingleSelectTypeOptionBloc(SingleSelectTypeOption typeOption, String fieldId) + : service = TypeOptionService(fieldId: fieldId), + super(SingleSelectTypeOptionState.initial(typeOption)) { + on( + (event, emit) async { + await event.map( + createOption: (_CreateOption value) async { + final result = await service.createOption(value.optionName); + result.fold( + (option) { + state.typeOption.options.insert(0, option); + emit(state); + }, + (err) => Log.error(err), + ); + }, + updateOptions: (_UpdateOptions value) async {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class SingleSelectTypeOptionEvent with _$SingleSelectTypeOptionEvent { + const factory SingleSelectTypeOptionEvent.createOption(String optionName) = _CreateOption; + const factory SingleSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions; +} + +@freezed +class SingleSelectTypeOptionState with _$SingleSelectTypeOptionState { + const factory SingleSelectTypeOptionState({ + required SingleSelectTypeOption typeOption, + }) = _SingleSelectTypeOptionState; + + factory SingleSelectTypeOptionState.initial(SingleSelectTypeOption typeOption) => SingleSelectTypeOptionState( + typeOption: typeOption, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart new file mode 100644 index 0000000000..8ab3460b82 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart @@ -0,0 +1,17 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; + +class TypeOptionService { + String fieldId; + TypeOptionService({ + required this.fieldId, + }); + + Future> createOption(String name) { + final payload = CreateSelectOptionPayload.create()..optionName = name; + return GridEventCreateSelectOption(payload).send(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 38135f75f6..e1d3020ae0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -14,7 +14,7 @@ export 'field/switch_field_type_bloc.dart'; // Field Type Option export 'field/type_option/date_bloc.dart'; export 'field/type_option/number_bloc.dart'; -export 'field/type_option/selection_bloc.dart'; +export 'field/type_option/single_select_bloc.dart'; // Cell export 'cell_bloc/text_cell_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart index 031edb93fd..5983102047 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart @@ -61,6 +61,7 @@ class _DocumentPageState extends State { @override Future dispose() async { documentBloc.close(); + _focusNode.dispose(); super.dispose(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index c282f10b40..8b2b74d9ae 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -20,7 +20,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: _CreateFieldPannelWidget(_createFieldBloc), - constraints: BoxConstraints.loose(const Size(220, 500)), + constraints: BoxConstraints.loose(const Size(220, 400)), ), identifier: identifier(), anchorContext: context, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index 6e03b4243d..1a418cf543 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -14,12 +13,13 @@ import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'type_option/multi_select.dart'; import 'type_option/number.dart'; +import 'type_option/single_select.dart'; typedef SelectFieldCallback = void Function(Field, Uint8List); @@ -50,7 +50,7 @@ class _FieldTypeSwitcherState extends State { final typeOptionWidget = _typeOptionWidget( context: context, - fieldType: state.field.fieldType, + field: state.field, data: state.typeOptionData, ); @@ -89,7 +89,7 @@ class _FieldTypeSwitcherState extends State { Widget? _typeOptionWidget({ required BuildContext context, - required FieldType fieldType, + required Field field, required TypeOptionData data, }) { final delegate = TypeOptionOperationDelegate( @@ -97,8 +97,9 @@ class _FieldTypeSwitcherState extends State { context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data)); }, requireToShowOverlay: _showOverlay, + hideOverlay: _hideOverlay, ); - final builder = _makeTypeOptionBuild(fieldType: fieldType, data: data, delegate: delegate); + final builder = _makeTypeOptionBuild(field: field, data: data, delegate: delegate); return builder.customWidget; } @@ -120,6 +121,12 @@ class _FieldTypeSwitcherState extends State { anchorOffset: const Offset(-20, 0), ); } + + void _hideOverlay(BuildContext context) { + if (currentOverlayIdentifier != null) { + FlowyOverlay.of(context).remove(currentOverlayIdentifier!); + } + } } abstract class TypeOptionBuilder { @@ -127,23 +134,24 @@ abstract class TypeOptionBuilder { } TypeOptionBuilder _makeTypeOptionBuild({ - required FieldType fieldType, + required Field field, required TypeOptionData data, required TypeOptionOperationDelegate delegate, }) { - switch (fieldType) { + switch (field.fieldType) { case FieldType.Checkbox: return CheckboxTypeOptionBuilder(data); case FieldType.DateTime: return DateTypeOptionBuilder(data, delegate); + case FieldType.SingleSelect: + return SingleSelectTypeOptionBuilder(field.id, data, delegate); case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder(data); + return MultiSelectTypeOptionBuilder(data, delegate); case FieldType.Number: return NumberTypeOptionBuilder(data, delegate); case FieldType.RichText: return RichTextTypeOptionBuilder(data); - case FieldType.SingleSelect: - return SingleSelectTypeOptionBuilder(data); + default: throw UnimplementedError; } @@ -156,13 +164,16 @@ abstract class TypeOptionWidget extends StatelessWidget { typedef TypeOptionData = Uint8List; typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); typedef ShowOverlayCallback = void Function(BuildContext anchorContext, String overlayIdentifier, Widget child); +typedef HideOverlayCallback = void Function(BuildContext anchorContext); class TypeOptionOperationDelegate { TypeOptionDataCallback didUpdateTypeOptionData; ShowOverlayCallback requireToShowOverlay; + HideOverlayCallback hideOverlay; TypeOptionOperationDelegate({ required this.didUpdateTypeOptionData, required this.requireToShowOverlay, + required this.hideOverlay, }); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart new file mode 100644 index 0000000000..31f9570602 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -0,0 +1,115 @@ +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; + +class SelectOptionColorList extends StatelessWidget { + const SelectOptionColorList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} + +class _SelectOptionColorItem extends StatelessWidget { + final SelectOptionColor option; + final bool isSelected; + const _SelectOptionColorItem({required this.option, required this.isSelected, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + Widget? checkmark; + if (isSelected) { + checkmark = svg("grid/details", color: theme.iconColor); + } + + final colorIcon = SizedBox.square( + dimension: 16, + child: Container( + decoration: BoxDecoration( + color: option.color(context), + shape: BoxShape.circle, + ), + ), + ); + + return FlowyButton( + text: FlowyText.medium( + option.name(), + fontSize: 12, + ), + hoverColor: theme.hover, + leftIcon: colorIcon, + rightIcon: checkmark, + onTap: () {}, + ); + } +} + +enum SelectOptionColor { + purple, + pink, + lightPink, + orange, + yellow, + lime, + green, + aqua, + blue, +} + +extension SelectOptionColorExtension on SelectOptionColor { + Color color(BuildContext context) { + final theme = context.watch(); + switch (this) { + case SelectOptionColor.purple: + return theme.tint1; + case SelectOptionColor.pink: + return theme.tint2; + case SelectOptionColor.lightPink: + return theme.tint3; + case SelectOptionColor.orange: + return theme.tint4; + case SelectOptionColor.yellow: + return theme.tint5; + case SelectOptionColor.lime: + return theme.tint6; + case SelectOptionColor.green: + return theme.tint7; + case SelectOptionColor.aqua: + return theme.tint8; + case SelectOptionColor.blue: + return theme.tint9; + } + } + + String name() { + switch (this) { + case SelectOptionColor.purple: + return LocaleKeys.grid_selectOption_purpleColor.tr(); + case SelectOptionColor.pink: + return LocaleKeys.grid_selectOption_pinkColor.tr(); + case SelectOptionColor.lightPink: + return LocaleKeys.grid_selectOption_lightPinkColor.tr(); + case SelectOptionColor.orange: + return LocaleKeys.grid_selectOption_orangeColor.tr(); + case SelectOptionColor.yellow: + return LocaleKeys.grid_selectOption_yellowColor.tr(); + case SelectOptionColor.lime: + return LocaleKeys.grid_selectOption_limeColor.tr(); + case SelectOptionColor.green: + return LocaleKeys.grid_selectOption_greenColor.tr(); + case SelectOptionColor.aqua: + return LocaleKeys.grid_selectOption_aquaColor.tr(); + case SelectOptionColor.blue: + return LocaleKeys.grid_selectOption_blueColor.tr(); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart new file mode 100644 index 0000000000..4a3694b5fc --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -0,0 +1,48 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'option_pannel.dart'; + +class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { + MultiSelectTypeOption typeOption; + TypeOptionOperationDelegate delegate; + + MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate) + : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); + + @override + Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption, delegate); +} + +class MultiSelectTypeOptionWidget extends TypeOptionWidget { + final MultiSelectTypeOption typeOption; + final TypeOptionOperationDelegate delegate; + const MultiSelectTypeOptionWidget(this.typeOption, this.delegate, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: typeOption), + child: BlocBuilder( + builder: (context, state) { + return OptionPannel( + options: state.typeOption.options, + beginEdit: () { + delegate.hideOverlay(context); + }, + createOptionCallback: (name) { + context.read().add(MultiSelectTypeOptionEvent.createOption(name)); + }, + updateOptionsCallback: (options) { + context.read().add(MultiSelectTypeOptionEvent.updateOptions(options)); + }, + ); + }, + ), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart similarity index 55% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart index 2d5c963fc5..736d03d96d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart @@ -1,8 +1,5 @@ -import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/field/type_option/selection_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -16,73 +13,48 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'widget.dart'; -class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { - SingleSelectTypeOption typeOption; - - SingleSelectTypeOptionBuilder(TypeOptionData typeOptionData) - : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => SingleSelectTypeOptionWidget(typeOption); -} - -class SingleSelectTypeOptionWidget extends TypeOptionWidget { - final SingleSelectTypeOption typeOption; - const SingleSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: OptionPannel(options: typeOption.options), - ); - } -} - -class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { - MultiSelectTypeOption typeOption; - - MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData) - : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption); -} - -class MultiSelectTypeOptionWidget extends TypeOptionWidget { - final MultiSelectTypeOption typeOption; - const MultiSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(), - child: OptionPannel(options: typeOption.options), - ); - } -} - class OptionPannel extends StatelessWidget { final List options; - const OptionPannel({required this.options, Key? key}) : super(key: key); + final VoidCallback beginEdit; + final Function(String optionName) createOptionCallback; + final Function(List) updateOptionsCallback; + const OptionPannel({ + required this.options, + required this.beginEdit, + required this.createOptionCallback, + required this.updateOptionsCallback, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => OptionPannelBloc(options: options), - child: BlocBuilder( + child: BlocConsumer( + listener: (context, state) { + if (state.isEditingOption) { + beginEdit(); + } + state.newOptionName.fold( + () => null, + (optionName) => createOptionCallback(optionName), + ); + }, builder: (context, state) { - List children = [const OptionTitle()]; - if (state.isAddingOption) { + List children = [ + const TypeOptionSeparator(), + const OptionTitle(), + ]; + if (state.isEditingOption) { children.add(const _AddOptionTextField()); } - if (state.options.isEmpty && !state.isAddingOption) { + if (state.options.isEmpty && !state.isEditingOption) { children.add(const _AddOptionButton()); } if (state.options.isNotEmpty) { - children.add(const _OptionList()); + children.add(_OptionList(key: ObjectKey(state.options))); } return Column(children: children); @@ -100,19 +72,27 @@ class OptionTitle extends StatelessWidget { final theme = context.watch(); return BlocBuilder( - buildWhen: (previous, current) => previous.options.length != current.options.length, builder: (context, state) { List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; - - if (state.options.isNotEmpty && state.isAddingOption == false) { - children.add(FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_field_addOption.tr(), fontSize: 12), - hoverColor: theme.hover, - onTap: () { - context.read().add(const OptionPannelEvent.beginAddingOption()); - }, - rightIcon: svg("grid/more", color: theme.iconColor), - )); + if (state.options.isNotEmpty) { + children.add(const Spacer()); + children.add( + SizedBox( + width: 100, + height: 26, + child: FlowyButton( + text: FlowyText.medium( + LocaleKeys.grid_field_addOption.tr(), + fontSize: 12, + textAlign: TextAlign.center, + ), + hoverColor: theme.hover, + onTap: () { + context.read().add(const OptionPannelEvent.beginAddingOption()); + }, + ), + ), + ); } return SizedBox( @@ -135,19 +115,16 @@ class _OptionList extends StatelessWidget { return _OptionItem(option: option); }).toList(); - return SizedBox( - width: 120, - child: ListView.separated( - shrinkWrap: true, - controller: ScrollController(), - separatorBuilder: (context, index) { - return VSpace(GridSize.typeOptionSeparatorHeight); - }, - itemCount: optionItems.length, - itemBuilder: (BuildContext context, int index) { - return optionItems[index]; - }, - ), + return ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: optionItems.length, + itemBuilder: (BuildContext context, int index) { + return optionItems[index]; + }, ); }, ); @@ -167,7 +144,7 @@ class _OptionItem extends StatelessWidget { text: FlowyText.medium(option.name, fontSize: 12), hoverColor: theme.hover, onTap: () {}, - rightIcon: svg("grid/more", color: theme.iconColor), + rightIcon: svg("grid/details", color: theme.iconColor), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart new file mode 100644 index 0000000000..6690729ff0 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart @@ -0,0 +1,55 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'option_pannel.dart'; + +class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { + final SingleSelectTypeOptionWidget _widget; + + SingleSelectTypeOptionBuilder( + String fieldId, + TypeOptionData typeOptionData, + TypeOptionOperationDelegate delegate, + ) : _widget = SingleSelectTypeOptionWidget( + fieldId, + SingleSelectTypeOption.fromBuffer(typeOptionData), + delegate, + ); + + @override + Widget? get customWidget => _widget; +} + +class SingleSelectTypeOptionWidget extends TypeOptionWidget { + final String fieldId; + final SingleSelectTypeOption typeOption; + final TypeOptionOperationDelegate delegate; + const SingleSelectTypeOptionWidget(this.fieldId, this.typeOption, this.delegate, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: typeOption, param2: fieldId), + child: BlocConsumer( + listener: (context, state) => delegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + builder: (context, state) { + return OptionPannel( + options: state.typeOption.options, + beginEdit: () { + delegate.hideOverlay(context); + }, + createOptionCallback: (name) { + context.read().add(SingleSelectTypeOptionEvent.createOption(name)); + }, + updateOptionsCallback: (options) { + context.read().add(SingleSelectTypeOptionEvent.updateOptions(options)); + }, + ); + }, + ), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart index f357c9afea..6f4e86a4e1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart @@ -21,6 +21,7 @@ class NameTextField extends StatefulWidget { class _NameTextFieldState extends State { late FocusNode _focusNode; + var isEdited = false; late TextEditingController _controller; @override @@ -35,31 +36,53 @@ class _NameTextFieldState extends State { @override Widget build(BuildContext context) { final theme = context.watch(); + return RoundedInputField( - controller: _controller, - focusNode: _focusNode, - height: 36, - style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500), - normalBorderColor: theme.shader4, - errorBorderColor: theme.red, - focusBorderColor: theme.main1, - cursorColor: theme.main1, - onChanged: (text) { - print(text); - }); + controller: _controller, + focusNode: _focusNode, + autoFocus: true, + height: 36, + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500), + normalBorderColor: theme.shader4, + focusBorderColor: theme.main1, + cursorColor: theme.main1, + onEditingComplete: () { + widget.onDone(_controller.text); + }, + ); } @override void dispose() { _focusNode.removeListener(notifyDidEndEditing); + _focusNode.dispose(); super.dispose(); } void notifyDidEndEditing() { if (_controller.text.isEmpty) { - // widget.onCanceled(); + if (isEdited) { + widget.onCanceled(); + } + isEdited = true; } else { widget.onDone(_controller.text); } } } + +class TypeOptionSeparator extends StatelessWidget { + const TypeOptionSeparator({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6), + child: Container( + color: theme.shader4, + height: 0.25, + ), + ); + } +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index 0bcd05f56e..13d02a0ea8 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -15,7 +15,7 @@ class FlowyButton extends StatelessWidget { Key? key, required this.text, this.onTap, - this.padding = const EdgeInsets.symmetric(horizontal: 3, vertical: 2), + this.padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2), this.leftIcon, this.rightIcon, this.hoverColor = Colors.transparent, @@ -44,12 +44,13 @@ class FlowyButton extends StatelessWidget { if (rightIcon != null) { children.add(SizedBox.fromSize(size: const Size.square(16), child: rightIcon!)); - children.add(const HSpace(6)); } return Padding( padding: padding, child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: children, ), ); diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart index b6bf1daf4b..0af5e4ec89 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart @@ -15,6 +15,7 @@ class RoundedInputField extends StatefulWidget { final String errorText; final TextStyle style; final ValueChanged? onChanged; + final VoidCallback? onEditingComplete; final String? initialValue; final EdgeInsets margin; final EdgeInsets padding; @@ -22,6 +23,7 @@ class RoundedInputField extends StatefulWidget { final double height; final FocusNode? focusNode; final TextEditingController? controller; + final bool autoFocus; const RoundedInputField({ Key? key, @@ -32,6 +34,7 @@ class RoundedInputField extends StatefulWidget { this.obscureIcon, this.obscureHideIcon, this.onChanged, + this.onEditingComplete, this.normalBorderColor = Colors.transparent, this.errorBorderColor = Colors.transparent, this.focusBorderColor, @@ -43,6 +46,7 @@ class RoundedInputField extends StatefulWidget { this.height = 48, this.focusNode, this.controller, + this.autoFocus = false, }) : super(key: key); @override @@ -78,6 +82,7 @@ class _RoundedInputFieldState extends State { controller: widget.controller, initialValue: widget.initialValue, focusNode: widget.focusNode, + autofocus: widget.autoFocus, onChanged: (value) { inputText = value; if (widget.onChanged != null) { @@ -85,6 +90,7 @@ class _RoundedInputFieldState extends State { } setState(() {}); }, + onEditingComplete: widget.onEditingComplete, cursorColor: widget.cursorColor, obscureText: obscuteText, style: widget.style, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 7f25329284..04098b288e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -137,6 +137,23 @@ class GridEventCreateEditFieldContext { } } +class GridEventCreateSelectOption { + CreateSelectOptionPayload request; + GridEventCreateSelectOption(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.CreateSelectOption.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(SelectOption.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateRow { CreateRowPayload request; GridEventCreateRow(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index b068956465..e2be9f11a2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -4,6 +4,7 @@ import 'package:flowy_sdk/log.dart'; // ignore: unnecessary_import import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event_map.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart index 307b9f86f2..9c4e31eeea 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -47,6 +47,7 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty'); static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty'); static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist'); + static const ErrorCode SelectOptionNameIsEmpty = ErrorCode._(442, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SelectOptionNameIsEmpty'); static const ErrorCode TypeOptionDataIsEmpty = ErrorCode._(450, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionDataIsEmpty'); static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData'); @@ -88,6 +89,7 @@ class ErrorCode extends $pb.ProtobufEnum { RowIdIsEmpty, FieldIdIsEmpty, FieldDoesNotExist, + SelectOptionNameIsEmpty, TypeOptionDataIsEmpty, InvalidData, ]; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart index 9345118baa..b3efa2c0ad 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -49,10 +49,11 @@ const ErrorCode$json = const { const {'1': 'RowIdIsEmpty', '2': 430}, const {'1': 'FieldIdIsEmpty', '2': 440}, const {'1': 'FieldDoesNotExist', '2': 441}, + const {'1': 'SelectOptionNameIsEmpty', '2': 442}, const {'1': 'TypeOptionDataIsEmpty', '2': 450}, const {'1': 'InvalidData', '2': 500}, ], }; /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM='); +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIcChdTZWxlY3RPcHRpb25OYW1lSXNFbXB0eRC6AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM='); 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 bd9afe2243..3dafd193b3 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 @@ -1536,3 +1536,50 @@ class QueryRowPayload extends $pb.GeneratedMessage { void clearRowId() => clearField(3); } +class CreateSelectOptionPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateSelectOptionPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'optionName') + ..hasRequiredFields = false + ; + + CreateSelectOptionPayload._() : super(); + factory CreateSelectOptionPayload({ + $core.String? optionName, + }) { + final _result = create(); + if (optionName != null) { + _result.optionName = optionName; + } + return _result; + } + factory CreateSelectOptionPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateSelectOptionPayload.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') + CreateSelectOptionPayload clone() => CreateSelectOptionPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CreateSelectOptionPayload copyWith(void Function(CreateSelectOptionPayload) updates) => super.copyWith((message) => updates(message as CreateSelectOptionPayload)) as CreateSelectOptionPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateSelectOptionPayload create() => CreateSelectOptionPayload._(); + CreateSelectOptionPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CreateSelectOptionPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateSelectOptionPayload? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get optionName => $_getSZ(0); + @$pb.TagNumber(1) + set optionName($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasOptionName() => $_has(0); + @$pb.TagNumber(1) + void clearOptionName() => clearField(1); +} + 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 0b900d46f9..3b7c58924e 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 @@ -302,3 +302,13 @@ const QueryRowPayload$json = const { /// Descriptor for `QueryRowPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List queryRowPayloadDescriptor = $convert.base64Decode('Cg9RdWVyeVJvd1BheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGJsb2NrX2lkGAIgASgJUgdibG9ja0lkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); +@$core.Deprecated('Use createSelectOptionPayloadDescriptor instead') +const CreateSelectOptionPayload$json = const { + '1': 'CreateSelectOptionPayload', + '2': const [ + const {'1': 'option_name', '3': 1, '4': 1, '5': 9, '10': 'optionName'}, + ], +}; + +/// Descriptor for `CreateSelectOptionPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEh8KC29wdGlvbl9uYW1lGAEgASgJUgpvcHRpb25OYW1l'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 46291923e0..25319128d8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -18,9 +18,10 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); static const GridEvent CreateEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); - static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); - static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); - static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); + static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption'); + static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); + static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); + static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); static const $core.List values = [ GetGridData, @@ -31,6 +32,7 @@ class GridEvent extends $pb.ProtobufEnum { DeleteField, DuplicateField, CreateEditFieldContext, + CreateSelectOption, CreateRow, GetRow, UpdateCell, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 278e0b14c3..747a591a02 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -20,11 +20,12 @@ const GridEvent$json = const { const {'1': 'DeleteField', '2': 13}, const {'1': 'DuplicateField', '2': 15}, const {'1': 'CreateEditFieldContext', '2': 16}, - const {'1': 'CreateRow', '2': 21}, - const {'1': 'GetRow', '2': 22}, - const {'1': 'UpdateCell', '2': 30}, + const {'1': 'CreateSelectOption', '2': 30}, + const {'1': 'CreateRow', '2': 50}, + const {'1': 'GetRow', '2': 51}, + const {'1': 'UpdateCell', '2': 70}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASDQoJQ3JlYXRlUm93EBUSCgoGR2V0Um93EBYSDgoKVXBkYXRlQ2VsbBAe'); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASFgoSQ3JlYXRlU2VsZWN0T3B0aW9uEB4SDQoJQ3JlYXRlUm93EDISCgoGR2V0Um93EDMSDgoKVXBkYXRlQ2VsbBBG'); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 97b91e5557..d29c2aec48 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,5 @@ use crate::manager::GridManager; -use crate::services::field::type_option_data_from_str; +use crate::services::field::{type_option_data_from_str, SelectOption}; use flowy_error::FlowyError; use flowy_grid_data_model::entities::*; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; @@ -88,6 +88,14 @@ pub(crate) async fn duplicate_field_handler( Ok(()) } +#[tracing::instrument(level = "debug", skip(data), err)] +pub(crate) async fn create_select_option_handler( + data: Data, +) -> DataResult { + let params: CreateSelectOptionParams = data.into_inner().try_into()?; + data_result(SelectOption::new(¶ms.option_name)) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn create_edit_field_context_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index efe5ddc094..966423c7c7 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -16,6 +16,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::DeleteField, delete_field_handler) .event(GridEvent::DuplicateField, duplicate_field_handler) .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler) + .event(GridEvent::CreateSelectOption, create_select_option_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) .event(GridEvent::UpdateCell, update_cell_handler); @@ -50,12 +51,15 @@ pub enum GridEvent { #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")] CreateEditFieldContext = 16, + #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] + CreateSelectOption = 30, + #[event(input = "CreateRowPayload", output = "Row")] - CreateRow = 21, + CreateRow = 50, #[event(input = "QueryRowPayload", output = "Row")] - GetRow = 22, + GetRow = 51, #[event(input = "CellMetaChangeset")] - UpdateCell = 30, + UpdateCell = 70, } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 13ee0705cc..2eab7357c5 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -33,9 +33,10 @@ pub enum GridEvent { DeleteField = 13, DuplicateField = 15, CreateEditFieldContext = 16, - CreateRow = 21, - GetRow = 22, - UpdateCell = 30, + CreateSelectOption = 30, + CreateRow = 50, + GetRow = 51, + UpdateCell = 70, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -53,9 +54,10 @@ impl ::protobuf::ProtobufEnum for GridEvent { 13 => ::std::option::Option::Some(GridEvent::DeleteField), 15 => ::std::option::Option::Some(GridEvent::DuplicateField), 16 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), - 21 => ::std::option::Option::Some(GridEvent::CreateRow), - 22 => ::std::option::Option::Some(GridEvent::GetRow), - 30 => ::std::option::Option::Some(GridEvent::UpdateCell), + 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption), + 50 => ::std::option::Option::Some(GridEvent::CreateRow), + 51 => ::std::option::Option::Some(GridEvent::GetRow), + 70 => ::std::option::Option::Some(GridEvent::UpdateCell), _ => ::std::option::Option::None } } @@ -70,6 +72,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::DeleteField, GridEvent::DuplicateField, GridEvent::CreateEditFieldContext, + GridEvent::CreateSelectOption, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, @@ -101,12 +104,13 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xcc\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xe4\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x1a\n\x16CreateE\ - ditFieldContext\x10\x10\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\ - \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\ + ditFieldContext\x10\x10\x12\x16\n\x12CreateSelectOption\x10\x1e\x12\r\n\ + \tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10Fb\x06p\ + roto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 327a1e3aee..ebc7ae6782 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -9,7 +9,8 @@ enum GridEvent { DeleteField = 13; DuplicateField = 15; CreateEditFieldContext = 16; - CreateRow = 21; - GetRow = 22; - UpdateCell = 30; + CreateSelectOption = 30; + CreateRow = 50; + GetRow = 51; + UpdateCell = 70; } diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 7c813bd1e0..3b0cf331ee 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -99,6 +99,8 @@ pub enum ErrorCode { FieldIdIsEmpty = 440, #[display(fmt = "Field doesn't exist")] FieldDoesNotExist = 441, + #[display(fmt = "The name of the option should not be empty")] + SelectOptionNameIsEmpty = 442, #[display(fmt = "Field's type option data should not be empty")] TypeOptionDataIsEmpty = 450, diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs index 8e6e1b9621..6e6db9139b 100644 --- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -62,6 +62,7 @@ pub enum ErrorCode { RowIdIsEmpty = 430, FieldIdIsEmpty = 440, FieldDoesNotExist = 441, + SelectOptionNameIsEmpty = 442, TypeOptionDataIsEmpty = 450, InvalidData = 500, } @@ -110,6 +111,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode { 430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty), 440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty), 441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist), + 442 => ::std::option::Option::Some(ErrorCode::SelectOptionNameIsEmpty), 450 => ::std::option::Option::Some(ErrorCode::TypeOptionDataIsEmpty), 500 => ::std::option::Option::Some(ErrorCode::InvalidData), _ => ::std::option::Option::None @@ -155,6 +157,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode { ErrorCode::RowIdIsEmpty, ErrorCode::FieldIdIsEmpty, ErrorCode::FieldDoesNotExist, + ErrorCode::SelectOptionNameIsEmpty, ErrorCode::TypeOptionDataIsEmpty, ErrorCode::InvalidData, ]; @@ -185,7 +188,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ncode.proto*\x80\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\ncode.proto*\x9e\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\ \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\ @@ -205,8 +208,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\ erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\ ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\ \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\ - \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1a\n\x15TypeOptionDataI\ - sEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\ + \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1c\n\x17SelectOptionNam\ + eIsEmpty\x10\xba\x03\x12\x1a\n\x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\ + \x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto index e01c42aa8b..d435d558dc 100644 --- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto +++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto @@ -38,6 +38,7 @@ enum ErrorCode { RowIdIsEmpty = 430; FieldIdIsEmpty = 440; FieldDoesNotExist = 441; + SelectOptionNameIsEmpty = 442; TypeOptionDataIsEmpty = 450; InvalidData = 500; } 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 dfd5dc397f..a85b8d382a 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -1,5 +1,5 @@ use crate::entities::{FieldMeta, FieldType, RowMeta}; -use crate::parser::NotEmptyUuid; +use crate::parser::{NotEmptyStr, NotEmptyUuid}; use flowy_derive::ProtoBuf; use flowy_error_code::ErrorCode; use std::collections::HashMap; @@ -494,3 +494,24 @@ impl TryInto for QueryRowPayload { }) } } + +#[derive(ProtoBuf, Default)] +pub struct CreateSelectOptionPayload { + #[pb(index = 1)] + pub option_name: String, +} + +pub struct CreateSelectOptionParams { + pub option_name: String, +} + +impl TryInto for CreateSelectOptionPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?; + Ok(CreateSelectOptionParams { + option_name: option_name.0, + }) + } +} diff --git a/shared-lib/flowy-grid-data-model/src/parser/mod.rs b/shared-lib/flowy-grid-data-model/src/parser/mod.rs index 7cb72eb859..3c43c76f39 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/mod.rs @@ -1,3 +1,3 @@ -mod id_parser; +mod str_parser; -pub use id_parser::*; +pub use str_parser::*; diff --git a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs b/shared-lib/flowy-grid-data-model/src/parser/str_parser.rs similarity index 54% rename from shared-lib/flowy-grid-data-model/src/parser/id_parser.rs rename to shared-lib/flowy-grid-data-model/src/parser/str_parser.rs index 5003ab2ce4..3e5e3c622b 100644 --- a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs +++ b/shared-lib/flowy-grid-data-model/src/parser/str_parser.rs @@ -19,3 +19,21 @@ impl AsRef for NotEmptyUuid { &self.0 } } + +#[derive(Debug)] +pub struct NotEmptyStr(pub String); + +impl NotEmptyStr { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err("Input string is empty".to_owned()); + } + Ok(Self(s)) + } +} + +impl AsRef for NotEmptyStr { + fn as_ref(&self) -> &str { + &self.0 + } +} 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 c18043184f..d55c5dac10 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 @@ -5258,6 +5258,165 @@ impl ::protobuf::reflect::ProtobufValue for QueryRowPayload { } } +#[derive(PartialEq,Clone,Default)] +pub struct CreateSelectOptionPayload { + // message fields + pub option_name: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CreateSelectOptionPayload { + fn default() -> &'a CreateSelectOptionPayload { + ::default_instance() + } +} + +impl CreateSelectOptionPayload { + pub fn new() -> CreateSelectOptionPayload { + ::std::default::Default::default() + } + + // string option_name = 1; + + + pub fn get_option_name(&self) -> &str { + &self.option_name + } + pub fn clear_option_name(&mut self) { + self.option_name.clear(); + } + + // Param is passed by value, moved + pub fn set_option_name(&mut self, v: ::std::string::String) { + self.option_name = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_option_name(&mut self) -> &mut ::std::string::String { + &mut self.option_name + } + + // Take field + pub fn take_option_name(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.option_name, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for CreateSelectOptionPayload { + 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.option_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.option_name.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.option_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.option_name.is_empty() { + os.write_string(1, &self.option_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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> CreateSelectOptionPayload { + CreateSelectOptionPayload::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>( + "option_name", + |m: &CreateSelectOptionPayload| { &m.option_name }, + |m: &mut CreateSelectOptionPayload| { &mut m.option_name }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateSelectOptionPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CreateSelectOptionPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateSelectOptionPayload::new) + } +} + +impl ::protobuf::Clear for CreateSelectOptionPayload { + fn clear(&mut self) { + self.option_name.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CreateSelectOptionPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CreateSelectOptionPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\ngrid.proto\x1a\nmeta.proto\"z\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\ \x01(\tR\x02id\x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrd\ @@ -5311,7 +5470,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ \x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ - kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowIdb\x06proto3\ + kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"<\n\x19CreateSelec\ + tOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionNameb\ + \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 3a74e23026..5c07b98d30 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 @@ -103,3 +103,6 @@ message QueryRowPayload { string block_id = 2; string row_id = 3; } +message CreateSelectOptionPayload { + string option_name = 1; +} From 547b8ec29c97dd0295337530b47e1619a8eb00bd Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 30 Mar 2022 22:51:52 +0800 Subject: [PATCH 18/47] fix: fix bugs --- .../app_flowy/assets/translations/en.json | 4 +- .../field/type_option/option_pannel_bloc.dart | 12 ++ .../field/type_option/single_select_bloc.dart | 52 +++++- .../widgets/header/field_tyep_switcher.dart | 62 ++++--- .../src/widgets/header/field_type_list.dart | 16 -- .../src/widgets/header/type_option/date.dart | 35 ++-- .../type_option/edit_option_pannel.dart | 155 ++++++++++++++++-- .../header/type_option/multi_select.dart | 14 +- .../widgets/header/type_option/number.dart | 28 ++-- .../header/type_option/option_pannel.dart | 67 ++++++-- .../header/type_option/single_select.dart | 36 ++-- 11 files changed, 373 insertions(+), 108 deletions(-) diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index b751bb6d3e..4bb37ea078 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -177,7 +177,9 @@ "limeColor": "Lime", "greenColor": "Green", "aquaColor": "Aqua", - "blueColor": "Blue" + "blueColor": "Blue", + "deleteTag": "Delete tag", + "colorPannelTitle": "Colors" } } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart index 445db413c0..715cde72d7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart @@ -19,6 +19,12 @@ class OptionPannelBloc extends Bloc { endAddingOption: (_EndAddingOption value) { emit(state.copyWith(isEditingOption: false, newOptionName: none())); }, + updateOption: (_UpdateOption value) { + emit(state.copyWith(updateOption: Some(value.option))); + }, + deleteOption: (_DeleteOption value) { + emit(state.copyWith(deleteOption: Some(value.option))); + }, ); }, ); @@ -35,6 +41,8 @@ class OptionPannelEvent with _$OptionPannelEvent { const factory OptionPannelEvent.createOption(String optionName) = _CreateOption; const factory OptionPannelEvent.beginAddingOption() = _BeginAddingOption; const factory OptionPannelEvent.endAddingOption() = _EndAddingOption; + const factory OptionPannelEvent.updateOption(SelectOption option) = _UpdateOption; + const factory OptionPannelEvent.deleteOption(SelectOption option) = _DeleteOption; } @freezed @@ -43,11 +51,15 @@ class OptionPannelState with _$OptionPannelState { required List options, required bool isEditingOption, required Option newOptionName, + required Option updateOption, + required Option deleteOption, }) = _OptionPannelState; factory OptionPannelState.initial(List options) => OptionPannelState( options: options, isEditingOption: false, newOptionName: none(), + updateOption: none(), + deleteOption: none(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart index 07a26439f3..03053b2dbb 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart @@ -3,7 +3,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - +import 'package:protobuf/protobuf.dart'; import 'type_option_service.dart'; part 'single_select_bloc.freezed.dart'; @@ -11,9 +11,13 @@ part 'single_select_bloc.freezed.dart'; class SingleSelectTypeOptionBloc extends Bloc { final TypeOptionService service; - SingleSelectTypeOptionBloc(SingleSelectTypeOption typeOption, String fieldId) - : service = TypeOptionService(fieldId: fieldId), - super(SingleSelectTypeOptionState.initial(typeOption)) { + SingleSelectTypeOptionBloc( + SingleSelectTypeOption typeOption, + String fieldId, + ) : service = TypeOptionService(fieldId: fieldId), + super( + SingleSelectTypeOptionState.initial(typeOption), + ) { on( (event, emit) async { await event.map( @@ -21,13 +25,17 @@ class SingleSelectTypeOptionBloc extends Bloc Log.error(err), ); }, - updateOptions: (_UpdateOptions value) async {}, + updateOption: (_UpdateOption value) async { + emit(state.copyWith(typeOption: _updateOption(value.option))); + }, + deleteOption: (_DeleteOption value) { + emit(state.copyWith(typeOption: _deleteOption(value.option))); + }, ); }, ); @@ -37,12 +45,40 @@ class SingleSelectTypeOptionBloc extends Bloc close() async { return super.close(); } + + SingleSelectTypeOption _insertOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.options.insert(0, option); + }); + } + + SingleSelectTypeOption _updateOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options[index] = option; + } + }); + } + + SingleSelectTypeOption _deleteOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options.removeAt(index); + } + }); + } } @freezed class SingleSelectTypeOptionEvent with _$SingleSelectTypeOptionEvent { const factory SingleSelectTypeOptionEvent.createOption(String optionName) = _CreateOption; - const factory SingleSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions; + const factory SingleSelectTypeOptionEvent.updateOption(SelectOption option) = _UpdateOption; + const factory SingleSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption; } @freezed diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index 1a418cf543..ce34097118 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -79,7 +79,7 @@ class _FieldTypeSwitcherState extends State { final list = FieldTypeList(onSelectField: (fieldType) { context.read().add(FieldTypeSwitchEvent.toFieldType(fieldType)); }); - _showOverlay(context, FieldTypeList.identifier(), list); + _showOverlay(context, list); }, leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), rightIcon: svg("grid/more", color: theme.iconColor), @@ -92,18 +92,27 @@ class _FieldTypeSwitcherState extends State { required Field field, required TypeOptionData data, }) { - final delegate = TypeOptionOperationDelegate( - didUpdateTypeOptionData: (data) { - context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data)); - }, - requireToShowOverlay: _showOverlay, + final overlayDelegate = TypeOptionOverlayDelegate( + showOverlay: _showOverlay, hideOverlay: _hideOverlay, ); - final builder = _makeTypeOptionBuild(field: field, data: data, delegate: delegate); + + final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { + context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data)); + }); + + final builder = _makeTypeOptionBuild( + field: field, + data: data, + overlayDelegate: overlayDelegate, + dataDelegate: dataDelegate, + ); + return builder.customWidget; } - void _showOverlay(BuildContext context, String identifier, Widget child) { + void _showOverlay(BuildContext context, Widget child, {VoidCallback? onRemoved}) { + final identifier = child.toString(); if (currentOverlayIdentifier != null) { FlowyOverlay.of(context).remove(currentOverlayIdentifier!); } @@ -112,7 +121,7 @@ class _FieldTypeSwitcherState extends State { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: child, - constraints: BoxConstraints.loose(const Size(240, 400)), + constraints: BoxConstraints.loose(const Size(340, 400)), ), identifier: identifier, anchorContext: context, @@ -136,19 +145,20 @@ abstract class TypeOptionBuilder { TypeOptionBuilder _makeTypeOptionBuild({ required Field field, required TypeOptionData data, - required TypeOptionOperationDelegate delegate, + required TypeOptionOverlayDelegate overlayDelegate, + required TypeOptionDataDelegate dataDelegate, }) { switch (field.fieldType) { case FieldType.Checkbox: return CheckboxTypeOptionBuilder(data); case FieldType.DateTime: - return DateTypeOptionBuilder(data, delegate); + return DateTypeOptionBuilder(data, overlayDelegate, dataDelegate); case FieldType.SingleSelect: - return SingleSelectTypeOptionBuilder(field.id, data, delegate); + return SingleSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate); case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder(data, delegate); + return MultiSelectTypeOptionBuilder(data, overlayDelegate); case FieldType.Number: - return NumberTypeOptionBuilder(data, delegate); + return NumberTypeOptionBuilder(data, overlayDelegate, dataDelegate); case FieldType.RichText: return RichTextTypeOptionBuilder(data); @@ -163,20 +173,30 @@ abstract class TypeOptionWidget extends StatelessWidget { typedef TypeOptionData = Uint8List; typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData); -typedef ShowOverlayCallback = void Function(BuildContext anchorContext, String overlayIdentifier, Widget child); +typedef ShowOverlayCallback = void Function( + BuildContext anchorContext, + Widget child, { + VoidCallback? onRemoved, +}); typedef HideOverlayCallback = void Function(BuildContext anchorContext); -class TypeOptionOperationDelegate { - TypeOptionDataCallback didUpdateTypeOptionData; - ShowOverlayCallback requireToShowOverlay; +class TypeOptionOverlayDelegate { + ShowOverlayCallback showOverlay; HideOverlayCallback hideOverlay; - TypeOptionOperationDelegate({ - required this.didUpdateTypeOptionData, - required this.requireToShowOverlay, + TypeOptionOverlayDelegate({ + required this.showOverlay, required this.hideOverlay, }); } +class TypeOptionDataDelegate { + TypeOptionDataCallback didUpdateTypeOptionData; + + TypeOptionDataDelegate({ + required this.didUpdateTypeOptionData, + }); +} + class RichTextTypeOptionBuilder extends TypeOptionBuilder { RichTextTypeOption typeOption; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index 0019ffa979..4511a84a1f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -17,22 +17,6 @@ class FieldTypeList extends StatelessWidget { final SelectFieldCallback onSelectField; const FieldTypeList({required this.onSelectField, Key? key}) : super(key: key); - static void show(BuildContext context, SelectFieldCallback onSelectField) { - final list = FieldTypeList(onSelectField: onSelectField); - FieldTypeList.hide(context); - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: list, - constraints: BoxConstraints.loose(const Size(140, 300)), - ), - identifier: FieldTypeList.identifier(), - anchorContext: context, - anchorDirection: AnchorDirection.leftWithCenterAligned, - style: FlowyOverlayStyle(blur: false), - anchorOffset: const Offset(-20, 0), - ); - } - static void hide(BuildContext context) { FlowyOverlay.of(context).remove(FieldTypeList.identifier()); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 493ab0e02e..581a3934e7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -15,30 +15,39 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class DateTypeOptionBuilder extends TypeOptionBuilder { - DateTypeOption typeOption; - TypeOptionOperationDelegate delegate; + final DateTypeOptionWidget _widget; - DateTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate) - : typeOption = DateTypeOption.fromBuffer(typeOptionData); + DateTypeOptionBuilder( + TypeOptionData typeOptionData, + TypeOptionOverlayDelegate overlayDelegate, + TypeOptionDataDelegate dataDelegate, + ) : _widget = DateTypeOptionWidget( + typeOption: DateTypeOption.fromBuffer(typeOptionData), + dataDelegate: dataDelegate, + overlayDelegate: overlayDelegate, + ); @override - Widget? get customWidget => DateTypeOptionWidget( - typeOption: typeOption, - operationDelegate: delegate, - ); + Widget? get customWidget => _widget; } class DateTypeOptionWidget extends TypeOptionWidget { final DateTypeOption typeOption; - final TypeOptionOperationDelegate operationDelegate; - const DateTypeOptionWidget({required this.typeOption, required this.operationDelegate, Key? key}) : super(key: key); + final TypeOptionOverlayDelegate overlayDelegate; + final TypeOptionDataDelegate dataDelegate; + const DateTypeOptionWidget({ + required this.typeOption, + required this.dataDelegate, + required this.overlayDelegate, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(param1: typeOption), child: BlocConsumer( - listener: (context, state) => operationDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return Column(children: [ _dateFormatButton(context), @@ -61,7 +70,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { final list = DateFormatList(onSelected: (format) { context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); }); - operationDelegate.requireToShowOverlay(context, list.identifier(), list); + overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), ), @@ -80,7 +89,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { final list = TimeFormatList(onSelected: (format) { context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); }); - operationDelegate.requireToShowOverlay(context, list.identifier(), list); + overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index 31f9570602..175f830657 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,18 +1,151 @@ +import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +class EditSelectOptionPannel extends StatelessWidget { + final SelectOption option; + final VoidCallback onDeleted; + final Function(SelectOption) onUpdated; + const EditSelectOptionPannel({ + required this.option, + required this.onDeleted, + required this.onUpdated, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => EditOptionBloc(option: option), + child: MultiBlocListener( + listeners: [ + BlocListener( + listenWhen: (p, c) => p.deleted != c.deleted, + listener: (context, state) { + state.deleted.fold(() => null, (_) => onDeleted()); + }, + ), + BlocListener( + listenWhen: (p, c) => p.option != c.option, + listener: (context, state) { + onUpdated(state.option); + }, + ), + ], + child: BlocBuilder( + builder: (context, state) { + List slivers = [ + SliverToBoxAdapter(child: _OptionNameTextField(state.option.name)), + const SliverToBoxAdapter(child: VSpace(10)), + const SliverToBoxAdapter(child: _DeleteTag()), + const SliverToBoxAdapter(child: TypeOptionSeparator()), + const SliverToBoxAdapter(child: SelectOptionColorList()), + ]; + + return CustomScrollView( + slivers: slivers, + controller: ScrollController(), + physics: StyledScrollPhysics(), + ); + }, + ), + ), + ); + } +} + +class _DeleteTag extends StatelessWidget { + const _DeleteTag({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr(), fontSize: 12), + hoverColor: theme.hover, + leftIcon: svg("grid/delete", color: theme.iconColor), + onTap: () { + context.read().add(const EditOptionEvent.delete()); + }, + ), + ); + } +} + +class _OptionNameTextField extends StatelessWidget { + final String name; + const _OptionNameTextField(this.name, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return NameTextField( + name: name, + onCanceled: () {}, + onDone: (optionName) { + context.read().add(EditOptionEvent.updateName(optionName)); + }, + ); + } +} + class SelectOptionColorList extends StatelessWidget { const SelectOptionColorList({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return Container(); + final optionItems = SelectOptionColor.values.map((option) { + // Color color = option.color(); + // var hex = option.color.value.toRadixString(16); + // if (hex.startsWith('ff')) { + // hex = hex.substring(2); + // } + // hex = '#$hex'; + + return _SelectOptionColorItem(option: option, isSelected: true); + }).toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: GridSize.typeOptionContentInsets, + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyText.medium( + LocaleKeys.grid_selectOption_colorPannelTitle.tr(), + fontSize: 12, + textAlign: TextAlign.left, + ), + ), + ), + ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: optionItems.length, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return optionItems[index]; + }, + ), + ], + ); } } @@ -24,12 +157,12 @@ class _SelectOptionColorItem extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); - Widget? checkmark; if (isSelected) { checkmark = svg("grid/details", color: theme.iconColor); } + final String hex = '#${option.color(context).value.toRadixString(16)}'; final colorIcon = SizedBox.square( dimension: 16, child: Container( @@ -40,15 +173,17 @@ class _SelectOptionColorItem extends StatelessWidget { ), ); - return FlowyButton( - text: FlowyText.medium( - option.name(), - fontSize: 12, + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(option.name(), fontSize: 12), + hoverColor: theme.hover, + leftIcon: colorIcon, + rightIcon: checkmark, + onTap: () { + context.read().add(EditOptionEvent.updateColor(hex)); + }, ), - hoverColor: theme.hover, - leftIcon: colorIcon, - rightIcon: checkmark, - onTap: () {}, ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index 4a3694b5fc..43cf2597fa 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -9,7 +9,7 @@ import 'option_pannel.dart'; class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { MultiSelectTypeOption typeOption; - TypeOptionOperationDelegate delegate; + TypeOptionOverlayDelegate delegate; MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate) : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); @@ -20,8 +20,8 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { class MultiSelectTypeOptionWidget extends TypeOptionWidget { final MultiSelectTypeOption typeOption; - final TypeOptionOperationDelegate delegate; - const MultiSelectTypeOptionWidget(this.typeOption, this.delegate, {Key? key}) : super(key: key); + final TypeOptionOverlayDelegate overlayDelegate; + const MultiSelectTypeOptionWidget(this.typeOption, this.overlayDelegate, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -32,14 +32,14 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { return OptionPannel( options: state.typeOption.options, beginEdit: () { - delegate.hideOverlay(context); + overlayDelegate.hideOverlay(context); }, createOptionCallback: (name) { context.read().add(MultiSelectTypeOptionEvent.createOption(name)); }, - updateOptionsCallback: (options) { - context.read().add(MultiSelectTypeOptionEvent.updateOptions(options)); - }, + updateOptionCallback: (updateOption) {}, + deleteOptionCallback: (deleteOption) {}, + overlayDelegate: overlayDelegate, ); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index 57a8254f2e..97dffd17e1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -15,25 +15,29 @@ import 'package:easy_localization/easy_localization.dart' hide NumberFormat; import 'package:app_flowy/generated/locale_keys.g.dart'; class NumberTypeOptionBuilder extends TypeOptionBuilder { - NumberTypeOption typeOption; - TypeOptionOperationDelegate delegate; + final NumberTypeOptionWidget _widget; NumberTypeOptionBuilder( TypeOptionData typeOptionData, - this.delegate, - ) : typeOption = NumberTypeOption.fromBuffer(typeOptionData); + TypeOptionOverlayDelegate overlayDelegate, + TypeOptionDataDelegate dataDelegate, + ) : _widget = NumberTypeOptionWidget( + typeOption: NumberTypeOption.fromBuffer(typeOptionData), + dataDelegate: dataDelegate, + overlayDelegate: overlayDelegate, + ); @override - Widget? get customWidget => NumberTypeOptionWidget( - typeOption: typeOption, - operationDelegate: delegate, - ); + Widget? get customWidget => _widget; } class NumberTypeOptionWidget extends TypeOptionWidget { - final TypeOptionOperationDelegate operationDelegate; + final TypeOptionDataDelegate dataDelegate; + final TypeOptionOverlayDelegate overlayDelegate; final NumberTypeOption typeOption; - const NumberTypeOptionWidget({required this.typeOption, required this.operationDelegate, Key? key}) : super(key: key); + const NumberTypeOptionWidget( + {required this.typeOption, required this.dataDelegate, required this.overlayDelegate, Key? key}) + : super(key: key); @override Widget build(BuildContext context) { @@ -43,7 +47,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { child: SizedBox( height: GridSize.typeOptionItemHeight, child: BlocConsumer( - listener: (context, state) => operationDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return FlowyButton( text: FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr(), fontSize: 12), @@ -53,7 +57,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { final list = NumberFormatList(onSelected: (format) { context.read().add(NumberTypeOptionEvent.didSelectFormat(format)); }); - operationDelegate.requireToShowOverlay(context, list.identifier(), list); + overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart index 736d03d96d..2c4a1b5e4a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -11,18 +12,24 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'edit_option_pannel.dart'; import 'widget.dart'; class OptionPannel extends StatelessWidget { final List options; final VoidCallback beginEdit; final Function(String optionName) createOptionCallback; - final Function(List) updateOptionsCallback; + final Function(SelectOption) updateOptionCallback; + final Function(SelectOption) deleteOptionCallback; + final TypeOptionOverlayDelegate overlayDelegate; + const OptionPannel({ required this.options, required this.beginEdit, required this.createOptionCallback, - required this.updateOptionsCallback, + required this.updateOptionCallback, + required this.deleteOptionCallback, + required this.overlayDelegate, Key? key, }) : super(key: key); @@ -39,6 +46,16 @@ class OptionPannel extends StatelessWidget { () => null, (optionName) => createOptionCallback(optionName), ); + + state.updateOption.fold( + () => null, + (updateOption) => updateOptionCallback(updateOption), + ); + + state.deleteOption.fold( + () => null, + (deleteOption) => deleteOptionCallback(deleteOption), + ); }, builder: (context, state) { List children = [ @@ -46,7 +63,7 @@ class OptionPannel extends StatelessWidget { const OptionTitle(), ]; if (state.isEditingOption) { - children.add(const _AddOptionTextField()); + children.add(const _OptionNameTextField()); } if (state.options.isEmpty && !state.isEditingOption) { @@ -54,7 +71,7 @@ class OptionPannel extends StatelessWidget { } if (state.options.isNotEmpty) { - children.add(_OptionList(key: ObjectKey(state.options))); + children.add(_OptionList(overlayDelegate)); } return Column(children: children); @@ -105,14 +122,18 @@ class OptionTitle extends StatelessWidget { } class _OptionList extends StatelessWidget { - const _OptionList({Key? key}) : super(key: key); + final TypeOptionOverlayDelegate delegate; + const _OptionList(this.delegate, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocBuilder( + buildWhen: (previous, current) { + return previous.options != current.options; + }, builder: (context, state) { final optionItems = state.options.map((option) { - return _OptionItem(option: option); + return _makeOptionItem(context, option); }).toList(); return ListView.separated( @@ -129,11 +150,37 @@ class _OptionList extends StatelessWidget { }, ); } + + _OptionItem _makeOptionItem(BuildContext context, SelectOption option) { + return _OptionItem( + option: option, + onEdited: (option) { + final pannel = EditSelectOptionPannel( + option: option, + onDeleted: () { + delegate.hideOverlay(context); + context.read().add(OptionPannelEvent.deleteOption(option)); + }, + onUpdated: (updatedOption) { + delegate.hideOverlay(context); + context.read().add(OptionPannelEvent.updateOption(updatedOption)); + }, + key: ValueKey(option.id), + ); + delegate.showOverlay(context, pannel); + }, + ); + } } class _OptionItem extends StatelessWidget { final SelectOption option; - const _OptionItem({required this.option, Key? key}) : super(key: key); + final Function(SelectOption) onEdited; + const _OptionItem({ + required this.option, + required this.onEdited, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -143,7 +190,7 @@ class _OptionItem extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(option.name, fontSize: 12), hoverColor: theme.hover, - onTap: () {}, + onTap: () => onEdited(option), rightIcon: svg("grid/details", color: theme.iconColor), ), ); @@ -170,8 +217,8 @@ class _AddOptionButton extends StatelessWidget { } } -class _AddOptionTextField extends StatelessWidget { - const _AddOptionTextField({Key? key}) : super(key: key); +class _OptionNameTextField extends StatelessWidget { + const _OptionNameTextField({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart index 6690729ff0..76573ef945 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart @@ -12,11 +12,13 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { SingleSelectTypeOptionBuilder( String fieldId, TypeOptionData typeOptionData, - TypeOptionOperationDelegate delegate, + TypeOptionOverlayDelegate overlayDelegate, + TypeOptionDataDelegate dataDelegate, ) : _widget = SingleSelectTypeOptionWidget( - fieldId, - SingleSelectTypeOption.fromBuffer(typeOptionData), - delegate, + fieldId: fieldId, + typeOption: SingleSelectTypeOption.fromBuffer(typeOptionData), + dataDelegate: dataDelegate, + overlayDelegate: overlayDelegate, ); @override @@ -26,27 +28,41 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { class SingleSelectTypeOptionWidget extends TypeOptionWidget { final String fieldId; final SingleSelectTypeOption typeOption; - final TypeOptionOperationDelegate delegate; - const SingleSelectTypeOptionWidget(this.fieldId, this.typeOption, this.delegate, {Key? key}) : super(key: key); + final TypeOptionOverlayDelegate overlayDelegate; + final TypeOptionDataDelegate dataDelegate; + const SingleSelectTypeOptionWidget({ + required this.fieldId, + required this.typeOption, + required this.dataDelegate, + required this.overlayDelegate, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt(param1: typeOption, param2: fieldId), child: BlocConsumer( - listener: (context, state) => delegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + listener: (context, state) { + dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); + }, builder: (context, state) { return OptionPannel( options: state.typeOption.options, beginEdit: () { - delegate.hideOverlay(context); + overlayDelegate.hideOverlay(context); }, createOptionCallback: (name) { context.read().add(SingleSelectTypeOptionEvent.createOption(name)); }, - updateOptionsCallback: (options) { - context.read().add(SingleSelectTypeOptionEvent.updateOptions(options)); + updateOptionCallback: (updateOption) { + context.read().add(SingleSelectTypeOptionEvent.updateOption(updateOption)); }, + deleteOptionCallback: (deleteOption) { + context.read().add(SingleSelectTypeOptionEvent.deleteOption(deleteOption)); + }, + overlayDelegate: overlayDelegate, + key: ValueKey(state.typeOption.hashCode), ); }, ), From 4b27fef76e3ddcfd48c1e6ca2101323f2a46b557 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 31 Mar 2022 14:43:31 +0800 Subject: [PATCH 19/47] chore: select option color --- .../field/type_option/edit_option_bloc.dart | 66 ++++++++++ .../menu/app/header/right_click_action.dart | 2 +- .../menu/app/section/disclosure_action.dart | 4 +- .../presentation/plugins/doc/document.dart | 2 +- .../widgets/header/create_field_pannel.dart | 3 + .../type_option/edit_option_pannel.dart | 94 ++++++-------- .../widgets/float_bubble/question_bubble.dart | 2 +- .../lib/src/flowy_overlay/flowy_overlay.dart | 50 ++++++-- .../flowy-grid/selection_type_option.pb.dart | 12 +- .../selection_type_option.pbenum.dart | 33 +++++ .../selection_type_option.pbjson.dart | 22 +++- frontend/rust-lib/Cargo.lock | 1 + frontend/rust-lib/flowy-grid/Cargo.toml | 1 + .../protobuf/model/selection_type_option.rs | 120 ++++++++++++++---- .../proto/selection_type_option.proto | 13 +- .../type_options/selection_type_option.rs | 26 +++- 16 files changed, 343 insertions(+), 108 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart new file mode 100644 index 0000000000..ccd0c47bab --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart @@ -0,0 +1,66 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:protobuf/protobuf.dart'; +import 'package:dartz/dartz.dart'; +part 'edit_option_bloc.freezed.dart'; + +class EditOptionBloc extends Bloc { + EditOptionBloc({required SelectOption option}) : super(EditOptionState.initial(option)) { + on( + (event, emit) async { + event.map( + updateName: (_UpdateName value) { + emit(state.copyWith(option: _updateName(value.name))); + }, + updateColor: (_UpdateColor value) { + emit(state.copyWith(option: _updateColor(value.color))); + }, + delete: (_Delete value) { + emit(state.copyWith(deleted: const Some(true))); + }, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } + + SelectOption _updateColor(SelectOptionColor color) { + state.option.freeze(); + return state.option.rebuild((option) { + option.color = color; + }); + } + + SelectOption _updateName(String name) { + state.option.freeze(); + return state.option.rebuild((option) { + option.name = name; + }); + } +} + +@freezed +class EditOptionEvent with _$EditOptionEvent { + const factory EditOptionEvent.updateName(String name) = _UpdateName; + const factory EditOptionEvent.updateColor(SelectOptionColor color) = _UpdateColor; + const factory EditOptionEvent.delete() = _Delete; +} + +@freezed +class EditOptionState with _$EditOptionState { + const factory EditOptionState({ + required SelectOption option, + required Option deleted, + }) = _EditOptionState; + + factory EditOptionState.initial(SelectOption option) => EditOptionState( + option: option, + deleted: none(), + ); +} diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart index 8938443236..be6a97dbfb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/right_click_action.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'header.dart'; -class AppDisclosureActionSheet with ActionList implements FlowyOverlayDelegate { +class AppDisclosureActionSheet with ActionList, FlowyOverlayDelegate { final Function(dartz.Option) onSelected; final _items = AppDisclosureAction.values.map((action) => DisclosureActionWrapper(action)).toList(); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index cf66476ab8..a706ae5019 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -11,9 +11,7 @@ import 'item.dart'; // [[Widget: LifeCycle]] // https://flutterbyexample.com/lesson/stateful-widget-lifecycle -class ViewDisclosureButton extends StatelessWidget - with ActionList - implements FlowyOverlayDelegate { +class ViewDisclosureButton extends StatelessWidget with ActionList, FlowyOverlayDelegate { final Function() onTap; final Function(dartz.Option) onSelected; final _items = ViewDisclosureAction.values.map((action) => ViewDisclosureActionWrapper(action)).toList(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart index 83e577ec10..b0727bb73a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart @@ -195,7 +195,7 @@ class DocumentShareButton extends StatelessWidget { } } -class ShareActions with ActionList implements FlowyOverlayDelegate { +class ShareActions with ActionList, FlowyOverlayDelegate { final Function(dartz.Option) onSelected; final _items = ShareAction.values.map((action) => ShareActionWrapper(action)).toList(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart index 8b2b74d9ae..a530737e28 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart @@ -38,6 +38,9 @@ class CreateFieldPannel extends FlowyOverlayDelegate { void didRemove() { _createFieldBloc.add(const CreateFieldEvent.done()); } + + @override + bool asBarrier() => true; } class _CreateFieldPannelWidget extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index 175f830657..e7999b7e4c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -50,13 +50,16 @@ class EditSelectOptionPannel extends StatelessWidget { const SliverToBoxAdapter(child: VSpace(10)), const SliverToBoxAdapter(child: _DeleteTag()), const SliverToBoxAdapter(child: TypeOptionSeparator()), - const SliverToBoxAdapter(child: SelectOptionColorList()), + SliverToBoxAdapter(child: SelectOptionColorList(selectedColor: state.option.color)), ]; - return CustomScrollView( - slivers: slivers, - controller: ScrollController(), - physics: StyledScrollPhysics(), + return SizedBox( + width: 160, + child: CustomScrollView( + slivers: slivers, + controller: ScrollController(), + physics: StyledScrollPhysics(), + ), ); }, ), @@ -102,19 +105,13 @@ class _OptionNameTextField extends StatelessWidget { } class SelectOptionColorList extends StatelessWidget { - const SelectOptionColorList({Key? key}) : super(key: key); + final SelectOptionColor selectedColor; + const SelectOptionColorList({required this.selectedColor, Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final optionItems = SelectOptionColor.values.map((option) { - // Color color = option.color(); - // var hex = option.color.value.toRadixString(16); - // if (hex.startsWith('ff')) { - // hex = hex.substring(2); - // } - // hex = '#$hex'; - - return _SelectOptionColorItem(option: option, isSelected: true); + final optionItems = SelectOptionColor.values.map((color) { + return _SelectOptionColorItem(color: color, isSelected: selectedColor == color); }).toList(); return Column( @@ -150,24 +147,23 @@ class SelectOptionColorList extends StatelessWidget { } class _SelectOptionColorItem extends StatelessWidget { - final SelectOptionColor option; + final SelectOptionColor color; final bool isSelected; - const _SelectOptionColorItem({required this.option, required this.isSelected, Key? key}) : super(key: key); + const _SelectOptionColorItem({required this.color, required this.isSelected, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); Widget? checkmark; if (isSelected) { - checkmark = svg("grid/details", color: theme.iconColor); + checkmark = svg("grid/checkmark"); } - final String hex = '#${option.color(context).value.toRadixString(16)}'; final colorIcon = SizedBox.square( dimension: 16, child: Container( decoration: BoxDecoration( - color: option.color(context), + color: color.color(context), shape: BoxShape.circle, ), ), @@ -176,75 +172,67 @@ class _SelectOptionColorItem extends StatelessWidget { return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( - text: FlowyText.medium(option.name(), fontSize: 12), + text: FlowyText.medium(color.optionName(), fontSize: 12), hoverColor: theme.hover, leftIcon: colorIcon, rightIcon: checkmark, onTap: () { - context.read().add(EditOptionEvent.updateColor(hex)); + context.read().add(EditOptionEvent.updateColor(color)); }, ), ); } } -enum SelectOptionColor { - purple, - pink, - lightPink, - orange, - yellow, - lime, - green, - aqua, - blue, -} - extension SelectOptionColorExtension on SelectOptionColor { Color color(BuildContext context) { final theme = context.watch(); switch (this) { - case SelectOptionColor.purple: + case SelectOptionColor.Purple: return theme.tint1; - case SelectOptionColor.pink: + case SelectOptionColor.Pink: return theme.tint2; - case SelectOptionColor.lightPink: + case SelectOptionColor.LightPink: return theme.tint3; - case SelectOptionColor.orange: + case SelectOptionColor.Orange: return theme.tint4; - case SelectOptionColor.yellow: + case SelectOptionColor.Yellow: return theme.tint5; - case SelectOptionColor.lime: + case SelectOptionColor.Lime: return theme.tint6; - case SelectOptionColor.green: + case SelectOptionColor.Green: return theme.tint7; - case SelectOptionColor.aqua: + case SelectOptionColor.Aqua: return theme.tint8; - case SelectOptionColor.blue: + case SelectOptionColor.Blue: return theme.tint9; + default: + throw ArgumentError; } } - String name() { + String optionName() { switch (this) { - case SelectOptionColor.purple: + case SelectOptionColor.Purple: return LocaleKeys.grid_selectOption_purpleColor.tr(); - case SelectOptionColor.pink: + case SelectOptionColor.Pink: return LocaleKeys.grid_selectOption_pinkColor.tr(); - case SelectOptionColor.lightPink: + case SelectOptionColor.LightPink: return LocaleKeys.grid_selectOption_lightPinkColor.tr(); - case SelectOptionColor.orange: + case SelectOptionColor.Orange: return LocaleKeys.grid_selectOption_orangeColor.tr(); - case SelectOptionColor.yellow: + case SelectOptionColor.Yellow: return LocaleKeys.grid_selectOption_yellowColor.tr(); - case SelectOptionColor.lime: + case SelectOptionColor.Lime: return LocaleKeys.grid_selectOption_limeColor.tr(); - case SelectOptionColor.green: + case SelectOptionColor.Green: return LocaleKeys.grid_selectOption_greenColor.tr(); - case SelectOptionColor.aqua: + case SelectOptionColor.Aqua: return LocaleKeys.grid_selectOption_aquaColor.tr(); - case SelectOptionColor.blue: + case SelectOptionColor.Blue: return LocaleKeys.grid_selectOption_blueColor.tr(); + default: + throw ArgumentError; } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart index 239918994e..3309566eaf 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart @@ -130,7 +130,7 @@ class QuestionBubble extends StatelessWidget { } } -class QuestionBubbleActionSheet with ActionList implements FlowyOverlayDelegate { +class QuestionBubbleActionSheet with ActionList, FlowyOverlayDelegate { final Function(dartz.Option) onSelected; final _items = BubbleAction.values.map((action) => BubbleActionWrapper(action)).toList(); diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 651971d17f..99d86d22bb 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -1,10 +1,8 @@ // ignore_for_file: unused_element -import 'package:dartz/dartz.dart' show Tuple3; +import 'dart:ui'; import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart'; import 'package:flutter/material.dart'; -import 'dart:ui'; - export './overlay_container.dart'; /// Specifies how overlay are anchored to the SourceWidget @@ -75,6 +73,7 @@ TransitionBuilder overlayManagerBuilder() { } abstract class FlowyOverlayDelegate { + bool asBarrier() => false; void didRemove(); } @@ -110,8 +109,20 @@ class FlowyOverlay extends StatefulWidget { FlowyOverlayState createState() => FlowyOverlayState(); } +class OverlayItem { + Widget widget; + String identifier; + FlowyOverlayDelegate? delegate; + + OverlayItem({ + required this.widget, + required this.identifier, + this.delegate, + }); +} + class FlowyOverlayState extends State { - List> _overlayList = []; + List _overlayList = []; FlowyOverlayStyle style = FlowyOverlayStyle(); /// Insert a overlay widget which frame is set by the widget, not the component. @@ -181,19 +192,32 @@ class FlowyOverlayState extends State { void remove(String identifier) { setState(() { - final index = _overlayList.indexWhere((ele) => ele.value2 == identifier); + final index = _overlayList.indexWhere((item) => item.identifier == identifier); if (index != -1) { - _overlayList.removeAt(index).value3?.didRemove(); + _overlayList.removeAt(index).delegate?.didRemove(); } }); } void removeAll() { setState(() { - for (var ele in _overlayList.reversed) { - ele.value3?.didRemove(); + if (_overlayList.isEmpty) { + return; + } + + final reveredList = _overlayList.reversed.toList(); + final firstItem = reveredList.removeAt(0); + firstItem.delegate?.didRemove(); + _overlayList.remove(firstItem); + + for (final element in reveredList) { + if (element.delegate?.asBarrier() ?? false) { + return; + } else { + element.delegate?.didRemove(); + _overlayList.remove(element); + } } - _overlayList = []; }); } @@ -252,13 +276,17 @@ class FlowyOverlayState extends State { } setState(() { - _overlayList.add(Tuple3(overlay, identifier, delegate)); + _overlayList.add(OverlayItem( + widget: overlay, + identifier: identifier, + delegate: delegate, + )); }); } @override Widget build(BuildContext context) { - final overlays = _overlayList.map((ele) => ele.value1); + final overlays = _overlayList.map((item) => item.widget); List children = [widget.child]; Widget? child; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart index f2222d82b8..2e1ac9610e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart @@ -9,6 +9,10 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; +import 'selection_type_option.pbenum.dart'; + +export 'selection_type_option.pbenum.dart'; + class SingleSelectTypeOption extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelectTypeOption', createEmptyInstance: create) ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) @@ -123,7 +127,7 @@ class SelectOption extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', 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') ? '' : 'color') + ..e(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'color', $pb.PbFieldType.OE, defaultOrMaker: SelectOptionColor.Purple, valueOf: SelectOptionColor.valueOf, enumValues: SelectOptionColor.values) ..hasRequiredFields = false ; @@ -131,7 +135,7 @@ class SelectOption extends $pb.GeneratedMessage { factory SelectOption({ $core.String? id, $core.String? name, - $core.String? color, + SelectOptionColor? color, }) { final _result = create(); if (id != null) { @@ -185,9 +189,9 @@ class SelectOption extends $pb.GeneratedMessage { void clearName() => clearField(2); @$pb.TagNumber(3) - $core.String get color => $_getSZ(2); + SelectOptionColor get color => $_getN(2); @$pb.TagNumber(3) - set color($core.String v) { $_setString(2, v); } + set color(SelectOptionColor v) { setField(3, v); } @$pb.TagNumber(3) $core.bool hasColor() => $_has(2); @$pb.TagNumber(3) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart index 9a52c17f7d..0a063abf16 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbenum.dart @@ -5,3 +5,36 @@ // @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 SelectOptionColor extends $pb.ProtobufEnum { + static const SelectOptionColor Purple = SelectOptionColor._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Purple'); + static const SelectOptionColor Pink = SelectOptionColor._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Pink'); + static const SelectOptionColor LightPink = SelectOptionColor._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'LightPink'); + static const SelectOptionColor Orange = SelectOptionColor._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Orange'); + static const SelectOptionColor Yellow = SelectOptionColor._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yellow'); + static const SelectOptionColor Lime = SelectOptionColor._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Lime'); + static const SelectOptionColor Green = SelectOptionColor._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Green'); + static const SelectOptionColor Aqua = SelectOptionColor._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Aqua'); + static const SelectOptionColor Blue = SelectOptionColor._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Blue'); + + static const $core.List values = [ + Purple, + Pink, + LightPink, + Orange, + Yellow, + Lime, + Green, + Aqua, + Blue, + ]; + + static final $core.Map<$core.int, SelectOptionColor> _byValue = $pb.ProtobufEnum.initByValue(values); + static SelectOptionColor? valueOf($core.int value) => _byValue[value]; + + const SelectOptionColor._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart index fdfc6833b0..7499864079 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart @@ -8,6 +8,24 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use selectOptionColorDescriptor instead') +const SelectOptionColor$json = const { + '1': 'SelectOptionColor', + '2': const [ + const {'1': 'Purple', '2': 0}, + const {'1': 'Pink', '2': 1}, + const {'1': 'LightPink', '2': 2}, + const {'1': 'Orange', '2': 3}, + const {'1': 'Yellow', '2': 4}, + const {'1': 'Lime', '2': 5}, + const {'1': 'Green', '2': 6}, + const {'1': 'Aqua', '2': 7}, + const {'1': 'Blue', '2': 8}, + ], +}; + +/// Descriptor for `SelectOptionColor`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List selectOptionColorDescriptor = $convert.base64Decode('ChFTZWxlY3RPcHRpb25Db2xvchIKCgZQdXJwbGUQABIICgRQaW5rEAESDQoJTGlnaHRQaW5rEAISCgoGT3JhbmdlEAMSCgoGWWVsbG93EAQSCAoETGltZRAFEgkKBUdyZWVuEAYSCAoEQXF1YRAHEggKBEJsdWUQCA=='); @$core.Deprecated('Use singleSelectTypeOptionDescriptor instead') const SingleSelectTypeOption$json = const { '1': 'SingleSelectTypeOption', @@ -36,9 +54,9 @@ const SelectOption$json = const { '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': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'}, + const {'1': 'color', '3': 3, '4': 1, '5': 14, '6': '.SelectOptionColor', '10': 'color'}, ], }; /// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y'); +final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSKAoFY29sb3IYAyABKA4yEi5TZWxlY3RPcHRpb25Db2xvclIFY29sb3I='); diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index e99f1b541b..1a996b2a43 100755 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -956,6 +956,7 @@ dependencies = [ "rusty-money", "serde", "serde_json", + "serde_repr", "strum", "strum_macros", "tokio", diff --git a/frontend/rust-lib/flowy-grid/Cargo.toml b/frontend/rust-lib/flowy-grid/Cargo.toml index 3549bedd08..de0320f062 100644 --- a/frontend/rust-lib/flowy-grid/Cargo.toml +++ b/frontend/rust-lib/flowy-grid/Cargo.toml @@ -33,6 +33,7 @@ tokio = {version = "1", features = ["sync"]} rayon = "1.5" serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} +serde_repr = "0.1" [dev-dependencies] flowy-test = { path = "../flowy-test" } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs index 6d12dbc81f..ae57224d2e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs @@ -430,7 +430,7 @@ pub struct SelectOption { // message fields pub id: ::std::string::String, pub name: ::std::string::String, - pub color: ::std::string::String, + pub color: SelectOptionColor, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -499,31 +499,20 @@ impl SelectOption { ::std::mem::replace(&mut self.name, ::std::string::String::new()) } - // string color = 3; + // .SelectOptionColor color = 3; - pub fn get_color(&self) -> &str { - &self.color + pub fn get_color(&self) -> SelectOptionColor { + self.color } pub fn clear_color(&mut self) { - self.color.clear(); + self.color = SelectOptionColor::Purple; } // Param is passed by value, moved - pub fn set_color(&mut self, v: ::std::string::String) { + pub fn set_color(&mut self, v: SelectOptionColor) { self.color = v; } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_color(&mut self) -> &mut ::std::string::String { - &mut self.color - } - - // Take field - pub fn take_color(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.color, ::std::string::String::new()) - } } impl ::protobuf::Message for SelectOption { @@ -542,7 +531,7 @@ impl ::protobuf::Message for SelectOption { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; }, 3 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.color)?; + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.color, 3, &mut self.unknown_fields)? }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -562,8 +551,8 @@ impl ::protobuf::Message for SelectOption { if !self.name.is_empty() { my_size += ::protobuf::rt::string_size(2, &self.name); } - if !self.color.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.color); + if self.color != SelectOptionColor::Purple { + my_size += ::protobuf::rt::enum_size(3, self.color); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -577,8 +566,8 @@ impl ::protobuf::Message for SelectOption { if !self.name.is_empty() { os.write_string(2, &self.name)?; } - if !self.color.is_empty() { - os.write_string(3, &self.color)?; + if self.color != SelectOptionColor::Purple { + os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.color))?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -628,7 +617,7 @@ impl ::protobuf::Message for SelectOption { |m: &SelectOption| { &m.name }, |m: &mut SelectOption| { &mut m.name }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "color", |m: &SelectOption| { &m.color }, |m: &mut SelectOption| { &mut m.color }, @@ -651,7 +640,7 @@ impl ::protobuf::Clear for SelectOption { fn clear(&mut self) { self.id.clear(); self.name.clear(); - self.color.clear(); + self.color = SelectOptionColor::Purple; self.unknown_fields.clear(); } } @@ -668,15 +657,90 @@ impl ::protobuf::reflect::ProtobufValue for SelectOption { } } +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum SelectOptionColor { + Purple = 0, + Pink = 1, + LightPink = 2, + Orange = 3, + Yellow = 4, + Lime = 5, + Green = 6, + Aqua = 7, + Blue = 8, +} + +impl ::protobuf::ProtobufEnum for SelectOptionColor { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(SelectOptionColor::Purple), + 1 => ::std::option::Option::Some(SelectOptionColor::Pink), + 2 => ::std::option::Option::Some(SelectOptionColor::LightPink), + 3 => ::std::option::Option::Some(SelectOptionColor::Orange), + 4 => ::std::option::Option::Some(SelectOptionColor::Yellow), + 5 => ::std::option::Option::Some(SelectOptionColor::Lime), + 6 => ::std::option::Option::Some(SelectOptionColor::Green), + 7 => ::std::option::Option::Some(SelectOptionColor::Aqua), + 8 => ::std::option::Option::Some(SelectOptionColor::Blue), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [SelectOptionColor] = &[ + SelectOptionColor::Purple, + SelectOptionColor::Pink, + SelectOptionColor::LightPink, + SelectOptionColor::Orange, + SelectOptionColor::Yellow, + SelectOptionColor::Lime, + SelectOptionColor::Green, + SelectOptionColor::Aqua, + SelectOptionColor::Blue, + ]; + 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::("SelectOptionColor", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for SelectOptionColor { +} + +impl ::std::default::Default for SelectOptionColor { + fn default() -> Self { + SelectOptionColor::Purple + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionColor { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\x1bselection_type_option.proto\"f\n\x16SingleSelectTypeOption\x12'\n\ \x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x12#\n\rdis\ able_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"e\n\x15MultiSelectType\ Option\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07option\ - s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"H\n\x0cSe\ - lectOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ - \x18\x02\x20\x01(\tR\x04name\x12\x14\n\x05color\x18\x03\x20\x01(\tR\x05c\ - olorb\x06proto3\ + s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"\\\n\x0cS\ + electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ + \x18\x02\x20\x01(\tR\x04name\x12(\n\x05color\x18\x03\x20\x01(\x0e2\x12.S\ + electOptionColorR\x05color*y\n\x11SelectOptionColor\x12\n\n\x06Purple\ + \x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\x10\x02\x12\n\n\x06O\ + range\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\n\x04Lime\x10\x05\x12\t\ + \n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\x12\x08\n\x04Blue\x10\x08b\ + \x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto index 9fdfc34e9b..f07e2273bb 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto @@ -11,5 +11,16 @@ message MultiSelectTypeOption { message SelectOption { string id = 1; string name = 2; - string color = 3; + SelectOptionColor color = 3; +} +enum SelectOptionColor { + Purple = 0; + Pink = 1; + LightPink = 2; + Orange = 3; + Yellow = 4; + Lime = 5; + Green = 6; + Aqua = 7; + Blue = 8; } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 73dd3bd432..015bf2257b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -3,7 +3,7 @@ use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use crate::services::util::*; use bytes::Bytes; -use flowy_derive::ProtoBuf; +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; @@ -151,7 +151,7 @@ pub struct SelectOption { pub name: String, #[pb(index = 3)] - pub color: String, + pub color: SelectOptionColor, } impl SelectOption { @@ -159,11 +159,31 @@ impl SelectOption { SelectOption { id: uuid(), name: name.to_owned(), - color: "".to_string(), + color: SelectOptionColor::default(), } } } +#[derive(ProtoBuf_Enum, Serialize, Deserialize, Debug, Clone)] +#[repr(u8)] +pub enum SelectOptionColor { + Purple = 0, + Pink = 1, + LightPink = 2, + Orange = 3, + Yellow = 4, + Lime = 5, + Green = 6, + Aqua = 7, + Blue = 8, +} + +impl std::default::Default for SelectOptionColor { + fn default() -> Self { + SelectOptionColor::Purple + } +} + #[cfg(test)] mod tests { use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; From 7c6a857a699646eeeddcbb6e521236bca2445463 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 31 Mar 2022 14:59:57 +0800 Subject: [PATCH 20/47] chore: multi select --- .../assets/images/grid/checkmark.svg | 3 + .../app_flowy/lib/startup/deps_resolver.dart | 4 +- .../field/type_option/multi_select_bloc.dart | 57 +++++++++++++++++-- .../widgets/header/field_tyep_switcher.dart | 2 +- .../header/type_option/multi_select.dart | 44 ++++++++++---- 5 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/checkmark.svg diff --git a/frontend/app_flowy/assets/images/grid/checkmark.svg b/frontend/app_flowy/assets/images/grid/checkmark.svg new file mode 100644 index 0000000000..f9c848f713 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/checkmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 8bab77150a..4cb0fda104 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -221,8 +221,8 @@ void _resolveGridDeps(GetIt getIt) { (typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId), ); - getIt.registerFactoryParam( - (typeOption, _) => MultiSelectTypeOptionBloc(typeOption), + getIt.registerFactoryParam( + (typeOption, fieldId) => MultiSelectTypeOptionBloc(typeOption, fieldId), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart index 75ac80c47c..0a96f5f69b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart @@ -1,18 +1,37 @@ -import 'dart:typed_data'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; +import 'package:protobuf/protobuf.dart'; +import 'type_option_service.dart'; part 'multi_select_bloc.freezed.dart'; class MultiSelectTypeOptionBloc extends Bloc { - MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption) : super(MultiSelectTypeOptionState.initial(typeOption)) { + final TypeOptionService service; + + MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption, String fieldId) + : service = TypeOptionService(fieldId: fieldId), + super(MultiSelectTypeOptionState.initial(typeOption)) { on( (event, emit) async { await event.map( - createOption: (_CreateOption value) {}, - updateOptions: (_UpdateOptions value) async {}, + createOption: (_CreateOption value) async { + final result = await service.createOption(value.optionName); + result.fold( + (option) { + emit(state.copyWith(typeOption: _insertOption(option))); + }, + (err) => Log.error(err), + ); + }, + updateOption: (_UpdateOption value) async { + emit(state.copyWith(typeOption: _updateOption(value.option))); + }, + deleteOption: (_DeleteOption value) { + emit(state.copyWith(typeOption: _deleteOption(value.option))); + }, ); }, ); @@ -22,12 +41,40 @@ class MultiSelectTypeOptionBloc extends Bloc close() async { return super.close(); } + + MultiSelectTypeOption _insertOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.options.insert(0, option); + }); + } + + MultiSelectTypeOption _updateOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options[index] = option; + } + }); + } + + MultiSelectTypeOption _deleteOption(SelectOption option) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options.removeAt(index); + } + }); + } } @freezed class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent { const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption; - const factory MultiSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions; + const factory MultiSelectTypeOptionEvent.updateOption(SelectOption option) = _UpdateOption; + const factory MultiSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption; } @freezed diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart index ce34097118..e8eb5caee2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart @@ -156,7 +156,7 @@ TypeOptionBuilder _makeTypeOptionBuild({ case FieldType.SingleSelect: return SingleSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate); case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder(data, overlayDelegate); + return MultiSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate); case FieldType.Number: return NumberTypeOptionBuilder(data, overlayDelegate, dataDelegate); case FieldType.RichText: diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index 43cf2597fa..23881e9310 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -8,26 +8,45 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'option_pannel.dart'; class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { - MultiSelectTypeOption typeOption; - TypeOptionOverlayDelegate delegate; + MultiSelectTypeOptionWidget _widget; - MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate) - : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData); + MultiSelectTypeOptionBuilder( + String fieldId, + TypeOptionData typeOptionData, + TypeOptionOverlayDelegate overlayDelegate, + TypeOptionDataDelegate dataDelegate, + ) : _widget = MultiSelectTypeOptionWidget( + fieldId: fieldId, + typeOption: MultiSelectTypeOption.fromBuffer(typeOptionData), + overlayDelegate: overlayDelegate, + dataDelegate: dataDelegate, + ); @override - Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption, delegate); + Widget? get customWidget => _widget; } class MultiSelectTypeOptionWidget extends TypeOptionWidget { + final String fieldId; final MultiSelectTypeOption typeOption; final TypeOptionOverlayDelegate overlayDelegate; - const MultiSelectTypeOptionWidget(this.typeOption, this.overlayDelegate, {Key? key}) : super(key: key); + final TypeOptionDataDelegate dataDelegate; + const MultiSelectTypeOptionWidget({ + required this.fieldId, + required this.typeOption, + required this.overlayDelegate, + required this.dataDelegate, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: typeOption), - child: BlocBuilder( + create: (context) => getIt(param1: typeOption, param2: fieldId), + child: BlocConsumer( + listener: (context, state) { + dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); + }, builder: (context, state) { return OptionPannel( options: state.typeOption.options, @@ -37,9 +56,14 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { createOptionCallback: (name) { context.read().add(MultiSelectTypeOptionEvent.createOption(name)); }, - updateOptionCallback: (updateOption) {}, - deleteOptionCallback: (deleteOption) {}, + updateOptionCallback: (updateOption) { + context.read().add(MultiSelectTypeOptionEvent.updateOption(updateOption)); + }, + deleteOptionCallback: (deleteOption) { + context.read().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption)); + }, overlayDelegate: overlayDelegate, + key: ValueKey(state.typeOption.hashCode), ); }, ), From c3c75dde9fcab43150f7a5322bbcdb744cd86bf0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 31 Mar 2022 19:45:54 +0800 Subject: [PATCH 21/47] chore: show edit field --- .../grid/field/type_option/date_bloc.dart | 22 +++- .../grid/field/type_option/number_bloc.dart | 11 +- .../src/widgets/header/edit_field_pannel.dart | 110 ------------------ .../src/widgets/header/grid_header_cell.dart | 4 +- .../src/widgets/header/type_option/date.dart | 67 ++++++++--- 5 files changed, 80 insertions(+), 134 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart index e2e7f2f0e2..0cf842a171 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart @@ -2,7 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - +import 'package:protobuf/protobuf.dart'; part 'date_bloc.freezed.dart'; class DateTypeOptionBloc extends Bloc { @@ -11,18 +11,30 @@ class DateTypeOptionBloc extends Bloc (event, emit) async { event.map( didSelectDateFormat: (_DidSelectDateFormat value) { - state.typeOption.dateFormat = value.format; - emit(state); + emit(state.copyWith(typeOption: _updateDateFormat(value.format))); }, didSelectTimeFormat: (_DidSelectTimeFormat value) { - state.typeOption.timeFormat = value.format; - emit(state); + emit(state.copyWith(typeOption: _updateTimeFormat(value.format))); }, ); }, ); } + DateTypeOption _updateTimeFormat(TimeFormat format) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.timeFormat = format; + }); + } + + DateTypeOption _updateDateFormat(DateFormat format) { + state.typeOption.freeze(); + return state.typeOption.rebuild((typeOption) { + typeOption.dateFormat = format; + }); + } + @override Future close() async { return super.close(); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart index a396454671..a655ebc1e8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart @@ -2,6 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; +import 'package:protobuf/protobuf.dart'; part 'number_bloc.freezed.dart'; @@ -11,14 +12,20 @@ class NumberTypeOptionBloc extends Bloc close() async { return super.close(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart deleted file mode 100644 index cab5a51138..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'field_name_input.dart'; -import 'field_operation_list.dart'; -import 'field_tyep_switcher.dart'; - -class EditFieldPannel extends StatelessWidget { - final GridFieldData fieldData; - const EditFieldPannel({required this.fieldData, Key? key}) : super(key: key); - - static void show(BuildContext context, GridFieldData fieldData) { - final editor = EditFieldPannel(fieldData: fieldData); - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: editor, - constraints: BoxConstraints.loose(const Size(300, 200)), - ), - identifier: editor.identifier(), - anchorContext: context, - anchorDirection: AnchorDirection.bottomWithLeftAligned, - ); - } - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: fieldData)..add(const EditFieldEvent.initial()), - child: SingleChildScrollView( - child: Column( - children: [ - const _FieldNameTextField(), - const VSpace(6), - const _FieldTypeSwitcher(), - const VSpace(6), - _FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())), - ], - ), - ), - ); - } - - String identifier() { - return toString(); - } -} - -class _FieldOperationList extends StatelessWidget { - final GridFieldData fieldData; - final VoidCallback onDismissed; - const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final actions = FieldAction.values - .map( - (action) => FieldActionItem( - fieldId: fieldData.field.id, - action: action, - onTap: onDismissed, - ), - ) - .toList(); - - return FieldOperationList(actions: actions); - } -} - -class _FieldTypeSwitcher extends StatelessWidget { - const _FieldTypeSwitcher({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final editContext = context.read().state.editContext; - final switchContext = SwitchFieldContext( - editContext.gridId, - editContext.gridField, - editContext.typeOptionData, - ); - return FieldTypeSwitcher(switchContext: switchContext, onSelected: (field, typeOptionData) {}); - }, - ); - } -} - -class _FieldNameTextField extends StatelessWidget { - const _FieldNameTextField({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: ((previous, current) => previous.fieldName == current.fieldName), - builder: (context, state) { - return FieldNameTextField( - name: state.fieldName, - errorText: state.errorText, - onNameChanged: (newName) { - context.read().add(EditFieldEvent.updateFieldName(newName)); - }, - ); - }, - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart index 5e5dc5f4fd..19869ccffc 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart @@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'edit_field_pannel.dart'; +import 'field_detail_pannel.dart'; class GridHeaderCell extends StatelessWidget { final GridFieldData fieldData; @@ -18,7 +18,7 @@ class GridHeaderCell extends StatelessWidget { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => EditFieldPannel.show(context, fieldData), + onTap: () => FieldDetailPannel.show(context, fieldData), rightIcon: svg("editor/details", color: theme.iconColor), text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 581a3934e7..0a057b5727 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -50,15 +50,15 @@ class DateTypeOptionWidget extends TypeOptionWidget { listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return Column(children: [ - _dateFormatButton(context), - _timeFormatButton(context), + _dateFormatButton(context, state.typeOption.dateFormat), + _timeFormatButton(context, state.typeOption.timeFormat), ]); }, ), ); } - Widget _dateFormatButton(BuildContext context) { + Widget _dateFormatButton(BuildContext context, DateFormat dataFormat) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, @@ -67,9 +67,12 @@ class DateTypeOptionWidget extends TypeOptionWidget { padding: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { - final list = DateFormatList(onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); - }); + final list = DateFormatList( + selectedFormat: dataFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); + }, + ); overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), @@ -77,7 +80,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { ); } - Widget _timeFormatButton(BuildContext context) { + Widget _timeFormatButton(BuildContext context, TimeFormat timeFormat) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, @@ -86,9 +89,11 @@ class DateTypeOptionWidget extends TypeOptionWidget { padding: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { - final list = TimeFormatList(onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); - }); + final list = TimeFormatList( + selectedFormat: timeFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); + }); overlayDelegate.showOverlay(context, list); }, rightIcon: svg("grid/more", color: theme.iconColor), @@ -98,8 +103,9 @@ class DateTypeOptionWidget extends TypeOptionWidget { } class DateFormatList extends StatelessWidget { + final DateFormat selectedFormat; final Function(DateFormat format) onSelected; - const DateFormatList({required this.onSelected, Key? key}) : super(key: key); + const DateFormatList({required this.selectedFormat, required this.onSelected, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -109,7 +115,8 @@ class DateFormatList extends StatelessWidget { onSelected: (format) { onSelected(format); FlowyOverlay.of(context).remove(identifier()); - }); + }, + isSelected: selectedFormat == format); }).toList(); return SizedBox( @@ -134,18 +141,30 @@ class DateFormatList extends StatelessWidget { } class DateFormatItem extends StatelessWidget { + final bool isSelected; final DateFormat dateFormat; final Function(DateFormat format) onSelected; - const DateFormatItem({required this.dateFormat, required this.onSelected, Key? key}) : super(key: key); + const DateFormatItem({ + required this.dateFormat, + required this.onSelected, + required this.isSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); + Widget? checkmark; + if (isSelected) { + checkmark = svg("grid/checkmark"); + } + return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(dateFormat.title(), fontSize: 12), hoverColor: theme.hover, + rightIcon: checkmark, onTap: () => onSelected(dateFormat), ), ); @@ -170,13 +189,19 @@ extension DateFormatExtension on DateFormat { } class TimeFormatList extends StatelessWidget { + final TimeFormat selectedFormat; final Function(TimeFormat format) onSelected; - const TimeFormatList({required this.onSelected, Key? key}) : super(key: key); + const TimeFormatList({ + required this.selectedFormat, + required this.onSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final formatItems = TimeFormat.values.map((format) { return TimeFormatItem( + isSelected: format == selectedFormat, timeFormat: format, onSelected: (format) { onSelected(format); @@ -207,17 +232,29 @@ class TimeFormatList extends StatelessWidget { class TimeFormatItem extends StatelessWidget { final TimeFormat timeFormat; + final bool isSelected; final Function(TimeFormat format) onSelected; - const TimeFormatItem({required this.timeFormat, required this.onSelected, Key? key}) : super(key: key); + const TimeFormatItem({ + required this.timeFormat, + required this.onSelected, + required this.isSelected, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); + Widget? checkmark; + if (isSelected) { + checkmark = svg("grid/checkmark"); + } + return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(timeFormat.title(), fontSize: 12), hoverColor: theme.hover, + rightIcon: checkmark, onTap: () => onSelected(timeFormat), ), ); From 37491688619436141c54e33e4f77559d72d7f7d7 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 31 Mar 2022 22:51:46 +0800 Subject: [PATCH 22/47] fix: fix some bugs --- .../app_flowy/assets/translations/en.json | 3 +- .../app_flowy/lib/startup/deps_resolver.dart | 13 +- .../grid/field/create_field_bloc.dart | 98 -------- .../grid/field/edit_field_bloc.dart | 108 +++++---- .../application/grid/field/field_service.dart | 40 +++- .../grid/field/grid_field_bloc.dart | 80 +++++++ .../grid/field/switch_field_type_bloc.dart | 28 +-- .../workspace/application/grid/prelude.dart | 2 +- .../{field_type_list.dart => field_list.dart} | 0 .../widgets/header/field_operation_list.dart | 8 +- ...tyep_switcher.dart => field_switcher.dart} | 28 +-- .../header/grid_field_action_sheet.dart | 103 +++++++++ ...eld_pannel.dart => grid_field_editor.dart} | 52 +++-- .../grid/src/widgets/header/grid_header.dart | 8 +- .../src/widgets/header/grid_header_cell.dart | 10 +- .../src/widgets/header/type_option/date.dart | 2 +- .../header/type_option/multi_select.dart | 2 +- .../widgets/header/type_option/number.dart | 2 +- .../header/type_option/option_pannel.dart | 2 +- .../header/type_option/single_select.dart | 2 +- .../lib/src/flowy_overlay/flowy_overlay.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 8 +- .../flowy-grid-data-model/grid.pb.dart | 63 +++-- .../flowy-grid-data-model/grid.pbjson.dart | 16 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 4 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 25 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 6 +- .../src/protobuf/model/event_map.rs | 16 +- .../src/protobuf/proto/event_map.proto | 2 +- .../flowy-grid/src/services/grid_editor.rs | 53 +++-- .../src/entities/grid.rs | 7 +- .../src/protobuf/model/grid.rs | 217 ++++++++++++------ .../src/protobuf/proto/grid.proto | 5 +- .../src/client_grid/grid_meta_pad.rs | 2 +- 35 files changed, 666 insertions(+), 355 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{field_type_list.dart => field_list.dart} (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{field_tyep_switcher.dart => field_switcher.dart} (88%) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{create_field_pannel.dart => grid_field_editor.dart} (58%) diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 4bb37ea078..b9ab426fbd 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -166,7 +166,8 @@ "timeFormatTwentyFourHour": "24 hour", "addSelectOption": "Add an option", "optionTitle": "Options", - "addOption": "Add option" + "addOption": "Add option", + "editProperty": "Edit property" }, "selectOption": { "purpleColor": "Purple", diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 4cb0fda104..1bb46f913f 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -165,16 +165,17 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (data, _) => EditFieldBloc( + getIt.registerFactoryParam( + (data, _) => GridFieldBloc( field: data.field, service: FieldService(gridId: data.gridId), ), ); - getIt.registerFactoryParam( - (gridId, _) => CreateFieldBloc( + getIt.registerFactoryParam( + (gridId, fieldLoader) => FieldEditorBloc( service: FieldService(gridId: gridId), + fieldLoader: fieldLoader, ), ); @@ -213,8 +214,8 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => FieldTypeSwitchBloc(context), + getIt.registerFactoryParam( + (context, _) => FieldSwitchBloc(context), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart deleted file mode 100644 index 6a5a276214..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; -import 'field_service.dart'; -import 'package:dartz/dartz.dart'; - -part 'create_field_bloc.freezed.dart'; - -class CreateFieldBloc extends Bloc { - final FieldService service; - - CreateFieldBloc({required this.service}) : super(CreateFieldState.initial(service.gridId)) { - on( - (event, emit) async { - await event.map( - initial: (_InitialField value) async { - await _getEditFieldContext(emit); - }, - updateName: (_UpdateName value) { - emit(state.copyWith(fieldName: value.name)); - }, - switchField: (_SwitchField value) { - emit(state.copyWith(field: Some(value.field), typeOptionData: value.typeOptionData)); - }, - done: (_Done value) async { - await _saveField(emit); - }, - ); - }, - ); - } - - @override - Future close() async { - return super.close(); - } - - Future _saveField(Emitter emit) async { - await state.field.fold( - () async => null, - (field) async { - field.name = state.fieldName; - - final result = await service.createField( - field: field, - typeOptionData: state.typeOptionData, - ); - result.fold((l) => null, (r) => null); - }, - ); - } - - Future _getEditFieldContext(Emitter emit) async { - final result = await service.getEditFieldContext(FieldType.RichText); - result.fold( - (editContext) { - emit(state.copyWith( - field: Some(editContext.gridField), - typeOptionData: editContext.typeOptionData, - fieldName: editContext.gridField.name, - )); - }, - (err) => Log.error(err), - ); - } -} - -@freezed -class CreateFieldEvent with _$CreateFieldEvent { - const factory CreateFieldEvent.initial() = _InitialField; - const factory CreateFieldEvent.updateName(String name) = _UpdateName; - const factory CreateFieldEvent.switchField(Field field, Uint8List typeOptionData) = _SwitchField; - const factory CreateFieldEvent.done() = _Done; -} - -@freezed -class CreateFieldState with _$CreateFieldState { - const factory CreateFieldState({ - required String fieldName, - required String gridId, - required String errorText, - required Option field, - required List typeOptionData, - }) = _CreateFieldState; - - factory CreateFieldState.initial(String gridId) => CreateFieldState( - gridId: gridId, - fieldName: '', - field: none(), - errorText: '', - typeOptionData: List.empty(), - ); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart index 525d5232d7..749cde3420 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart @@ -1,50 +1,38 @@ +import 'dart:typed_data'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'field_service.dart'; +import 'package:dartz/dartz.dart'; part 'edit_field_bloc.freezed.dart'; -class EditFieldBloc extends Bloc { +class FieldEditorBloc extends Bloc { final FieldService service; + final FieldContextLoader _loader; - EditFieldBloc({required Field field, required this.service}) - : super(EditFieldState.initial(EditFieldContext.create()..gridField = field)) { - on( + FieldEditorBloc({ + required this.service, + required FieldContextLoader fieldLoader, + }) : _loader = fieldLoader, + super(FieldEditorState.initial(service.gridId)) { + on( (event, emit) async { await event.map( - initial: (_InitialField value) {}, - updateFieldName: (_UpdateFieldName value) async { - final result = await service.updateField(fieldId: field.id, name: value.name); - result.fold( - (l) => null, - (err) => Log.error(err), - ); + initial: (_InitialField value) async { + await _getEditFieldContext(emit); }, - hideField: (_HideField value) async { - final result = await service.updateField(fieldId: field.id, visibility: false); - result.fold( - (l) => null, - (err) => Log.error(err), - ); + updateName: (_UpdateName value) { + emit(state.copyWith(fieldName: value.name)); }, - deleteField: (_DeleteField value) async { - final result = await service.deleteField(fieldId: field.id); - result.fold( - (l) => null, - (err) => Log.error(err), - ); + switchField: (_SwitchField value) { + emit(state.copyWith(field: Some(value.field), typeOptionData: value.typeOptionData)); }, - duplicateField: (_DuplicateField value) async { - final result = await service.duplicateField(fieldId: field.id); - result.fold( - (l) => null, - (err) => Log.error(err), - ); + done: (_Done value) async { + await _saveField(emit); }, - saveField: (_SaveField value) {}, ); }, ); @@ -54,29 +42,59 @@ class EditFieldBloc extends Bloc { Future close() async { return super.close(); } + + Future _saveField(Emitter emit) async { + await state.field.fold( + () async => null, + (field) async { + field.name = state.fieldName; + final result = await service.createField( + field: field, + typeOptionData: state.typeOptionData, + ); + result.fold((l) => null, (r) => null); + }, + ); + } + + Future _getEditFieldContext(Emitter emit) async { + final result = await _loader.load(); + result.fold( + (editContext) { + emit(state.copyWith( + field: Some(editContext.gridField), + typeOptionData: editContext.typeOptionData, + fieldName: editContext.gridField.name, + )); + }, + (err) => Log.error(err), + ); + } } @freezed -class EditFieldEvent with _$EditFieldEvent { - const factory EditFieldEvent.initial() = _InitialField; - const factory EditFieldEvent.updateFieldName(String name) = _UpdateFieldName; - const factory EditFieldEvent.hideField() = _HideField; - const factory EditFieldEvent.duplicateField() = _DuplicateField; - const factory EditFieldEvent.deleteField() = _DeleteField; - const factory EditFieldEvent.saveField() = _SaveField; +class FieldEditorEvent with _$FieldEditorEvent { + const factory FieldEditorEvent.initial() = _InitialField; + const factory FieldEditorEvent.updateName(String name) = _UpdateName; + const factory FieldEditorEvent.switchField(Field field, Uint8List typeOptionData) = _SwitchField; + const factory FieldEditorEvent.done() = _Done; } @freezed -class EditFieldState with _$EditFieldState { - const factory EditFieldState({ - required EditFieldContext editContext, - required String errorText, +class FieldEditorState with _$FieldEditorState { + const factory FieldEditorState({ required String fieldName, - }) = _EditFieldState; + required String gridId, + required String errorText, + required Option field, + required List typeOptionData, + }) = _FieldEditorState; - factory EditFieldState.initial(EditFieldContext editContext) => EditFieldState( - editContext: editContext, + factory FieldEditorState.initial(String gridId) => FieldEditorState( + gridId: gridId, + fieldName: '', + field: none(), errorText: '', - fieldName: editContext.gridField.name, + typeOptionData: List.empty(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 24644f0fae..b38d9ffba1 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -11,11 +11,11 @@ class FieldService { FieldService({required this.gridId}); Future> getEditFieldContext(FieldType fieldType) { - final payload = CreateEditFieldContextParams.create() + final payload = GetEditFieldContextParams.create() ..gridId = gridId ..fieldType = fieldType; - return GridEventCreateEditFieldContext(payload).send(); + return GridEventGetEditFieldContext(payload).send(); } Future> updateField({ @@ -108,3 +108,39 @@ class GridFieldData extends Equatable { @override List get props => [field.id]; } + +abstract class FieldContextLoader { + Future> load(); +} + +class NewFieldContextLoader extends FieldContextLoader { + final String gridId; + NewFieldContextLoader({ + required this.gridId, + }); + + @override + Future> load() { + final payload = GetEditFieldContextParams.create() + ..gridId = gridId + ..fieldType = FieldType.RichText; + + return GridEventGetEditFieldContext(payload).send(); + } +} + +class FieldContextLoaderAdaptor extends FieldContextLoader { + final GridFieldData data; + + FieldContextLoaderAdaptor(this.data); + + @override + Future> load() { + final payload = GetEditFieldContextParams.create() + ..gridId = data.gridId + ..fieldId = data.field.id + ..fieldType = data.field.fieldType; + + return GridEventGetEditFieldContext(payload).send(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart new file mode 100644 index 0000000000..f3ec3b4cbe --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart @@ -0,0 +1,80 @@ +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'field_service.dart'; + +part 'grid_field_bloc.freezed.dart'; + +class GridFieldBloc extends Bloc { + final FieldService service; + + GridFieldBloc({required Field field, required this.service}) + : super(GridFieldState.initial(EditFieldContext.create()..gridField = field)) { + on( + (event, emit) async { + await event.map( + updateFieldName: (_UpdateFieldName value) async { + final result = await service.updateField(fieldId: field.id, name: value.name); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + hideField: (_HideField value) async { + final result = await service.updateField(fieldId: field.id, visibility: false); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + deleteField: (_DeleteField value) async { + final result = await service.deleteField(fieldId: field.id); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + duplicateField: (_DuplicateField value) async { + final result = await service.duplicateField(fieldId: field.id); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + saveField: (_SaveField value) {}, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class GridFieldEvent with _$GridFieldEvent { + const factory GridFieldEvent.updateFieldName(String name) = _UpdateFieldName; + const factory GridFieldEvent.hideField() = _HideField; + const factory GridFieldEvent.duplicateField() = _DuplicateField; + const factory GridFieldEvent.deleteField() = _DeleteField; + const factory GridFieldEvent.saveField() = _SaveField; +} + +@freezed +class GridFieldState with _$GridFieldState { + const factory GridFieldState({ + required EditFieldContext editContext, + required String errorText, + required String fieldName, + }) = _GridFieldState; + + factory GridFieldState.initial(EditFieldContext editContext) => GridFieldState( + editContext: editContext, + errorText: '', + fieldName: editContext.gridField.name, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart index ba8371c3a3..1bb2bb18ce 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -9,9 +9,9 @@ import 'field_service.dart'; part 'switch_field_type_bloc.freezed.dart'; -class FieldTypeSwitchBloc extends Bloc { - FieldTypeSwitchBloc(SwitchFieldContext editContext) : super(FieldTypeSwitchState.initial(editContext)) { - on( +class FieldSwitchBloc extends Bloc { + FieldSwitchBloc(SwitchFieldContext editContext) : super(FieldSwitchState.initial(editContext)) { + on( (event, emit) async { await event.map( toFieldType: (_ToFieldType value) async { @@ -19,12 +19,8 @@ class FieldTypeSwitchBloc extends Bloc Log.error(err), ); @@ -44,20 +40,20 @@ class FieldTypeSwitchBloc extends Bloc FieldTypeSwitchState( + factory FieldSwitchState.initial(SwitchFieldContext switchContext) => FieldSwitchState( gridId: switchContext.gridId, field: switchContext.field, typeOptionData: Uint8List.fromList(switchContext.typeOptionData), diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index e1d3020ae0..8b13a4f34d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -7,8 +7,8 @@ export 'data.dart'; // Field export 'field/field_service.dart'; export 'field/grid_header_bloc.dart'; +export 'field/grid_field_bloc.dart'; export 'field/edit_field_bloc.dart'; -export 'field/create_field_bloc.dart'; export 'field/switch_field_type_bloc.dart'; // Field Type Option diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart index a4ccc94a94..956060039d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/field/edit_field_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/grid_field_bloc.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -86,13 +86,13 @@ extension _FieldActionExtension on FieldAction { void run(BuildContext context) { switch (this) { case FieldAction.hide: - context.read().add(const EditFieldEvent.hideField()); + context.read().add(const GridFieldEvent.hideField()); break; case FieldAction.duplicate: - context.read().add(const EditFieldEvent.duplicateField()); + context.read().add(const GridFieldEvent.duplicateField()); break; case FieldAction.delete: - context.read().add(const EditFieldEvent.deleteField()); + context.read().add(const GridFieldEvent.deleteField()); break; } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart similarity index 88% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart index e8eb5caee2..5f11d750d8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart @@ -15,39 +15,41 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart'; import 'type_option/multi_select.dart'; import 'type_option/number.dart'; import 'type_option/single_select.dart'; -typedef SelectFieldCallback = void Function(Field, Uint8List); +typedef UpdateFieldCallback = void Function(Field, Uint8List); -class FieldTypeSwitcher extends StatefulWidget { +class FieldSwitcher extends StatefulWidget { final SwitchFieldContext switchContext; - final SelectFieldCallback onSelected; + final UpdateFieldCallback onUpdated; - const FieldTypeSwitcher({ + const FieldSwitcher({ required this.switchContext, - required this.onSelected, + required this.onUpdated, Key? key, }) : super(key: key); @override - State createState() => _FieldTypeSwitcherState(); + State createState() => _FieldSwitcherState(); } -class _FieldTypeSwitcherState extends State { +class _FieldSwitcherState extends State { String? currentOverlayIdentifier; @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: widget.switchContext), - child: BlocBuilder( + create: (context) => getIt(param1: widget.switchContext), + child: BlocConsumer( + listener: (context, state) { + widget.onUpdated(state.field, state.typeOptionData); + }, builder: (context, state) { List children = [_switchFieldTypeButton(context, state.field)]; - final typeOptionWidget = _typeOptionWidget( context: context, field: state.field, @@ -77,7 +79,7 @@ class _FieldTypeSwitcherState extends State { hoverColor: theme.hover, onTap: () { final list = FieldTypeList(onSelectField: (fieldType) { - context.read().add(FieldTypeSwitchEvent.toFieldType(fieldType)); + context.read().add(FieldSwitchEvent.toFieldType(fieldType)); }); _showOverlay(context, list); }, @@ -98,7 +100,7 @@ class _FieldTypeSwitcherState extends State { ); final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { - context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data)); + context.read().add(FieldSwitchEvent.didUpdateTypeOptionData(data)); }); final builder = _makeTypeOptionBuild( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart new file mode 100644 index 0000000000..13f9fbaba5 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart @@ -0,0 +1,103 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'field_operation_list.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; + +class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate { + final GridFieldData fieldData; + final VoidCallback onEdited; + const GridFieldActionSheet({required this.fieldData, required this.onEdited, Key? key}) : super(key: key); + + static void show(BuildContext overlayContext, GridFieldData fieldData, final VoidCallback onEdited) { + final editor = GridFieldActionSheet(fieldData: fieldData, onEdited: onEdited); + FlowyOverlay.of(overlayContext).insertWithAnchor( + widget: OverlayContainer( + child: editor, + constraints: BoxConstraints.loose(const Size(240, 200)), + ), + identifier: editor.identifier(), + anchorContext: overlayContext, + anchorDirection: AnchorDirection.bottomWithLeftAligned, + ); + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: fieldData), + child: SingleChildScrollView( + child: Column( + children: [ + _EditFieldButton( + onEdited: () { + FlowyOverlay.of(context).remove(identifier()); + onEdited(); + }, + ), + const VSpace(6), + _FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())), + ], + ), + ), + ); + } + + String identifier() { + return toString(); + } + + @override + bool asBarrier() => true; +} + +class _EditFieldButton extends StatelessWidget { + final Function() onEdited; + const _EditFieldButton({required this.onEdited, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocBuilder( + builder: (context, state) { + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), + hoverColor: theme.hover, + onTap: onEdited, + ), + ); + }, + ); + } +} + +class _FieldOperationList extends StatelessWidget { + final GridFieldData fieldData; + final VoidCallback onDismissed; + const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final actions = FieldAction.values + .map( + (action) => FieldActionItem( + fieldId: fieldData.field.id, + action: action, + onTap: onDismissed, + ), + ) + .toList(); + + return FieldOperationList(actions: actions); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart similarity index 58% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart index a530737e28..085f051699 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/field/create_field_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/edit_field_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/application/grid/field/switch_field_type_bloc.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -7,19 +8,24 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_name_input.dart'; -import 'field_tyep_switcher.dart'; +import 'field_switcher.dart'; -class CreateFieldPannel extends FlowyOverlayDelegate { +class FieldEditor extends FlowyOverlayDelegate { final String gridId; - final CreateFieldBloc _createFieldBloc; - CreateFieldPannel({required this.gridId, Key? key}) : _createFieldBloc = getIt(param1: gridId) { - _createFieldBloc.add(const CreateFieldEvent.initial()); + final FieldEditorBloc _fieldEditorBloc; + final FieldContextLoader? fieldContextLoader; + FieldEditor({ + required this.gridId, + required this.fieldContextLoader, + Key? key, + }) : _fieldEditorBloc = getIt(param1: gridId, param2: fieldContextLoader) { + _fieldEditorBloc.add(const FieldEditorEvent.initial()); } - void show(BuildContext context, String gridId) { + void show(BuildContext context) { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: _CreateFieldPannelWidget(_createFieldBloc), + child: _EditFieldPannelWidget(_fieldEditorBloc), constraints: BoxConstraints.loose(const Size(220, 400)), ), identifier: identifier(), @@ -36,22 +42,22 @@ class CreateFieldPannel extends FlowyOverlayDelegate { @override void didRemove() { - _createFieldBloc.add(const CreateFieldEvent.done()); + _fieldEditorBloc.add(const FieldEditorEvent.done()); } @override bool asBarrier() => true; } -class _CreateFieldPannelWidget extends StatelessWidget { - final CreateFieldBloc createFieldBloc; - const _CreateFieldPannelWidget(this.createFieldBloc, {Key? key}) : super(key: key); +class _EditFieldPannelWidget extends StatelessWidget { + final FieldEditorBloc editorBloc; + const _EditFieldPannelWidget(this.editorBloc, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider.value( - value: createFieldBloc, - child: BlocBuilder( + value: editorBloc, + child: BlocBuilder( builder: (context, state) { return state.field.fold( () => const SizedBox(width: 200), @@ -62,7 +68,7 @@ class _CreateFieldPannelWidget extends StatelessWidget { const VSpace(10), const _FieldNameTextField(), const VSpace(10), - _FieldTypeSwitcher(SwitchFieldContext(state.gridId, field, state.typeOptionData)), + _FieldSwitcher(SwitchFieldContext(state.gridId, field, state.typeOptionData)), ], ), ); @@ -72,16 +78,16 @@ class _CreateFieldPannelWidget extends StatelessWidget { } } -class _FieldTypeSwitcher extends StatelessWidget { +class _FieldSwitcher extends StatelessWidget { final SwitchFieldContext switchContext; - const _FieldTypeSwitcher(this.switchContext, {Key? key}) : super(key: key); + const _FieldSwitcher(this.switchContext, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return FieldTypeSwitcher( + return FieldSwitcher( switchContext: switchContext, - onSelected: (field, typeOptionData) { - context.read().add(CreateFieldEvent.switchField(field, typeOptionData)); + onUpdated: (field, typeOptionData) { + context.read().add(FieldEditorEvent.switchField(field, typeOptionData)); }, ); } @@ -92,14 +98,14 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( buildWhen: (previous, current) => previous.fieldName != current.fieldName, builder: (context, state) { return FieldNameTextField( name: state.fieldName, - errorText: context.read().state.errorText, + errorText: context.read().state.errorText, onNameChanged: (newName) { - context.read().add(CreateFieldEvent.updateName(newName)); + context.read().add(FieldEditorEvent.updateName(newName)); }, ); }, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index 6e07fec904..6125cf4526 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -9,7 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'create_field_pannel.dart'; +import 'grid_field_editor.dart'; import 'grid_header_cell.dart'; class GridHeaderDelegate extends SliverPersistentHeaderDelegate { @@ -113,10 +113,14 @@ class CreateFieldButton extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); + return FlowyButton( text: const FlowyText.medium('New column', fontSize: 12), hoverColor: theme.hover, - onTap: () => CreateFieldPannel(gridId: gridId).show(context, gridId), + onTap: () => FieldEditor( + gridId: gridId, + fieldContextLoader: NewFieldContextLoader(gridId: gridId), + ).show(context), leftIcon: svg("home/add"), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart index 19869ccffc..4efedbfe6d 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart @@ -7,7 +7,8 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'field_detail_pannel.dart'; +import 'grid_field_editor.dart'; +import 'grid_field_action_sheet.dart'; class GridHeaderCell extends StatelessWidget { final GridFieldData fieldData; @@ -18,7 +19,12 @@ class GridHeaderCell extends StatelessWidget { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => FieldDetailPannel.show(context, fieldData), + onTap: () => GridFieldActionSheet.show(context, fieldData, () { + FieldEditor( + gridId: fieldData.gridId, + fieldContextLoader: FieldContextLoaderAdaptor(fieldData), + ).show(context); + }), rightIcon: svg("editor/details", color: theme.iconColor), text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 0a057b5727..5057d5caee 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:easy_localization/easy_localization.dart' hide DateFormat; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index 23881e9310..99728aeffb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index 97dffd17e1..bbff9dd5ad 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/number_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart index 2c4a1b5e4a..b4039bbce1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart index 76573ef945..ecc0dfc80a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 99d86d22bb..0290cf18b3 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -74,7 +74,7 @@ TransitionBuilder overlayManagerBuilder() { abstract class FlowyOverlayDelegate { bool asBarrier() => false; - void didRemove(); + void didRemove() => {}; } class FlowyOverlay extends StatefulWidget { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 04098b288e..5f34777079 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -120,13 +120,13 @@ class GridEventDuplicateField { } } -class GridEventCreateEditFieldContext { - CreateEditFieldContextParams request; - GridEventCreateEditFieldContext(this.request); +class GridEventGetEditFieldContext { + GetEditFieldContextParams request; + GridEventGetEditFieldContext(this.request); Future> send() { final request = FFIRequest.create() - ..event = GridEvent.CreateEditFieldContext.toString() + ..event = GridEvent.GetEditFieldContext.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) 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 3dafd193b3..cd3c552036 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 @@ -374,47 +374,65 @@ class FieldOrder extends $pb.GeneratedMessage { void clearFieldId() => clearField(1); } -class CreateEditFieldContextParams extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateEditFieldContextParams', createEmptyInstance: create) +enum GetEditFieldContextParams_OneOfFieldId { + fieldId, + notSet +} + +class GetEditFieldContextParams extends $pb.GeneratedMessage { + static const $core.Map<$core.int, GetEditFieldContextParams_OneOfFieldId> _GetEditFieldContextParams_OneOfFieldIdByTag = { + 2 : GetEditFieldContextParams_OneOfFieldId.fieldId, + 0 : GetEditFieldContextParams_OneOfFieldId.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetEditFieldContextParams', createEmptyInstance: create) + ..oo(0, [2]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..e<$0.FieldType>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..e<$0.FieldType>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values) ..hasRequiredFields = false ; - CreateEditFieldContextParams._() : super(); - factory CreateEditFieldContextParams({ + GetEditFieldContextParams._() : super(); + factory GetEditFieldContextParams({ $core.String? gridId, + $core.String? fieldId, $0.FieldType? fieldType, }) { final _result = create(); if (gridId != null) { _result.gridId = gridId; } + if (fieldId != null) { + _result.fieldId = fieldId; + } if (fieldType != null) { _result.fieldType = fieldType; } return _result; } - factory CreateEditFieldContextParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CreateEditFieldContextParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory GetEditFieldContextParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetEditFieldContextParams.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') - CreateEditFieldContextParams clone() => CreateEditFieldContextParams()..mergeFromMessage(this); + GetEditFieldContextParams clone() => GetEditFieldContextParams()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CreateEditFieldContextParams copyWith(void Function(CreateEditFieldContextParams) updates) => super.copyWith((message) => updates(message as CreateEditFieldContextParams)) as CreateEditFieldContextParams; // ignore: deprecated_member_use + GetEditFieldContextParams copyWith(void Function(GetEditFieldContextParams) updates) => super.copyWith((message) => updates(message as GetEditFieldContextParams)) as GetEditFieldContextParams; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static CreateEditFieldContextParams create() => CreateEditFieldContextParams._(); - CreateEditFieldContextParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static GetEditFieldContextParams create() => GetEditFieldContextParams._(); + GetEditFieldContextParams createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static CreateEditFieldContextParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CreateEditFieldContextParams? _defaultInstance; + static GetEditFieldContextParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GetEditFieldContextParams? _defaultInstance; + + GetEditFieldContextParams_OneOfFieldId whichOneOfFieldId() => _GetEditFieldContextParams_OneOfFieldIdByTag[$_whichOneof(0)]!; + void clearOneOfFieldId() => clearField($_whichOneof(0)); @$pb.TagNumber(1) $core.String get gridId => $_getSZ(0); @@ -426,13 +444,22 @@ class CreateEditFieldContextParams extends $pb.GeneratedMessage { void clearGridId() => clearField(1); @$pb.TagNumber(2) - $0.FieldType get fieldType => $_getN(1); + $core.String get fieldId => $_getSZ(1); @$pb.TagNumber(2) - set fieldType($0.FieldType v) { setField(2, v); } + set fieldId($core.String v) { $_setString(1, v); } @$pb.TagNumber(2) - $core.bool hasFieldType() => $_has(1); + $core.bool hasFieldId() => $_has(1); @$pb.TagNumber(2) - void clearFieldType() => clearField(2); + void clearFieldId() => clearField(2); + + @$pb.TagNumber(3) + $0.FieldType get fieldType => $_getN(2); + @$pb.TagNumber(3) + set fieldType($0.FieldType v) { setField(3, v); } + @$pb.TagNumber(3) + $core.bool hasFieldType() => $_has(2); + @$pb.TagNumber(3) + void clearFieldType() => clearField(3); } class EditFieldContext extends $pb.GeneratedMessage { 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 3b7c58924e..713f10794c 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 @@ -68,17 +68,21 @@ const FieldOrder$json = const { /// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElk'); -@$core.Deprecated('Use createEditFieldContextParamsDescriptor instead') -const CreateEditFieldContextParams$json = const { - '1': 'CreateEditFieldContextParams', +@$core.Deprecated('Use getEditFieldContextParamsDescriptor instead') +const GetEditFieldContextParams$json = const { + '1': 'GetEditFieldContextParams', '2': const [ const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, - const {'1': 'field_type', '3': 2, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'}, + const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'fieldId'}, + const {'1': 'field_type', '3': 3, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'}, + ], + '8': const [ + const {'1': 'one_of_field_id'}, ], }; -/// Descriptor for `CreateEditFieldContextParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createEditFieldContextParamsDescriptor = $convert.base64Decode('ChxDcmVhdGVFZGl0RmllbGRDb250ZXh0UGFyYW1zEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIpCgpmaWVsZF90eXBlGAIgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGU='); +/// Descriptor for `GetEditFieldContextParams`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getEditFieldContextParamsDescriptor = $convert.base64Decode('ChlHZXRFZGl0RmllbGRDb250ZXh0UGFyYW1zEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIbCghmaWVsZF9pZBgCIAEoCUgAUgdmaWVsZElkEikKCmZpZWxkX3R5cGUYAyABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZUIRCg9vbmVfb2ZfZmllbGRfaWQ='); @$core.Deprecated('Use editFieldContextDescriptor instead') const EditFieldContext$json = const { '1': 'EditFieldContext', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 25319128d8..38b2bcf764 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -17,7 +17,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); - static const GridEvent CreateEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext'); + static const GridEvent GetEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetEditFieldContext'); static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption'); static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); @@ -31,7 +31,7 @@ class GridEvent extends $pb.ProtobufEnum { CreateField, DeleteField, DuplicateField, - CreateEditFieldContext, + GetEditFieldContext, CreateSelectOption, CreateRow, GetRow, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 747a591a02..fb883500d5 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -19,7 +19,7 @@ const GridEvent$json = const { const {'1': 'CreateField', '2': 12}, const {'1': 'DeleteField', '2': 13}, const {'1': 'DuplicateField', '2': 15}, - const {'1': 'CreateEditFieldContext', '2': 16}, + const {'1': 'GetEditFieldContext', '2': 16}, const {'1': 'CreateSelectOption', '2': 30}, const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, @@ -28,4 +28,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASFgoSQ3JlYXRlU2VsZWN0T3B0aW9uEB4SDQoJQ3JlYXRlUm93EDISCgoGR2V0Um93EDMSDgoKVXBkYXRlQ2VsbBBG'); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIXChNHZXRFZGl0RmllbGRDb250ZXh0EBASFgoSQ3JlYXRlU2VsZWN0T3B0aW9uEB4SDQoJQ3JlYXRlUm93EDISCgoGR2V0Um93EDMSDgoKVXBkYXRlQ2VsbBBG'); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index d29c2aec48..5ae05c4838 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,6 +1,7 @@ use crate::manager::GridManager; use crate::services::field::{type_option_data_from_str, SelectOption}; -use flowy_error::FlowyError; +use crate::services::grid_editor::ClientGridEditor; +use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; @@ -97,13 +98,14 @@ pub(crate) async fn create_select_option_handler( } #[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn create_edit_field_context_handler( - data: Data, +pub(crate) async fn edit_edit_field_context_handler( + data: Data, manager: AppData>, ) -> DataResult { - let params: CreateEditFieldContextParams = data.into_inner(); + let params: GetEditFieldContextParams = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let field_meta = editor.default_field_meta(¶ms.field_type).await?; + + let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; let type_option_data = type_option_data_from_str(&field_meta.type_option_json, &field_meta.field_type); let field: Field = field_meta.into(); let edit_context = EditFieldContext { @@ -114,6 +116,19 @@ pub(crate) async fn create_edit_field_context_handler( data_result(edit_context) } +async fn get_or_create_field_meta( + params: &GetEditFieldContextParams, + editor: Arc, +) -> FlowyResult { + if params.field_id.is_some() { + if let Some(field_meta) = editor.get_field(params.field_id.as_ref().unwrap()).await? { + return Ok(field_meta); + } + } + + editor.default_field_meta(¶ms.field_type).await +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_row_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 966423c7c7..ffc30cf7e1 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -15,7 +15,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::CreateField, create_field_handler) .event(GridEvent::DeleteField, delete_field_handler) .event(GridEvent::DuplicateField, duplicate_field_handler) - .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler) + .event(GridEvent::GetEditFieldContext, edit_edit_field_context_handler) .event(GridEvent::CreateSelectOption, create_select_option_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) @@ -48,8 +48,8 @@ pub enum GridEvent { #[event(input = "FieldIdentifierPayload")] DuplicateField = 15, - #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")] - CreateEditFieldContext = 16, + #[event(input = "GetEditFieldContextParams", output = "EditFieldContext")] + GetEditFieldContext = 16, #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] CreateSelectOption = 30, diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 2eab7357c5..62f0995df0 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -32,7 +32,7 @@ pub enum GridEvent { CreateField = 12, DeleteField = 13, DuplicateField = 15, - CreateEditFieldContext = 16, + GetEditFieldContext = 16, CreateSelectOption = 30, CreateRow = 50, GetRow = 51, @@ -53,7 +53,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 12 => ::std::option::Option::Some(GridEvent::CreateField), 13 => ::std::option::Option::Some(GridEvent::DeleteField), 15 => ::std::option::Option::Some(GridEvent::DuplicateField), - 16 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext), + 16 => ::std::option::Option::Some(GridEvent::GetEditFieldContext), 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption), 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), @@ -71,7 +71,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::CreateField, GridEvent::DeleteField, GridEvent::DuplicateField, - GridEvent::CreateEditFieldContext, + GridEvent::GetEditFieldContext, GridEvent::CreateSelectOption, GridEvent::CreateRow, GridEvent::GetRow, @@ -104,13 +104,13 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xe4\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xe1\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ - leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x1a\n\x16CreateE\ - ditFieldContext\x10\x10\x12\x16\n\x12CreateSelectOption\x10\x1e\x12\r\n\ - \tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10Fb\x06p\ - roto3\ + leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x17\n\x13GetEdit\ + FieldContext\x10\x10\x12\x16\n\x12CreateSelectOption\x10\x1e\x12\r\n\tCr\ + eateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10Fb\x06proto\ + 3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index ebc7ae6782..b977992b96 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -8,7 +8,7 @@ enum GridEvent { CreateField = 12; DeleteField = 13; DuplicateField = 15; - CreateEditFieldContext = 16; + GetEditFieldContext = 16; CreateSelectOption = 30; CreateRow = 50; GetRow = 51; 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 7ff089ff9b..295353c8d5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -53,24 +53,40 @@ impl ClientGridEditor { field, type_option_data, start_field_id, - .. + grid_id, } = params; - let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); - - let field_meta = FieldMeta { - id: field.id, - name: field.name, - desc: field.desc, - field_type: field.field_type, - frozen: field.frozen, - visibility: field.visibility, - width: field.width, - type_option_json, - }; - let _ = self - .modify(|grid| Ok(grid.create_field(field_meta, start_field_id)?)) + .modify(|grid| { + if grid.contain_field(&field.id) { + let changeset = FieldChangesetParams { + field_id: field.id, + grid_id, + name: Some(field.name), + desc: Some(field.desc), + field_type: Some(field.field_type), + frozen: Some(field.frozen), + visibility: Some(field.visibility), + width: Some(field.width), + type_option_data: Some(type_option_data), + }; + + Ok(grid.update_field(changeset)?) + } else { + let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); + let field_meta = FieldMeta { + id: field.id, + name: field.name, + desc: field.desc, + field_type: field.field_type, + frozen: field.frozen, + visibility: field.visibility, + width: field.width, + type_option_json, + }; + Ok(grid.create_field(field_meta, start_field_id)?) + } + }) .await?; let _ = self.notify_did_update_fields().await?; Ok(()) @@ -116,6 +132,13 @@ impl ClientGridEditor { Ok(()) } + pub async fn get_field(&self, field_id: &str) -> FlowyResult> { + match self.pad.read().await.get_field(field_id) { + None => Ok(None), + Some(field_meta) => Ok(Some(field_meta.clone())), + } + } + pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?; Ok(()) 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 a85b8d382a..1b88e52ef7 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -101,11 +101,14 @@ impl std::convert::From<&FieldMeta> for FieldOrder { } #[derive(Debug, Default, ProtoBuf)] -pub struct CreateEditFieldContextParams { +pub struct GetEditFieldContextParams { #[pb(index = 1)] pub grid_id: String, - #[pb(index = 2)] + #[pb(index = 2, one_of)] + pub field_id: Option, + + #[pb(index = 3)] pub field_type: FieldType, } 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 d55c5dac10..6fdc3205e1 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 @@ -1221,23 +1221,30 @@ impl ::protobuf::reflect::ProtobufValue for FieldOrder { } #[derive(PartialEq,Clone,Default)] -pub struct CreateEditFieldContextParams { +pub struct GetEditFieldContextParams { // message fields pub grid_id: ::std::string::String, pub field_type: super::meta::FieldType, + // message oneof groups + pub one_of_field_id: ::std::option::Option, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a CreateEditFieldContextParams { - fn default() -> &'a CreateEditFieldContextParams { - ::default_instance() +impl<'a> ::std::default::Default for &'a GetEditFieldContextParams { + fn default() -> &'a GetEditFieldContextParams { + ::default_instance() } } -impl CreateEditFieldContextParams { - pub fn new() -> CreateEditFieldContextParams { +#[derive(Clone,PartialEq,Debug)] +pub enum GetEditFieldContextParams_oneof_one_of_field_id { + field_id(::std::string::String), +} + +impl GetEditFieldContextParams { + pub fn new() -> GetEditFieldContextParams { ::std::default::Default::default() } @@ -1267,7 +1274,56 @@ impl CreateEditFieldContextParams { ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) } - // .FieldType field_type = 2; + // string field_id = 2; + + + pub fn get_field_id(&self) -> &str { + match self.one_of_field_id { + ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v)) => v, + _ => "", + } + } + pub fn clear_field_id(&mut self) { + self.one_of_field_id = ::std::option::Option::None; + } + + pub fn has_field_id(&self) -> bool { + match self.one_of_field_id { + ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(_)) = self.one_of_field_id { + } else { + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(::std::string::String::new())); + } + match self.one_of_field_id { + ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + if self.has_field_id() { + match self.one_of_field_id.take() { + ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } + + // .FieldType field_type = 3; pub fn get_field_type(&self) -> super::meta::FieldType { @@ -1283,7 +1339,7 @@ impl CreateEditFieldContextParams { } } -impl ::protobuf::Message for CreateEditFieldContextParams { +impl ::protobuf::Message for GetEditFieldContextParams { fn is_initialized(&self) -> bool { true } @@ -1296,7 +1352,13 @@ impl ::protobuf::Message for CreateEditFieldContextParams { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; }, 2 => { - ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 2, &mut self.unknown_fields)? + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(is.read_string()?)); + }, + 3 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 3, &mut self.unknown_fields)? }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -1314,7 +1376,14 @@ impl ::protobuf::Message for CreateEditFieldContextParams { my_size += ::protobuf::rt::string_size(1, &self.grid_id); } if self.field_type != super::meta::FieldType::RichText { - my_size += ::protobuf::rt::enum_size(2, self.field_type); + my_size += ::protobuf::rt::enum_size(3, self.field_type); + } + if let ::std::option::Option::Some(ref v) = self.one_of_field_id { + match v { + &GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v) => { + my_size += ::protobuf::rt::string_size(2, &v); + }, + }; } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1326,7 +1395,14 @@ impl ::protobuf::Message for CreateEditFieldContextParams { os.write_string(1, &self.grid_id)?; } if self.field_type != super::meta::FieldType::RichText { - os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.field_type))?; + os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.field_type))?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_field_id { + match v { + &GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v) => { + os.write_string(2, v)?; + }, + }; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1358,8 +1434,8 @@ impl ::protobuf::Message for CreateEditFieldContextParams { Self::descriptor_static() } - fn new() -> CreateEditFieldContextParams { - CreateEditFieldContextParams::new() + fn new() -> GetEditFieldContextParams { + GetEditFieldContextParams::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -1368,43 +1444,49 @@ impl ::protobuf::Message for CreateEditFieldContextParams { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "grid_id", - |m: &CreateEditFieldContextParams| { &m.grid_id }, - |m: &mut CreateEditFieldContextParams| { &mut m.grid_id }, + |m: &GetEditFieldContextParams| { &m.grid_id }, + |m: &mut GetEditFieldContextParams| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "field_id", + GetEditFieldContextParams::has_field_id, + GetEditFieldContextParams::get_field_id, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "field_type", - |m: &CreateEditFieldContextParams| { &m.field_type }, - |m: &mut CreateEditFieldContextParams| { &mut m.field_type }, + |m: &GetEditFieldContextParams| { &m.field_type }, + |m: &mut GetEditFieldContextParams| { &mut m.field_type }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CreateEditFieldContextParams", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "GetEditFieldContextParams", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static CreateEditFieldContextParams { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CreateEditFieldContextParams::new) + fn default_instance() -> &'static GetEditFieldContextParams { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(GetEditFieldContextParams::new) } } -impl ::protobuf::Clear for CreateEditFieldContextParams { +impl ::protobuf::Clear for GetEditFieldContextParams { fn clear(&mut self) { self.grid_id.clear(); + self.one_of_field_id = ::std::option::Option::None; self.field_type = super::meta::FieldType::RichText; self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for CreateEditFieldContextParams { +impl ::std::fmt::Debug for GetEditFieldContextParams { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for CreateEditFieldContextParams { +impl ::protobuf::reflect::ProtobufValue for GetEditFieldContextParams { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -5431,48 +5513,49 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"K\n\x15FieldIdentifierParams\ \x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\ id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFieldContextParams\x12\ - \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\nfield_type\x18\ - \x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\x12\ - \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\x18\ - \x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\x18\ - \x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\x05it\ - ems\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\ - \x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\n\x08\ - RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\ - lock_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\x03\x20\ - \x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\ - \tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellB\ - yFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\ - \x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01\ - (\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\ - \x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\ - \x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05items\x18\x01\ - \x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\x19\n\ - \x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\x0e\n\ - \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ - 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ - \x01(\tR\x07fieldId\x12\x18\n\x07content\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(\t\ - R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ - lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ - \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ - idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ - \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ - rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ - \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ - \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ - \x0cstartFieldIdB\x17\n\x15one_of_start_field_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\"e\n\ - \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ - ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ - \x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ - \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ - kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"<\n\x19CreateSelec\ - tOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionNameb\ - \x06proto3\ + \x18\x01\x20\x01(\tR\x07fieldId\"\x8f\x01\n\x19GetEditFieldContextParams\ + \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\x08field_i\ + d\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\ + \x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"|\n\x10EditFiel\ + dContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid\ + _field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option\ + _data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\ + \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\ + edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\ + ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\ + \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\ + t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\ + \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\ + \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\ + \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ + .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ + \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ + items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ + \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ + \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ + \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ + \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\ + 2\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\ + RowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\ + \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\ + \x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\ + \x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\ + \x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\ + \x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ + \x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\ + \x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\ + \x0f.GridBlockOrderR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\ + \x20\x01(\tR\x07blockId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\ + \"<\n\x19CreateSelectOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\ + \x01(\tR\noptionNameb\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 5c07b98d30..cba28ad711 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 @@ -26,9 +26,10 @@ message FieldIdentifierParams { message FieldOrder { string field_id = 1; } -message CreateEditFieldContextParams { +message GetEditFieldContextParams { string grid_id = 1; - FieldType field_type = 2; + oneof one_of_field_id { string field_id = 2; }; + FieldType field_type = 3; } message EditFieldContext { string grid_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 78c0091b57..d3e407a763 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -45,7 +45,7 @@ impl GridMetaPad { self.modify_grid(|grid| { // Check if the field exists or not if grid.fields.iter().any(|field_meta| field_meta.id == new_field_meta.id) { - tracing::warn!("Duplicate grid field"); + tracing::error!("Duplicate grid field"); return Ok(None); } From 80f82fa5b1a95f71effcf6c2e8afc308e9bae427 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 1 Apr 2022 09:31:10 +0800 Subject: [PATCH 23/47] chore: update field type option data using deserializer --- .../application/grid/field/field_service.dart | 12 +- .../grid/field/switch_field_type_bloc.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 19 +- .../flowy-grid-data-model/grid.pb.dart | 111 ++++- .../flowy-grid-data-model/grid.pbjson.dart | 22 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 2 + .../protobuf/flowy-grid/event_map.pbjson.dart | 3 +- .../rust-lib/flowy-grid/src/event_handler.rs | 19 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 8 +- .../src/protobuf/model/event_map.rs | 13 +- .../src/protobuf/proto/event_map.proto | 1 + .../flowy-grid/src/services/grid_editor.rs | 41 +- .../src/entities/grid.rs | 34 +- .../src/protobuf/model/grid.rs | 391 ++++++++++++++---- .../src/protobuf/proto/grid.proto | 7 +- .../src/client_grid/grid_meta_pad.rs | 12 +- 16 files changed, 558 insertions(+), 139 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index b38d9ffba1..5bb80a0119 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -10,12 +10,13 @@ class FieldService { FieldService({required this.gridId}); - Future> getEditFieldContext(FieldType fieldType) { - final payload = GetEditFieldContextParams.create() + Future> switchToField(String fieldId, FieldType fieldType) { + final payload = EditFieldPayload.create() ..gridId = gridId + ..fieldId = fieldId ..fieldType = fieldType; - return GridEventGetEditFieldContext(payload).send(); + return GridEventSwitchToField(payload).send(); } Future> updateField({ @@ -58,6 +59,7 @@ class FieldService { return GridEventUpdateField(payload).send(); } + // Create the field if it does not exist. Otherwise, update the field. Future> createField({ required Field field, List? typeOptionData, @@ -121,7 +123,7 @@ class NewFieldContextLoader extends FieldContextLoader { @override Future> load() { - final payload = GetEditFieldContextParams.create() + final payload = GetEditFieldContextPayload.create() ..gridId = gridId ..fieldType = FieldType.RichText; @@ -136,7 +138,7 @@ class FieldContextLoaderAdaptor extends FieldContextLoader { @override Future> load() { - final payload = GetEditFieldContextParams.create() + final payload = GetEditFieldContextPayload.create() ..gridId = data.gridId ..fieldId = data.field.id ..fieldType = data.field.fieldType; diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart index 1bb2bb18ce..edb0732ddf 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart @@ -16,7 +16,7 @@ class FieldSwitchBloc extends Bloc { await event.map( toFieldType: (_ToFieldType value) async { final fieldService = FieldService(gridId: state.gridId); - final result = await fieldService.getEditFieldContext(value.fieldType); + final result = await fieldService.switchToField(state.field.id, value.fieldType); result.fold( (newEditContext) { final typeOptionData = Uint8List.fromList(newEditContext.typeOptionData); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 5f34777079..45b33f1004 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -103,6 +103,23 @@ class GridEventDeleteField { } } +class GridEventSwitchToField { + EditFieldPayload request; + GridEventSwitchToField(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.SwitchToField.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(EditFieldContext.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventDuplicateField { FieldIdentifierPayload request; GridEventDuplicateField(this.request); @@ -121,7 +138,7 @@ class GridEventDuplicateField { } class GridEventGetEditFieldContext { - GetEditFieldContextParams request; + GetEditFieldContextPayload request; GridEventGetEditFieldContext(this.request); Future> send() { 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 cd3c552036..7fcee422d7 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 @@ -374,17 +374,17 @@ class FieldOrder extends $pb.GeneratedMessage { void clearFieldId() => clearField(1); } -enum GetEditFieldContextParams_OneOfFieldId { +enum GetEditFieldContextPayload_OneOfFieldId { fieldId, notSet } -class GetEditFieldContextParams extends $pb.GeneratedMessage { - static const $core.Map<$core.int, GetEditFieldContextParams_OneOfFieldId> _GetEditFieldContextParams_OneOfFieldIdByTag = { - 2 : GetEditFieldContextParams_OneOfFieldId.fieldId, - 0 : GetEditFieldContextParams_OneOfFieldId.notSet +class GetEditFieldContextPayload extends $pb.GeneratedMessage { + static const $core.Map<$core.int, GetEditFieldContextPayload_OneOfFieldId> _GetEditFieldContextPayload_OneOfFieldIdByTag = { + 2 : GetEditFieldContextPayload_OneOfFieldId.fieldId, + 0 : GetEditFieldContextPayload_OneOfFieldId.notSet }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetEditFieldContextParams', createEmptyInstance: create) + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetEditFieldContextPayload', createEmptyInstance: create) ..oo(0, [2]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') @@ -392,8 +392,8 @@ class GetEditFieldContextParams extends $pb.GeneratedMessage { ..hasRequiredFields = false ; - GetEditFieldContextParams._() : super(); - factory GetEditFieldContextParams({ + GetEditFieldContextPayload._() : super(); + factory GetEditFieldContextPayload({ $core.String? gridId, $core.String? fieldId, $0.FieldType? fieldType, @@ -410,28 +410,28 @@ class GetEditFieldContextParams extends $pb.GeneratedMessage { } return _result; } - factory GetEditFieldContextParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory GetEditFieldContextParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory GetEditFieldContextPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetEditFieldContextPayload.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') - GetEditFieldContextParams clone() => GetEditFieldContextParams()..mergeFromMessage(this); + GetEditFieldContextPayload clone() => GetEditFieldContextPayload()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - GetEditFieldContextParams copyWith(void Function(GetEditFieldContextParams) updates) => super.copyWith((message) => updates(message as GetEditFieldContextParams)) as GetEditFieldContextParams; // ignore: deprecated_member_use + GetEditFieldContextPayload copyWith(void Function(GetEditFieldContextPayload) updates) => super.copyWith((message) => updates(message as GetEditFieldContextPayload)) as GetEditFieldContextPayload; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static GetEditFieldContextParams create() => GetEditFieldContextParams._(); - GetEditFieldContextParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static GetEditFieldContextPayload create() => GetEditFieldContextPayload._(); + GetEditFieldContextPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static GetEditFieldContextParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static GetEditFieldContextParams? _defaultInstance; + static GetEditFieldContextPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GetEditFieldContextPayload? _defaultInstance; - GetEditFieldContextParams_OneOfFieldId whichOneOfFieldId() => _GetEditFieldContextParams_OneOfFieldIdByTag[$_whichOneof(0)]!; + GetEditFieldContextPayload_OneOfFieldId whichOneOfFieldId() => _GetEditFieldContextPayload_OneOfFieldIdByTag[$_whichOneof(0)]!; void clearOneOfFieldId() => clearField($_whichOneof(0)); @$pb.TagNumber(1) @@ -462,6 +462,81 @@ class GetEditFieldContextParams extends $pb.GeneratedMessage { void clearFieldType() => clearField(3); } +class EditFieldPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditFieldPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..e<$0.FieldType>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: $0.FieldType.RichText, valueOf: $0.FieldType.valueOf, enumValues: $0.FieldType.values) + ..hasRequiredFields = false + ; + + EditFieldPayload._() : super(); + factory EditFieldPayload({ + $core.String? gridId, + $core.String? fieldId, + $0.FieldType? fieldType, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (fieldType != null) { + _result.fieldType = fieldType; + } + return _result; + } + factory EditFieldPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory EditFieldPayload.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') + EditFieldPayload clone() => EditFieldPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + EditFieldPayload copyWith(void Function(EditFieldPayload) updates) => super.copyWith((message) => updates(message as EditFieldPayload)) as EditFieldPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static EditFieldPayload create() => EditFieldPayload._(); + EditFieldPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static EditFieldPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static EditFieldPayload? _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 fieldId => $_getSZ(1); + @$pb.TagNumber(2) + set fieldId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasFieldId() => $_has(1); + @$pb.TagNumber(2) + void clearFieldId() => clearField(2); + + @$pb.TagNumber(3) + $0.FieldType get fieldType => $_getN(2); + @$pb.TagNumber(3) + set fieldType($0.FieldType v) { setField(3, v); } + @$pb.TagNumber(3) + $core.bool hasFieldType() => $_has(2); + @$pb.TagNumber(3) + void clearFieldType() => clearField(3); +} + class EditFieldContext extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditFieldContext', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') 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 713f10794c..596c7f6fc1 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 @@ -68,9 +68,9 @@ const FieldOrder$json = const { /// Descriptor for `FieldOrder`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldOrderDescriptor = $convert.base64Decode('CgpGaWVsZE9yZGVyEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElk'); -@$core.Deprecated('Use getEditFieldContextParamsDescriptor instead') -const GetEditFieldContextParams$json = const { - '1': 'GetEditFieldContextParams', +@$core.Deprecated('Use getEditFieldContextPayloadDescriptor instead') +const GetEditFieldContextPayload$json = const { + '1': 'GetEditFieldContextPayload', '2': const [ const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'fieldId'}, @@ -81,8 +81,20 @@ const GetEditFieldContextParams$json = const { ], }; -/// Descriptor for `GetEditFieldContextParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List getEditFieldContextParamsDescriptor = $convert.base64Decode('ChlHZXRFZGl0RmllbGRDb250ZXh0UGFyYW1zEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIbCghmaWVsZF9pZBgCIAEoCUgAUgdmaWVsZElkEikKCmZpZWxkX3R5cGUYAyABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZUIRCg9vbmVfb2ZfZmllbGRfaWQ='); +/// Descriptor for `GetEditFieldContextPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getEditFieldContextPayloadDescriptor = $convert.base64Decode('ChpHZXRFZGl0RmllbGRDb250ZXh0UGF5bG9hZBIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSGwoIZmllbGRfaWQYAiABKAlIAFIHZmllbGRJZBIpCgpmaWVsZF90eXBlGAMgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGVCEQoPb25lX29mX2ZpZWxkX2lk'); +@$core.Deprecated('Use editFieldPayloadDescriptor instead') +const EditFieldPayload$json = const { + '1': 'EditFieldPayload', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'field_type', '3': 3, '4': 1, '5': 14, '6': '.FieldType', '10': 'fieldType'}, + ], +}; + +/// Descriptor for `EditFieldPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List editFieldPayloadDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIZCghmaWVsZF9pZBgCIAEoCVIHZmllbGRJZBIpCgpmaWVsZF90eXBlGAMgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGU='); @$core.Deprecated('Use editFieldContextDescriptor instead') const EditFieldContext$json = const { '1': 'EditFieldContext', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 38b2bcf764..7d69a59524 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -16,6 +16,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField'); static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField'); static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); + static const GridEvent SwitchToField = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SwitchToField'); static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); static const GridEvent GetEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetEditFieldContext'); static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption'); @@ -30,6 +31,7 @@ class GridEvent extends $pb.ProtobufEnum { UpdateField, CreateField, DeleteField, + SwitchToField, DuplicateField, GetEditFieldContext, CreateSelectOption, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index fb883500d5..dc5ca350b6 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -18,6 +18,7 @@ const GridEvent$json = const { const {'1': 'UpdateField', '2': 11}, const {'1': 'CreateField', '2': 12}, const {'1': 'DeleteField', '2': 13}, + const {'1': 'SwitchToField', '2': 14}, const {'1': 'DuplicateField', '2': 15}, const {'1': 'GetEditFieldContext', '2': 16}, const {'1': 'CreateSelectOption', '2': 30}, @@ -28,4 +29,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIXChNHZXRFZGl0RmllbGRDb250ZXh0EBASFgoSQ3JlYXRlU2VsZWN0T3B0aW9uEB4SDQoJQ3JlYXRlUm93EDISCgoGR2V0Um93EDMSDgoKVXBkYXRlQ2VsbBBG'); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg4KClVwZGF0ZUNlbGwQRg=='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 5ae05c4838..25f11c3010 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -78,6 +78,17 @@ pub(crate) async fn delete_field_handler( Ok(()) } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn switch_to_field_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: EditFieldParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let edit_context = editor.switch_to_field_type(¶ms.field_id, params.field_type).await?; + data_result(edit_context) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn duplicate_field_handler( data: Data, @@ -98,11 +109,11 @@ pub(crate) async fn create_select_option_handler( } #[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn edit_edit_field_context_handler( - data: Data, +pub(crate) async fn get_field_context_handler( + data: Data, manager: AppData>, ) -> DataResult { - let params: GetEditFieldContextParams = data.into_inner(); + let params = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; @@ -117,7 +128,7 @@ pub(crate) async fn edit_edit_field_context_handler( } async fn get_or_create_field_meta( - params: &GetEditFieldContextParams, + params: &GetEditFieldContextPayload, editor: Arc, ) -> FlowyResult { if params.field_id.is_some() { diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index ffc30cf7e1..5183b8afb7 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -14,8 +14,9 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) .event(GridEvent::DeleteField, delete_field_handler) + .event(GridEvent::SwitchToField, switch_to_field_handler) .event(GridEvent::DuplicateField, duplicate_field_handler) - .event(GridEvent::GetEditFieldContext, edit_edit_field_context_handler) + .event(GridEvent::GetEditFieldContext, get_field_context_handler) .event(GridEvent::CreateSelectOption, create_select_option_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) @@ -45,10 +46,13 @@ pub enum GridEvent { #[event(input = "FieldIdentifierPayload")] DeleteField = 13, + #[event(input = "EditFieldPayload", output = "EditFieldContext")] + SwitchToField = 14, + #[event(input = "FieldIdentifierPayload")] DuplicateField = 15, - #[event(input = "GetEditFieldContextParams", output = "EditFieldContext")] + #[event(input = "GetEditFieldContextPayload", output = "EditFieldContext")] GetEditFieldContext = 16, #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 62f0995df0..368c4df718 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -31,6 +31,7 @@ pub enum GridEvent { UpdateField = 11, CreateField = 12, DeleteField = 13, + SwitchToField = 14, DuplicateField = 15, GetEditFieldContext = 16, CreateSelectOption = 30, @@ -52,6 +53,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 11 => ::std::option::Option::Some(GridEvent::UpdateField), 12 => ::std::option::Option::Some(GridEvent::CreateField), 13 => ::std::option::Option::Some(GridEvent::DeleteField), + 14 => ::std::option::Option::Some(GridEvent::SwitchToField), 15 => ::std::option::Option::Some(GridEvent::DuplicateField), 16 => ::std::option::Option::Some(GridEvent::GetEditFieldContext), 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption), @@ -70,6 +72,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::UpdateField, GridEvent::CreateField, GridEvent::DeleteField, + GridEvent::SwitchToField, GridEvent::DuplicateField, GridEvent::GetEditFieldContext, GridEvent::CreateSelectOption, @@ -104,13 +107,13 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xe1\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xf4\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ - leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x17\n\x13GetEdit\ - FieldContext\x10\x10\x12\x16\n\x12CreateSelectOption\x10\x1e\x12\r\n\tCr\ - eateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10Fb\x06proto\ - 3\ + leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ + ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x16\n\x12Creat\ + eSelectOption\x10\x1e\x12\r\n\tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\ + \x0e\n\nUpdateCell\x10Fb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index b977992b96..9d2ea5961f 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -7,6 +7,7 @@ enum GridEvent { UpdateField = 11; CreateField = 12; DeleteField = 13; + SwitchToField = 14; DuplicateField = 15; GetEditFieldContext = 16; CreateSelectOption = 30; 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 295353c8d5..3b48f244d5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -7,8 +7,9 @@ use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; -use flowy_sync::client_grid::{GridChangeset, GridMetaPad}; +use flowy_sync::client_grid::{GridChangeset, GridMetaPad, TypeOptionDataDeserializer}; use flowy_sync::entities::revision::Revision; +use flowy_sync::errors::CollaborateResult; use flowy_sync::util::make_delta_from_revisions; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; @@ -59,6 +60,7 @@ impl ClientGridEditor { let _ = self .modify(|grid| { if grid.contain_field(&field.id) { + let deserializer = TypeOptionChangesetDeserializer(field.field_type.clone()); let changeset = FieldChangesetParams { field_id: field.id, grid_id, @@ -70,8 +72,7 @@ impl ClientGridEditor { width: Some(field.width), type_option_data: Some(type_option_data), }; - - Ok(grid.update_field(changeset)?) + Ok(grid.update_field(changeset, deserializer)?) } else { let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); let field_meta = FieldMeta { @@ -103,19 +104,12 @@ impl ClientGridEditor { } pub async fn update_field(&self, mut params: FieldChangesetParams) -> FlowyResult<()> { - if let Some(type_option_data) = params.type_option_data { - match self.pad.read().await.get_field(¶ms.field_id) { - None => return Err(ErrorCode::FieldDoesNotExist.into()), - Some(field_meta) => { - // The type_option_data is serialized by protobuf. But the type_option_data should be - // serialized by utf-8 encoding. So we must transform the data here. - let type_option_json = type_option_json_str_from_bytes(type_option_data, &field_meta.field_type); - params.type_option_data = Some(type_option_json.as_bytes().to_vec()); - } - } - } + let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { + None => return Err(ErrorCode::FieldDoesNotExist.into()), + Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), + }; - let _ = self.modify(|grid| Ok(grid.update_field(params)?)).await?; + let _ = self.modify(|grid| Ok(grid.update_field(params, deserializer)?)).await?; let _ = self.notify_did_update_fields().await?; Ok(()) } @@ -126,6 +120,12 @@ impl ClientGridEditor { Ok(()) } + pub async fn switch_to_field_type(&self, field_id: &str, field_type: FieldType) -> FlowyResult { + let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?; + let _ = self.notify_did_update_fields().await?; + todo!() + } + pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.duplicate_field(field_id)?)).await?; let _ = self.notify_did_update_fields().await?; @@ -402,3 +402,14 @@ impl RevisionCompactor for GridRevisionCompactor { Ok(delta.to_delta_bytes()) } } + +struct TypeOptionChangesetDeserializer(FieldType); +impl TypeOptionDataDeserializer for TypeOptionChangesetDeserializer { + fn deserialize(&self, type_option_data: Vec) -> CollaborateResult { + // The type_option_data is serialized by protobuf. But the type_option_data should be + // serialized by utf-8. So we must transform the data here. + + let type_option_json = type_option_json_str_from_bytes(type_option_data, &self.0); + Ok(type_option_json) + } +} 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 1b88e52ef7..b60aafedae 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -101,7 +101,7 @@ impl std::convert::From<&FieldMeta> for FieldOrder { } #[derive(Debug, Default, ProtoBuf)] -pub struct GetEditFieldContextParams { +pub struct GetEditFieldContextPayload { #[pb(index = 1)] pub grid_id: String, @@ -112,6 +112,38 @@ pub struct GetEditFieldContextParams { pub field_type: FieldType, } +#[derive(Debug, Default, ProtoBuf)] +pub struct EditFieldPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field_id: String, + + #[pb(index = 3)] + pub field_type: FieldType, +} + +pub struct EditFieldParams { + pub grid_id: String, + pub field_id: String, + pub field_type: FieldType, +} + +impl TryInto for EditFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + Ok(EditFieldParams { + grid_id: grid_id.0, + field_id: field_id.0, + field_type: self.field_type, + }) + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct EditFieldContext { #[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 6fdc3205e1..7d13585c86 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 @@ -1221,30 +1221,30 @@ impl ::protobuf::reflect::ProtobufValue for FieldOrder { } #[derive(PartialEq,Clone,Default)] -pub struct GetEditFieldContextParams { +pub struct GetEditFieldContextPayload { // message fields pub grid_id: ::std::string::String, pub field_type: super::meta::FieldType, // message oneof groups - pub one_of_field_id: ::std::option::Option, + pub one_of_field_id: ::std::option::Option, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a GetEditFieldContextParams { - fn default() -> &'a GetEditFieldContextParams { - ::default_instance() +impl<'a> ::std::default::Default for &'a GetEditFieldContextPayload { + fn default() -> &'a GetEditFieldContextPayload { + ::default_instance() } } #[derive(Clone,PartialEq,Debug)] -pub enum GetEditFieldContextParams_oneof_one_of_field_id { +pub enum GetEditFieldContextPayload_oneof_one_of_field_id { field_id(::std::string::String), } -impl GetEditFieldContextParams { - pub fn new() -> GetEditFieldContextParams { +impl GetEditFieldContextPayload { + pub fn new() -> GetEditFieldContextPayload { ::std::default::Default::default() } @@ -1279,7 +1279,7 @@ impl GetEditFieldContextParams { pub fn get_field_id(&self) -> &str { match self.one_of_field_id { - ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v)) => v, + ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(ref v)) => v, _ => "", } } @@ -1289,24 +1289,24 @@ impl GetEditFieldContextParams { pub fn has_field_id(&self) -> bool { match self.one_of_field_id { - ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(..)) => true, + ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_field_id(&mut self, v: ::std::string::String) { - self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(v)) + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(v)) } // Mutable pointer to the field. pub fn mut_field_id(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(_)) = self.one_of_field_id { + if let ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(_)) = self.one_of_field_id { } else { - self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(::std::string::String::new())); + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(::std::string::String::new())); } match self.one_of_field_id { - ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref mut v)) => v, + ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(ref mut v)) => v, _ => panic!(), } } @@ -1315,7 +1315,7 @@ impl GetEditFieldContextParams { pub fn take_field_id(&mut self) -> ::std::string::String { if self.has_field_id() { match self.one_of_field_id.take() { - ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(v)) => v, + ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(v)) => v, _ => panic!(), } } else { @@ -1339,7 +1339,7 @@ impl GetEditFieldContextParams { } } -impl ::protobuf::Message for GetEditFieldContextParams { +impl ::protobuf::Message for GetEditFieldContextPayload { fn is_initialized(&self) -> bool { true } @@ -1355,7 +1355,7 @@ impl ::protobuf::Message for GetEditFieldContextParams { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextParams_oneof_one_of_field_id::field_id(is.read_string()?)); + self.one_of_field_id = ::std::option::Option::Some(GetEditFieldContextPayload_oneof_one_of_field_id::field_id(is.read_string()?)); }, 3 => { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 3, &mut self.unknown_fields)? @@ -1380,7 +1380,7 @@ impl ::protobuf::Message for GetEditFieldContextParams { } if let ::std::option::Option::Some(ref v) = self.one_of_field_id { match v { - &GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v) => { + &GetEditFieldContextPayload_oneof_one_of_field_id::field_id(ref v) => { my_size += ::protobuf::rt::string_size(2, &v); }, }; @@ -1399,7 +1399,7 @@ impl ::protobuf::Message for GetEditFieldContextParams { } if let ::std::option::Option::Some(ref v) = self.one_of_field_id { match v { - &GetEditFieldContextParams_oneof_one_of_field_id::field_id(ref v) => { + &GetEditFieldContextPayload_oneof_one_of_field_id::field_id(ref v) => { os.write_string(2, v)?; }, }; @@ -1434,8 +1434,8 @@ impl ::protobuf::Message for GetEditFieldContextParams { Self::descriptor_static() } - fn new() -> GetEditFieldContextParams { - GetEditFieldContextParams::new() + fn new() -> GetEditFieldContextPayload { + GetEditFieldContextPayload::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -1444,34 +1444,34 @@ impl ::protobuf::Message for GetEditFieldContextParams { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "grid_id", - |m: &GetEditFieldContextParams| { &m.grid_id }, - |m: &mut GetEditFieldContextParams| { &mut m.grid_id }, + |m: &GetEditFieldContextPayload| { &m.grid_id }, + |m: &mut GetEditFieldContextPayload| { &mut m.grid_id }, )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "field_id", - GetEditFieldContextParams::has_field_id, - GetEditFieldContextParams::get_field_id, + GetEditFieldContextPayload::has_field_id, + GetEditFieldContextPayload::get_field_id, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "field_type", - |m: &GetEditFieldContextParams| { &m.field_type }, - |m: &mut GetEditFieldContextParams| { &mut m.field_type }, + |m: &GetEditFieldContextPayload| { &m.field_type }, + |m: &mut GetEditFieldContextPayload| { &mut m.field_type }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "GetEditFieldContextParams", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "GetEditFieldContextPayload", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static GetEditFieldContextParams { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(GetEditFieldContextParams::new) + fn default_instance() -> &'static GetEditFieldContextPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(GetEditFieldContextPayload::new) } } -impl ::protobuf::Clear for GetEditFieldContextParams { +impl ::protobuf::Clear for GetEditFieldContextPayload { fn clear(&mut self) { self.grid_id.clear(); self.one_of_field_id = ::std::option::Option::None; @@ -1480,13 +1480,245 @@ impl ::protobuf::Clear for GetEditFieldContextParams { } } -impl ::std::fmt::Debug for GetEditFieldContextParams { +impl ::std::fmt::Debug for GetEditFieldContextPayload { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for GetEditFieldContextParams { +impl ::protobuf::reflect::ProtobufValue for GetEditFieldContextPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct EditFieldPayload { + // message fields + pub grid_id: ::std::string::String, + pub field_id: ::std::string::String, + pub field_type: super::meta::FieldType, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a EditFieldPayload { + fn default() -> &'a EditFieldPayload { + ::default_instance() + } +} + +impl EditFieldPayload { + pub fn new() -> EditFieldPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string field_id = 2; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // .FieldType field_type = 3; + + + pub fn get_field_type(&self) -> super::meta::FieldType { + self.field_type + } + pub fn clear_field_type(&mut self) { + self.field_type = super::meta::FieldType::RichText; + } + + // Param is passed by value, moved + pub fn set_field_type(&mut self, v: super::meta::FieldType) { + self.field_type = v; + } +} + +impl ::protobuf::Message for EditFieldPayload { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 3 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.field_type, 3, &mut self.unknown_fields)? + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.field_id); + } + if self.field_type != super::meta::FieldType::RichText { + my_size += ::protobuf::rt::enum_size(3, self.field_type); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.field_id.is_empty() { + os.write_string(2, &self.field_id)?; + } + if self.field_type != super::meta::FieldType::RichText { + os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.field_type))?; + } + 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() -> EditFieldPayload { + EditFieldPayload::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>( + "grid_id", + |m: &EditFieldPayload| { &m.grid_id }, + |m: &mut EditFieldPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &EditFieldPayload| { &m.field_id }, + |m: &mut EditFieldPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "field_type", + |m: &EditFieldPayload| { &m.field_type }, + |m: &mut EditFieldPayload| { &mut m.field_type }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "EditFieldPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static EditFieldPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(EditFieldPayload::new) + } +} + +impl ::protobuf::Clear for EditFieldPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.field_id.clear(); + self.field_type = super::meta::FieldType::RichText; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for EditFieldPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for EditFieldPayload { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -5513,49 +5745,52 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"K\n\x15FieldIdentifierParams\ \x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\ id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\"\x8f\x01\n\x19GetEditFieldContextParams\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\x08field_i\ - d\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\ - \x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"|\n\x10EditFiel\ - dContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid\ - _field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option\ - _data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\ - \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\ - edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\ - ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\ - \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\ - t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\ - \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\ - \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\ - \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ - \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ - .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ - \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ - items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ - \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ - \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ - \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ - \x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\ - 2\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\ - RowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\ - \x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\ - \x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\ - \x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\ - \x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\ - \x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\ - \x0f.GridBlockOrderR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\ - \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\ - \x20\x01(\tR\x07blockId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\ - \"<\n\x19CreateSelectOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\ - \x01(\tR\noptionNameb\x06proto3\ + \x18\x01\x20\x01(\tR\x07fieldId\"\x90\x01\n\x1aGetEditFieldContextPayloa\ + d\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\x08field_\ + id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\ + \x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"q\n\x10EditFiel\ + dPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\ + \x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\nfield_type\x18\x03\ + \x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\x12\x17\ + \n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\x18\x02\ + \x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\x18\x03\ + \x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\x05items\ + \x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\ + \x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\n\x08\ + RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\ + lock_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\x03\x20\ + \x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\ + \tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellB\ + yFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\ + \x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01\ + (\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\ + \x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\ + \x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05items\x18\x01\ + \x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\x19\n\ + \x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\x0e\n\ + \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ + 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ + \x01(\tR\x07fieldId\x12\x18\n\x07content\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(\t\ + R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ + lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ + \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ + idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ + \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ + rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ + \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ + \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ + \x0cstartFieldIdB\x17\n\x15one_of_start_field_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\"e\n\ + \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ + ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ + \x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ + \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ + kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"<\n\x19CreateSelec\ + tOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionNameb\ + \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 cba28ad711..6e4a4f31cf 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 @@ -26,11 +26,16 @@ message FieldIdentifierParams { message FieldOrder { string field_id = 1; } -message GetEditFieldContextParams { +message GetEditFieldContextPayload { string grid_id = 1; oneof one_of_field_id { string field_id = 2; }; FieldType field_type = 3; } +message EditFieldPayload { + string grid_id = 1; + string field_id = 2; + FieldType field_type = 3; +} message EditFieldContext { string grid_id = 1; Field grid_field = 2; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index d3e407a763..362fe924b0 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -20,6 +20,10 @@ pub struct GridMetaPad { pub(crate) delta: GridMetaDelta, } +pub trait TypeOptionDataDeserializer { + fn deserialize(&self, type_option_data: Vec) -> CollaborateResult; +} + impl GridMetaPad { pub fn from_delta(delta: GridMetaDelta) -> CollaborateResult { let s = delta.to_str()?; @@ -85,7 +89,11 @@ impl GridMetaPad { }) } - pub fn update_field(&mut self, changeset: FieldChangesetParams) -> CollaborateResult> { + pub fn update_field( + &mut self, + changeset: FieldChangesetParams, + deserializer: T, + ) -> CollaborateResult> { let field_id = changeset.field_id.clone(); self.modify_field(&field_id, |field| { let mut is_changed = None; @@ -120,7 +128,7 @@ impl GridMetaPad { } if let Some(type_option_data) = changeset.type_option_data { - match String::from_utf8(type_option_data) { + match deserializer.deserialize(type_option_data) { Ok(type_option_json) => { field.type_option_json = type_option_json; is_changed = Some(()) From e0b969595cae57835333529d9c75b74041628259 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 1 Apr 2022 16:38:51 +0800 Subject: [PATCH 24/47] chore: save type option data as map --- .../flowy-grid-data-model/meta.pb.dart | 59 +++- .../flowy-grid-data-model/meta.pbjson.dart | 25 +- .../rust-lib/flowy-grid/src/event_handler.rs | 8 +- frontend/rust-lib/flowy-grid/src/macros.rs | 84 ++--- .../src/services/field/field_builder.rs | 54 ++-- .../type_options/checkbox_type_option.rs | 25 +- .../field/type_options/date_type_option.rs | 19 +- .../src/services/field/type_options/mod.rs | 1 + .../field/type_options/number_type_option.rs | 16 +- .../type_options/selection_type_option.rs | 28 +- .../field/type_options/text_type_option.rs | 16 +- .../field/type_options/type_option_data.rs | 9 + .../flowy-grid/src/services/grid_editor.rs | 20 +- .../src/services/row/cell_data_serde.rs | 32 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 2 +- .../src/entities/meta.rs | 57 +++- .../src/protobuf/model/meta.rs | 295 ++++++++++++++---- .../src/protobuf/proto/meta.proto | 5 +- .../src/client_grid/grid_meta_pad.rs | 4 +- 19 files changed, 524 insertions(+), 235 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index bc29686021..c391040543 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -215,7 +215,7 @@ class FieldMeta extends $pb.GeneratedMessage { ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionJson') + ..aOM(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionByFieldTypeId', subBuilder: TypeOptionDataByFieldTypeId.create) ..hasRequiredFields = false ; @@ -228,7 +228,7 @@ class FieldMeta extends $pb.GeneratedMessage { $core.bool? frozen, $core.bool? visibility, $core.int? width, - $core.String? typeOptionJson, + TypeOptionDataByFieldTypeId? typeOptionByFieldTypeId, }) { final _result = create(); if (id != null) { @@ -252,8 +252,8 @@ class FieldMeta extends $pb.GeneratedMessage { if (width != null) { _result.width = width; } - if (typeOptionJson != null) { - _result.typeOptionJson = typeOptionJson; + if (typeOptionByFieldTypeId != null) { + _result.typeOptionByFieldTypeId = typeOptionByFieldTypeId; } return _result; } @@ -342,13 +342,56 @@ class FieldMeta extends $pb.GeneratedMessage { void clearWidth() => clearField(7); @$pb.TagNumber(8) - $core.String get typeOptionJson => $_getSZ(7); + TypeOptionDataByFieldTypeId get typeOptionByFieldTypeId => $_getN(7); @$pb.TagNumber(8) - set typeOptionJson($core.String v) { $_setString(7, v); } + set typeOptionByFieldTypeId(TypeOptionDataByFieldTypeId v) { setField(8, v); } @$pb.TagNumber(8) - $core.bool hasTypeOptionJson() => $_has(7); + $core.bool hasTypeOptionByFieldTypeId() => $_has(7); @$pb.TagNumber(8) - void clearTypeOptionJson() => clearField(8); + void clearTypeOptionByFieldTypeId() => clearField(8); + @$pb.TagNumber(8) + TypeOptionDataByFieldTypeId ensureTypeOptionByFieldTypeId() => $_ensure(7); +} + +class TypeOptionDataByFieldTypeId extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TypeOptionDataByFieldTypeId', createEmptyInstance: create) + ..m<$core.String, $core.String>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'map', entryClassName: 'TypeOptionDataByFieldTypeId.MapEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OS) + ..hasRequiredFields = false + ; + + TypeOptionDataByFieldTypeId._() : super(); + factory TypeOptionDataByFieldTypeId({ + $core.Map<$core.String, $core.String>? map, + }) { + final _result = create(); + if (map != null) { + _result.map.addAll(map); + } + return _result; + } + factory TypeOptionDataByFieldTypeId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TypeOptionDataByFieldTypeId.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') + TypeOptionDataByFieldTypeId clone() => TypeOptionDataByFieldTypeId()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TypeOptionDataByFieldTypeId copyWith(void Function(TypeOptionDataByFieldTypeId) updates) => super.copyWith((message) => updates(message as TypeOptionDataByFieldTypeId)) as TypeOptionDataByFieldTypeId; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static TypeOptionDataByFieldTypeId create() => TypeOptionDataByFieldTypeId._(); + TypeOptionDataByFieldTypeId createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TypeOptionDataByFieldTypeId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TypeOptionDataByFieldTypeId? _defaultInstance; + + @$pb.TagNumber(1) + $core.Map<$core.String, $core.String> get map => $_getMap(0); } enum FieldChangesetPayload_OneOfName { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 7c690f7b1e..74a4ffe802 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -69,12 +69,33 @@ const FieldMeta$json = const { const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'}, const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'}, const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'}, - const {'1': 'type_option_json', '3': 8, '4': 1, '5': 9, '10': 'typeOptionJson'}, + const {'1': 'type_option_by_field_type_id', '3': 8, '4': 1, '5': 11, '6': '.TypeOptionDataByFieldTypeId', '10': 'typeOptionByFieldTypeId'}, ], }; /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSKAoQdHlwZV9vcHRpb25fanNvbhgIIAEoCVIOdHlwZU9wdGlvbkpzb24='); +final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSWwocdHlwZV9vcHRpb25fYnlfZmllbGRfdHlwZV9pZBgIIAEoCzIcLlR5cGVPcHRpb25EYXRhQnlGaWVsZFR5cGVJZFIXdHlwZU9wdGlvbkJ5RmllbGRUeXBlSWQ='); +@$core.Deprecated('Use typeOptionDataByFieldTypeIdDescriptor instead') +const TypeOptionDataByFieldTypeId$json = const { + '1': 'TypeOptionDataByFieldTypeId', + '2': const [ + const {'1': 'map', '3': 1, '4': 3, '5': 11, '6': '.TypeOptionDataByFieldTypeId.MapEntry', '10': 'map'}, + ], + '3': const [TypeOptionDataByFieldTypeId_MapEntry$json], +}; + +@$core.Deprecated('Use typeOptionDataByFieldTypeIdDescriptor instead') +const TypeOptionDataByFieldTypeId_MapEntry$json = const { + '1': 'MapEntry', + '2': const [ + const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, + const {'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'}, + ], + '7': const {'7': true}, +}; + +/// Descriptor for `TypeOptionDataByFieldTypeId`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List typeOptionDataByFieldTypeIdDescriptor = $convert.base64Decode('ChtUeXBlT3B0aW9uRGF0YUJ5RmllbGRUeXBlSWQSNwoDbWFwGAEgAygLMiUuVHlwZU9wdGlvbkRhdGFCeUZpZWxkVHlwZUlkLk1hcEVudHJ5UgNtYXAaNgoITWFwRW50cnkSEAoDa2V5GAEgASgJUgNrZXkSFAoFdmFsdWUYAiABKAlSBXZhbHVlOgI4AQ=='); @$core.Deprecated('Use fieldChangesetPayloadDescriptor instead') const FieldChangesetPayload$json = const { '1': 'FieldChangesetPayload', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 25f11c3010..53660bdea2 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,5 @@ use crate::manager::GridManager; -use crate::services::field::{type_option_data_from_str, SelectOption}; +use crate::services::field::{type_option_builder_from_json_str, SelectOption}; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; @@ -115,9 +115,11 @@ pub(crate) async fn get_field_context_handler( ) -> DataResult { let params = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; - let type_option_data = type_option_data_from_str(&field_meta.type_option_json, &field_meta.field_type); + let s = field_meta.get_type_option_str().unwrap(); + let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); + let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let field: Field = field_meta.into(); let edit_context = EditFieldContext { grid_id: params.grid_id, diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index 932d93c6ed..2afa9eeda2 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -9,15 +9,16 @@ macro_rules! impl_into_box_type_option_builder { }; } -macro_rules! impl_from_json_str_and_from_bytes { +macro_rules! impl_builder_from_json_str_and_from_bytes { ($target: ident,$type_option: ident) => { impl $target { - pub fn from_json_str(s: &str) -> $target { - $target($type_option::from(s)) + pub fn from_protobuf_bytes(bytes: Bytes) -> $target { + let type_option = $type_option::from_protobuf_bytes(bytes); + $target(type_option) } - pub fn from_bytes(bytes: Bytes) -> $target { - let type_option = $type_option::try_from(bytes).unwrap_or($type_option::default()); + pub fn from_json_str(s: &str) -> $target { + let type_option = $type_option::from_json_str(s); $target(type_option) } } @@ -25,48 +26,33 @@ macro_rules! impl_from_json_str_and_from_bytes { } #[macro_export] -macro_rules! impl_from_and_to_type_option { +macro_rules! impl_type_option { ($target: ident, $field_type:expr) => { - impl_from_field_type_option!($target); - impl_to_field_type_option!($target, $field_type); - }; -} - -#[macro_export] -macro_rules! impl_from_field_type_option { - ($target: ident) => { impl std::convert::From<&FieldMeta> for $target { fn from(field_meta: &FieldMeta) -> $target { - $target::from(field_meta.type_option_json.as_str()) - } - } - - impl std::convert::From<&str> for $target { - fn from(type_option_str: &str) -> $target { - match serde_json::from_str(type_option_str) { - Ok(obj) => obj, - Err(err) => { - tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); - $target::default() - } + match field_meta + .type_option_by_field_type_id + .get_entry::<$target>(&$field_type) + { + None => $target::default(), + Some(target) => target, } } } - }; -} - -#[macro_export] -macro_rules! impl_to_field_type_option { - ($target: ident, $field_type:expr) => { - impl $target { - pub fn field_type(&self) -> FieldType { - $field_type - } - } impl std::convert::From<$target> for String { - fn from(field_description: $target) -> Self { - match serde_json::to_string(&field_description) { + fn from(type_option: $target) -> String { + type_option.json_str() + } + } + + impl TypeOptionDataEntry for $target { + fn field_type(&self) -> FieldType { + $field_type + } + + fn json_str(&self) -> String { + match serde_json::to_string(&self) { Ok(s) => s, Err(e) => { tracing::error!("Field type data convert to AnyData fail, error: {:?}", e); @@ -74,6 +60,26 @@ macro_rules! impl_to_field_type_option { } } } + + fn protobuf_bytes(&self) -> Bytes { + self.clone().try_into().unwrap() + } + } + + impl TypeOptionDataFrom for $target { + fn from_json_str(s: &str) -> $target { + match serde_json::from_str(s) { + Ok(obj) => obj, + Err(err) => { + tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); + $target::default() + } + } + } + + fn from_protobuf_bytes(bytes: Bytes) -> $target { + $target::try_from(bytes).unwrap_or($target::default()) + } } }; } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 474a97e885..d978951425 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,6 +1,8 @@ use crate::services::field::type_options::*; use bytes::Bytes; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{ + Field, FieldMeta, FieldType, TypeOptionDataByFieldTypeId, TypeOptionDataEntry, TypeOptionDataFrom, +}; pub struct FieldBuilder { field_meta: FieldMeta, @@ -24,6 +26,23 @@ impl FieldBuilder { Self::new(type_option_builder) } + pub fn from_field(field: Field, type_option_builder: Box) -> Self { + let field_meta = FieldMeta { + id: field.id, + name: field.name, + desc: field.desc, + field_type: field.field_type, + frozen: field.frozen, + visibility: field.visibility, + width: field.width, + type_option_by_field_type_id: TypeOptionDataByFieldTypeId::default(), + }; + Self { + field_meta, + type_option_builder, + } + } + pub fn name(mut self, name: &str) -> Self { self.field_meta.name = name.to_owned(); self @@ -52,16 +71,16 @@ impl FieldBuilder { pub fn build(self) -> FieldMeta { debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); let mut field_meta = self.field_meta; - let type_option_json = self.type_option_builder.build_type_option_str(); - field_meta.type_option_json = type_option_json; + field_meta + .type_option_by_field_type_id + .insert_entry(self.type_option_builder.entry()); field_meta } } pub trait TypeOptionBuilder { fn field_type(&self) -> FieldType; - fn build_type_option_str(&self) -> String; - fn build_type_option_data(&self) -> Bytes; + fn entry(&self) -> &dyn TypeOptionDataEntry; } pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box { @@ -88,23 +107,14 @@ pub fn type_option_builder_from_json_str(s: &str, field_type: &FieldType) -> Box } } -pub fn type_option_builder_from_bytes(bytes: Bytes, field_type: &FieldType) -> Box { +pub fn type_option_builder_from_bytes>(bytes: T, field_type: &FieldType) -> Box { + let bytes = bytes.into(); match field_type { - FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_bytes(bytes)), - FieldType::Number => Box::new(NumberTypeOptionBuilder::from_bytes(bytes)), - FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_bytes(bytes)), - FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_bytes(bytes)), - FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_bytes(bytes)), - FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_bytes(bytes)), + FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::Number => Box::new(NumberTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_protobuf_bytes(bytes)), } } - -pub fn type_option_data_from_str(s: &str, field_type: &FieldType) -> Vec { - let builder = type_option_builder_from_json_str(s, field_type); - builder.build_type_option_data().to_vec() -} - -pub fn type_option_json_str_from_bytes(bytes: Vec, field_type: &FieldType) -> String { - let builder = type_option_builder_from_bytes(Bytes::from(bytes), field_type); - builder.build_type_option_str() -} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index f6e07c831a..99fd2290db 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,16 +1,19 @@ -use crate::impl_from_and_to_type_option; -use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use crate::impl_type_option; +use crate::services::field::{ + BoxTypeOptionBuilder, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption, + SingleSelectTypeOption, TypeOptionBuilder, +}; use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); impl_into_box_type_option_builder!(CheckboxTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(CheckboxTypeOptionBuilder, CheckboxTypeOption); +impl_builder_from_json_str_and_from_bytes!(CheckboxTypeOptionBuilder, CheckboxTypeOption); impl CheckboxTypeOptionBuilder { pub fn set_selected(mut self, is_selected: bool) -> Self { @@ -24,12 +27,8 @@ impl TypeOptionBuilder for CheckboxTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -38,7 +37,7 @@ pub struct CheckboxTypeOption { #[pb(index = 1)] pub is_selected: bool, } -impl_from_and_to_type_option!(CheckboxTypeOption, FieldType::Checkbox); +impl_type_option!(CheckboxTypeOption, FieldType::Checkbox); impl CellDataSerde for CheckboxTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -47,8 +46,8 @@ impl CellDataSerde for CheckboxTypeOption { fn serialize_cell_data(&self, data: &str) -> Result { let s = match string_to_bool(data) { - true => "1", - false => "0", + true => "No", + false => "Yes", }; Ok(s.to_owned()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index dca1654b3e..92d01cf90b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,15 +1,14 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::row::CellDataSerde; use bytes::Bytes; - use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; -use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use crate::services::field::{BoxTypeOptionBuilder, RichTextTypeOption, TypeOptionBuilder}; use strum_macros::EnumIter; // Date @@ -21,7 +20,7 @@ pub struct DateTypeOption { #[pb(index = 2)] pub time_format: TimeFormat, } -impl_from_and_to_type_option!(DateTypeOption, FieldType::DateTime); +impl_type_option!(DateTypeOption, FieldType::DateTime); impl DateTypeOption { #[allow(dead_code)] @@ -66,7 +65,7 @@ impl CellDataSerde for DateTypeOption { #[derive(Default)] pub struct DateTypeOptionBuilder(DateTypeOption); impl_into_box_type_option_builder!(DateTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); +impl_builder_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); impl DateTypeOptionBuilder { pub fn date_format(mut self, date_format: DateFormat) -> Self { @@ -84,12 +83,8 @@ impl TypeOptionBuilder for DateTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs index 958edf2664..b5cab79b97 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs @@ -3,6 +3,7 @@ mod date_type_option; mod number_type_option; mod selection_type_option; mod text_type_option; +mod type_option_data; pub use checkbox_type_option::*; pub use date_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 67de271309..fc052df8e7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -1,8 +1,8 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::row::CellDataSerde; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use lazy_static::lazy_static; use rust_decimal::prelude::Zero; use rust_decimal::Decimal; @@ -22,7 +22,7 @@ lazy_static! { #[derive(Default)] pub struct NumberTypeOptionBuilder(NumberTypeOption); impl_into_box_type_option_builder!(NumberTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); +impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); impl NumberTypeOptionBuilder { pub fn name(mut self, name: &str) -> Self { @@ -51,12 +51,8 @@ impl TypeOptionBuilder for NumberTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -78,7 +74,7 @@ pub struct NumberTypeOption { #[pb(index = 5)] pub name: String, } -impl_from_and_to_type_option!(NumberTypeOption, FieldType::Number); +impl_type_option!(NumberTypeOption, FieldType::Number); impl std::default::Default for NumberTypeOption { fn default() -> Self { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 015bf2257b..c712c747ec 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,11 +1,11 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -21,7 +21,7 @@ pub struct SingleSelectTypeOption { #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); +impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl CellDataSerde for SingleSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -36,7 +36,7 @@ impl CellDataSerde for SingleSelectTypeOption { #[derive(Default)] pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption); impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOption); +impl_builder_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOption); impl SingleSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { @@ -50,12 +50,8 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -68,7 +64,7 @@ pub struct MultiSelectTypeOption { #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); impl CellDataSerde for MultiSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -83,7 +79,7 @@ impl CellDataSerde for MultiSelectTypeOption { #[derive(Default)] pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); +impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); impl MultiSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { self.0.options.push(opt); @@ -96,12 +92,8 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 3b2cfa051d..a1441f28c7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,28 +1,24 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct RichTextTypeOptionBuilder(RichTextTypeOption); impl_into_box_type_option_builder!(RichTextTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); +impl_builder_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); impl TypeOptionBuilder for RichTextTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -31,7 +27,7 @@ pub struct RichTextTypeOption { #[pb(index = 1)] pub format: String, } -impl_from_and_to_type_option!(RichTextTypeOption, FieldType::RichText); +impl_type_option!(RichTextTypeOption, FieldType::RichText); impl CellDataSerde for RichTextTypeOption { fn deserialize_cell_data(&self, data: String) -> String { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs new file mode 100644 index 0000000000..330cc4fb10 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs @@ -0,0 +1,9 @@ +use flowy_grid_data_model::entities::FieldType; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +// #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] +// pub struct TypeOptionData { +// #[pb(index = 1)] +// pub map: HashMap, +// } 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 3b48f244d5..226949a5d2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{type_option_json_str_from_bytes, FieldBuilder}; +use crate::services::field::{type_option_builder_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; @@ -74,17 +74,9 @@ impl ClientGridEditor { }; Ok(grid.update_field(changeset, deserializer)?) } else { - let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); - let field_meta = FieldMeta { - id: field.id, - name: field.name, - desc: field.desc, - field_type: field.field_type, - frozen: field.frozen, - visibility: field.visibility, - width: field.width, - type_option_json, - }; + // let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); + let builder = type_option_builder_from_bytes(type_option_data, &field.field_type); + let field_meta = FieldBuilder::from_field(field, builder).build(); Ok(grid.create_field(field_meta, start_field_id)?) } }) @@ -409,7 +401,7 @@ impl TypeOptionDataDeserializer for TypeOptionChangesetDeserializer { // The type_option_data is serialized by protobuf. But the type_option_data should be // serialized by utf-8. So we must transform the data here. - let type_option_json = type_option_json_str_from_bytes(type_option_data, &self.0); - Ok(type_option_json) + let builder = type_option_builder_from_bytes(type_option_data, &self.0); + Ok(builder.entry().json_str()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs index 3d1c1939d7..1e60583df8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs @@ -8,25 +8,25 @@ pub trait CellDataSerde { } #[allow(dead_code)] -pub fn serialize_cell_data(data: &str, field: &FieldMeta) -> Result { - match field.field_type { - FieldType::RichText => RichTextTypeOption::from(field).serialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field).serialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field).serialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field).serialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field).serialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field).serialize_cell_data(data), +pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result { + match field_meta.field_type { + FieldType::RichText => RichTextTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).serialize_cell_data(data), } } -pub fn deserialize_cell_data(data: String, field: &FieldMeta) -> Result { - let s = match field.field_type { - FieldType::RichText => RichTextTypeOption::from(field).deserialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field).deserialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field).deserialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field).deserialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field).deserialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field).deserialize_cell_data(data), +pub fn deserialize_cell_data(data: String, field_meta: &FieldMeta) -> Result { + let s = match field_meta.field_type { + FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data), }; Ok(s) } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 7739356531..49fc16bb5a 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -3,7 +3,7 @@ use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, + BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_grid_data_model::parser::CreateFieldParams; diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 90074cadff..a09ced64b8 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -1,8 +1,11 @@ use crate::parser::NotEmptyUuid; +use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error_code::ErrorCode; use serde::{Deserialize, Serialize}; +use std::any::Any; use std::collections::HashMap; +use std::ops::Deref; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; pub const DEFAULT_ROW_HEIGHT: i32 = 36; @@ -76,7 +79,7 @@ pub struct GridBlockMetaSerde { pub row_metas: Vec, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] pub struct FieldMeta { #[pb(index = 1)] pub id: String, @@ -100,7 +103,7 @@ pub struct FieldMeta { pub width: i32, #[pb(index = 8)] - pub type_option_json: String, + pub type_option_by_field_type_id: TypeOptionDataByFieldTypeId, } impl FieldMeta { @@ -113,7 +116,55 @@ impl FieldMeta { frozen: false, visibility: true, width: DEFAULT_FIELD_WIDTH, - type_option_json: Default::default(), + type_option_by_field_type_id: Default::default(), + } + } + + pub fn get_type_option_str(&self) -> Option { + match self.type_option_by_field_type_id.get(&self.field_type) { + None => None, + Some(s) => Some(s.to_owned()), + } + } +} + +pub trait TypeOptionDataEntry { + fn field_type(&self) -> FieldType; + fn json_str(&self) -> String; + fn protobuf_bytes(&self) -> Bytes; +} + +pub trait TypeOptionDataFrom { + fn from_json_str(s: &str) -> Self; + fn from_protobuf_bytes(bytes: Bytes) -> Self; +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] +pub struct TypeOptionDataByFieldTypeId { + #[pb(index = 1)] + pub map: HashMap, +} + +impl TypeOptionDataByFieldTypeId { + pub fn insert_entry(&mut self, entry: &T) { + self.map.insert(entry.field_type().type_id(), entry.json_str()); + } + + pub fn insert(&mut self, field_type: &FieldType, json_str: String) { + self.map.insert(field_type.type_id(), json_str); + } + + pub fn get_entry(&self, field_type: &FieldType) -> Option { + match self.map.get(&field_type.type_id()) { + None => None, + Some(s) => Some(T::from_json_str(s)), + } + } + + pub fn get(&self, field_type: &FieldType) -> Option { + match self.map.get(&field_type.type_id()) { + None => None, + Some(s) => Some(s.to_owned()), } } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index f22a7c00a2..4b0de2d3fb 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -727,7 +727,7 @@ pub struct FieldMeta { pub frozen: bool, pub visibility: bool, pub width: i32, - pub type_option_json: ::std::string::String, + pub type_option_by_field_type_id: ::protobuf::SingularPtrField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -882,35 +882,47 @@ impl FieldMeta { self.width = v; } - // string type_option_json = 8; + // .TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8; - pub fn get_type_option_json(&self) -> &str { - &self.type_option_json + pub fn get_type_option_by_field_type_id(&self) -> &TypeOptionDataByFieldTypeId { + self.type_option_by_field_type_id.as_ref().unwrap_or_else(|| ::default_instance()) } - pub fn clear_type_option_json(&mut self) { - self.type_option_json.clear(); + pub fn clear_type_option_by_field_type_id(&mut self) { + self.type_option_by_field_type_id.clear(); + } + + pub fn has_type_option_by_field_type_id(&self) -> bool { + self.type_option_by_field_type_id.is_some() } // Param is passed by value, moved - pub fn set_type_option_json(&mut self, v: ::std::string::String) { - self.type_option_json = v; + pub fn set_type_option_by_field_type_id(&mut self, v: TypeOptionDataByFieldTypeId) { + self.type_option_by_field_type_id = ::protobuf::SingularPtrField::some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_type_option_json(&mut self) -> &mut ::std::string::String { - &mut self.type_option_json + pub fn mut_type_option_by_field_type_id(&mut self) -> &mut TypeOptionDataByFieldTypeId { + if self.type_option_by_field_type_id.is_none() { + self.type_option_by_field_type_id.set_default(); + } + self.type_option_by_field_type_id.as_mut().unwrap() } // Take field - pub fn take_type_option_json(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.type_option_json, ::std::string::String::new()) + pub fn take_type_option_by_field_type_id(&mut self) -> TypeOptionDataByFieldTypeId { + self.type_option_by_field_type_id.take().unwrap_or_else(|| TypeOptionDataByFieldTypeId::new()) } } impl ::protobuf::Message for FieldMeta { fn is_initialized(&self) -> bool { + for v in &self.type_option_by_field_type_id { + if !v.is_initialized() { + return false; + } + }; true } @@ -952,7 +964,7 @@ impl ::protobuf::Message for FieldMeta { self.width = tmp; }, 8 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_option_json)?; + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.type_option_by_field_type_id)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -987,8 +999,9 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint); } - if !self.type_option_json.is_empty() { - my_size += ::protobuf::rt::string_size(8, &self.type_option_json); + if let Some(ref v) = self.type_option_by_field_type_id.as_ref() { + let len = v.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); @@ -1017,8 +1030,10 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { os.write_int32(7, self.width)?; } - if !self.type_option_json.is_empty() { - os.write_string(8, &self.type_option_json)?; + if let Some(ref v) = self.type_option_by_field_type_id.as_ref() { + os.write_tag(8, ::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(()) @@ -1093,10 +1108,10 @@ impl ::protobuf::Message for FieldMeta { |m: &FieldMeta| { &m.width }, |m: &mut FieldMeta| { &mut m.width }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "type_option_json", - |m: &FieldMeta| { &m.type_option_json }, - |m: &mut FieldMeta| { &mut m.type_option_json }, + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "type_option_by_field_type_id", + |m: &FieldMeta| { &m.type_option_by_field_type_id }, + |m: &mut FieldMeta| { &mut m.type_option_by_field_type_id }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "FieldMeta", @@ -1121,7 +1136,7 @@ impl ::protobuf::Clear for FieldMeta { self.frozen = false; self.visibility = false; self.width = 0; - self.type_option_json.clear(); + self.type_option_by_field_type_id.clear(); self.unknown_fields.clear(); } } @@ -1138,6 +1153,160 @@ impl ::protobuf::reflect::ProtobufValue for FieldMeta { } } +#[derive(PartialEq,Clone,Default)] +pub struct TypeOptionDataByFieldTypeId { + // message fields + pub map: ::std::collections::HashMap<::std::string::String, ::std::string::String>, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a TypeOptionDataByFieldTypeId { + fn default() -> &'a TypeOptionDataByFieldTypeId { + ::default_instance() + } +} + +impl TypeOptionDataByFieldTypeId { + pub fn new() -> TypeOptionDataByFieldTypeId { + ::std::default::Default::default() + } + + // repeated .TypeOptionDataByFieldTypeId.MapEntry map = 1; + + + pub fn get_map(&self) -> &::std::collections::HashMap<::std::string::String, ::std::string::String> { + &self.map + } + pub fn clear_map(&mut self) { + self.map.clear(); + } + + // Param is passed by value, moved + pub fn set_map(&mut self, v: ::std::collections::HashMap<::std::string::String, ::std::string::String>) { + self.map = v; + } + + // Mutable pointer to the field. + pub fn mut_map(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, ::std::string::String> { + &mut self.map + } + + // Take field + pub fn take_map(&mut self) -> ::std::collections::HashMap<::std::string::String, ::std::string::String> { + ::std::mem::replace(&mut self.map, ::std::collections::HashMap::new()) + } +} + +impl ::protobuf::Message for TypeOptionDataByFieldTypeId { + 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_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(wire_type, is, &mut self.map)?; + }, + _ => { + ::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; + my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(1, &self.map); + 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<()> { + ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(1, &self.map, 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() -> TypeOptionDataByFieldTypeId { + TypeOptionDataByFieldTypeId::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_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>( + "map", + |m: &TypeOptionDataByFieldTypeId| { &m.map }, + |m: &mut TypeOptionDataByFieldTypeId| { &mut m.map }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "TypeOptionDataByFieldTypeId", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static TypeOptionDataByFieldTypeId { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(TypeOptionDataByFieldTypeId::new) + } +} + +impl ::protobuf::Clear for TypeOptionDataByFieldTypeId { + fn clear(&mut self) { + self.map.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for TypeOptionDataByFieldTypeId { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for TypeOptionDataByFieldTypeId { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct FieldChangesetPayload { // message fields @@ -3507,51 +3676,55 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"V\n\x12GridBlockMet\ aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\ - metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xe6\x01\n\tFieldM\ + metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\x99\x02\n\tFieldM\ eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12(\n\x10type_option_json\x18\x08\x20\x01(\tR\x0etypeOptionJson\"\ - \xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\ - \x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\ - \x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\ - \x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n\ - .FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\ - \x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibi\ - lity\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\x10ty\ - pe_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\r\n\x0bone_of\ - _nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_fro\ - zenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x19\n\x17one_of_\ - type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\t\ - R\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\ - \n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08blo\ - ck_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\ - \x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\ - \x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\ - \x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ - \x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.C\ - ellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\ - \x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\ - \x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\ - \nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaCh\ - angeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\ + idth\x12[\n\x1ctype_option_by_field_type_id\x18\x08\x20\x01(\x0b2\x1c.Ty\ + peOptionDataByFieldTypeIdR\x17typeOptionByFieldTypeId\"\x8e\x01\n\x1bTyp\ + eOptionDataByFieldTypeId\x127\n\x03map\x18\x01\x20\x03(\x0b2%.TypeOption\ + DataByFieldTypeId.MapEntryR\x03map\x1a6\n\x08MapEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05va\ + lue:\x028\x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\ + \x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\ + \x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\ + \x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\ + \x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\ + \x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\ + \x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\ + \r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\ + \n\rone_of_frozenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\ + \x19\n\x17one_of_type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\ + \x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\ + \x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02\ + id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_b\ + y_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellBy\ + FieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nv\ + isibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\ \x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\ - \x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\ - \n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\ - \x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\ - \x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ - \x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\ - \x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\ - \x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridCont\ - ext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\ - \x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMe\ - tas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSer\ - deR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\ - \x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSele\ - ct\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\ - \x05b\x06proto3\ + \x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChan\ + geset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06heig\ + ht\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\ + \x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\ + \x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12Cel\ + lByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\ + \x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\ro\ + ne_of_heightB\x13\n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08f\ + ield_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01\ + (\tR\x04data\"\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05ro\ + wId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04da\ + ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10Bui\ + ldGridContext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\n\ + fieldMetas\x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMeta\ + R\nblockMetas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBl\ + ockMetaSerdeR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\ + \x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSi\ + ngleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbo\ + x\x10\x05b\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/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 2c5bd41f86..897143247b 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -22,7 +22,10 @@ message FieldMeta { bool frozen = 5; bool visibility = 6; int32 width = 7; - string type_option_json = 8; + TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8; +} +message TypeOptionDataByFieldTypeId { + map map = 1; } message FieldChangesetPayload { string field_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 362fe924b0..5d7085e92c 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -129,8 +129,8 @@ impl GridMetaPad { if let Some(type_option_data) = changeset.type_option_data { match deserializer.deserialize(type_option_data) { - Ok(type_option_json) => { - field.type_option_json = type_option_json; + Ok(json_str) => { + field.type_option_by_field_type_id.insert(&field.field_type, json_str); is_changed = Some(()) } Err(err) => { From 915d71991a75ffb3a33ea7fb530052c89d124090 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 1 Apr 2022 22:46:01 +0800 Subject: [PATCH 25/47] chore: save multi type option data --- .../rust-lib/flowy-grid/src/event_handler.rs | 59 ++++++++++++++----- .../flowy-grid/src/services/grid_editor.rs | 20 +++++-- .../src/client_grid/grid_meta_pad.rs | 34 ++++++++++- 3 files changed, 90 insertions(+), 23 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 53660bdea2..e15c113484 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,5 @@ use crate::manager::GridManager; -use crate::services::field::{type_option_builder_from_json_str, SelectOption}; +use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str, SelectOption}; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; @@ -85,7 +85,19 @@ pub(crate) async fn switch_to_field_handler( ) -> DataResult { let params: EditFieldParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let edit_context = editor.switch_to_field_type(¶ms.field_id, params.field_type).await?; + editor + .switch_to_field_type(¶ms.field_id, ¶ms.field_type) + .await?; + + let field_meta = editor.get_field(¶ms.field_id).await?; + let edit_context = make_field_edit_context( + ¶ms.grid_id, + Some(params.field_id), + params.field_type, + editor, + field_meta, + ) + .await?; data_result(edit_context) } @@ -115,31 +127,46 @@ pub(crate) async fn get_field_context_handler( ) -> DataResult { let params = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; - let s = field_meta.get_type_option_str().unwrap(); - let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); - let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let edit_context = + make_field_edit_context(¶ms.grid_id, params.field_id, params.field_type, editor, None).await?; - let field: Field = field_meta.into(); - let edit_context = EditFieldContext { - grid_id: params.grid_id, - grid_field: field, - type_option_data, - }; data_result(edit_context) } +async fn make_field_edit_context( + grid_id: &str, + field_id: Option, + field_type: FieldType, + editor: Arc, + field_meta: Option, +) -> FlowyResult { + let field_meta = field_meta.unwrap_or(get_or_create_field_meta(field_id, &field_type, editor).await?); + let s = field_meta + .get_type_option_str() + .unwrap_or_else(|| default_type_option_builder_from_type(&field_type).entry().json_str()); + + let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); + let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let field: Field = field_meta.into(); + Ok(EditFieldContext { + grid_id: grid_id.to_string(), + grid_field: field, + type_option_data, + }) +} + async fn get_or_create_field_meta( - params: &GetEditFieldContextPayload, + field_id: Option, + field_type: &FieldType, editor: Arc, ) -> FlowyResult { - if params.field_id.is_some() { - if let Some(field_meta) = editor.get_field(params.field_id.as_ref().unwrap()).await? { + if field_id.is_some() { + if let Some(field_meta) = editor.get_field(field_id.as_ref().unwrap()).await? { return Ok(field_meta); } } - editor.default_field_meta(¶ms.field_type).await + editor.create_next_field_meta(field_type).await } #[tracing::instrument(level = "debug", skip(data, manager), err)] 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 226949a5d2..3ca651f5dc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,10 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{type_option_builder_from_bytes, FieldBuilder}; +use crate::services::field::{ + default_type_option_builder_from_type, type_option_builder_from_bytes, type_option_builder_from_json_str, + FieldBuilder, +}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; @@ -85,7 +88,7 @@ impl ClientGridEditor { Ok(()) } - pub async fn default_field_meta(&self, field_type: &FieldType) -> FlowyResult { + pub async fn create_next_field_meta(&self, field_type: &FieldType) -> FlowyResult { let name = format!("Property {}", self.pad.read().await.fields().len() + 1); let field_meta = FieldBuilder::from_field_type(field_type).name(&name).build(); Ok(field_meta) @@ -95,7 +98,7 @@ impl ClientGridEditor { self.pad.read().await.contain_field(field_id) } - pub async fn update_field(&self, mut params: FieldChangesetParams) -> FlowyResult<()> { + pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { None => return Err(ErrorCode::FieldDoesNotExist.into()), Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), @@ -112,10 +115,15 @@ impl ClientGridEditor { Ok(()) } - pub async fn switch_to_field_type(&self, field_id: &str, field_type: FieldType) -> FlowyResult { - let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?; + pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> { + let type_option_json_builder = + |field_type: &FieldType| -> String { default_type_option_builder_from_type(field_type).entry().json_str() }; + + let _ = self + .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) + .await?; let _ = self.notify_did_update_fields().await?; - todo!() + Ok(()) } pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 5d7085e92c..eac4b97be9 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -3,7 +3,8 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; use flowy_grid_data_model::entities::{ - FieldChangesetParams, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder, + FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta, GridBlockMetaChangeset, GridMeta, + RepeatedFieldOrder, TypeOptionDataEntry, }; use lib_infra::uuid; @@ -89,6 +90,37 @@ impl GridMetaPad { }) } + pub fn switch_to_field( + &mut self, + field_id: &str, + field_type: FieldType, + type_option_json_builder: B, + ) -> CollaborateResult> + where + B: FnOnce(&FieldType) -> String, + { + self.modify_grid(|grid| { + // + match grid.fields.iter_mut().find(|field_meta| field_meta.id == field_id) { + None => { + tracing::warn!("Can not find the field with id: {}", field_id); + Ok(None) + } + Some(field_meta) => { + if field_meta.get_type_option_str().is_none() { + let type_option_json = type_option_json_builder(&field_type); + field_meta + .type_option_by_field_type_id + .insert(&field_type, type_option_json); + } + + field_meta.field_type = field_type; + Ok(Some(())) + } + } + }) + } + pub fn update_field( &mut self, changeset: FieldChangesetParams, From 82eed0506b1809ae2b9d1063c698537608942e3f Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 1 Apr 2022 22:49:26 +0800 Subject: [PATCH 26/47] chore: fix warnings --- .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- frontend/rust-lib/flowy-grid/src/macros.rs | 7 +-- .../src/services/field/field_builder.rs | 8 +-- .../type_options/checkbox_type_option.rs | 7 +-- .../field/type_options/date_type_option.rs | 4 +- .../field/type_options/number_type_option.rs | 2 +- .../type_options/selection_type_option.rs | 2 +- .../field/type_options/text_type_option.rs | 2 +- .../field/type_options/type_option_data.rs | 4 -- .../flowy-grid/src/services/grid_editor.rs | 5 +- .../flowy-grid/tests/grid/grid_test.rs | 15 ++--- .../rust-lib/flowy-grid/tests/grid/script.rs | 22 +++++-- .../src/entities/meta.rs | 60 ++++++++++--------- .../src/client_grid/grid_meta_pad.rs | 13 ++-- 14 files changed, 75 insertions(+), 78 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index e15c113484..e90998b986 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -142,7 +142,7 @@ async fn make_field_edit_context( ) -> FlowyResult { let field_meta = field_meta.unwrap_or(get_or_create_field_meta(field_id, &field_type, editor).await?); let s = field_meta - .get_type_option_str() + .get_type_option_str(None) .unwrap_or_else(|| default_type_option_builder_from_type(&field_type).entry().json_str()); let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index 2afa9eeda2..4a4994729c 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -30,10 +30,7 @@ macro_rules! impl_type_option { ($target: ident, $field_type:expr) => { impl std::convert::From<&FieldMeta> for $target { fn from(field_meta: &FieldMeta) -> $target { - match field_meta - .type_option_by_field_type_id - .get_entry::<$target>(&$field_type) - { + match field_meta.get_type_option_entry::<$target>(Some($field_type)) { None => $target::default(), Some(target) => target, } @@ -66,7 +63,7 @@ macro_rules! impl_type_option { } } - impl TypeOptionDataFrom for $target { + impl TypeOptionDataEntity for $target { fn from_json_str(s: &str) -> $target { match serde_json::from_str(s) { Ok(obj) => obj, diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index d978951425..9a654d4c43 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,8 +1,6 @@ use crate::services::field::type_options::*; use bytes::Bytes; -use flowy_grid_data_model::entities::{ - Field, FieldMeta, FieldType, TypeOptionDataByFieldTypeId, TypeOptionDataEntry, TypeOptionDataFrom, -}; +use flowy_grid_data_model::entities::{Field, FieldMeta, FieldType, TypeOptionDataByFieldTypeId, TypeOptionDataEntry}; pub struct FieldBuilder { field_meta: FieldMeta, @@ -71,9 +69,7 @@ impl FieldBuilder { pub fn build(self) -> FieldMeta { debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); let mut field_meta = self.field_meta; - field_meta - .type_option_by_field_type_id - .insert_entry(self.type_option_builder.entry()); + field_meta.insert_type_option_entry(self.type_option_builder.entry()); field_meta } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 99fd2290db..3611f5a0db 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,13 +1,10 @@ use crate::impl_type_option; -use crate::services::field::{ - BoxTypeOptionBuilder, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption, - SingleSelectTypeOption, TypeOptionBuilder, -}; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; #[derive(Default)] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 92d01cf90b..86c15e13c5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -5,10 +5,10 @@ use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; -use crate::services::field::{BoxTypeOptionBuilder, RichTextTypeOption, TypeOptionBuilder}; +use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use strum_macros::EnumIter; // Date diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index fc052df8e7..7e557955df 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -2,7 +2,7 @@ use crate::impl_type_option; use crate::services::row::CellDataSerde; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use lazy_static::lazy_static; use rust_decimal::prelude::Zero; use rust_decimal::Decimal; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index c712c747ec..abc9c81288 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -5,7 +5,7 @@ use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use uuid::Uuid; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index a1441f28c7..6bffc8606f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -4,7 +4,7 @@ use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; #[derive(Default)] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs index 330cc4fb10..fbba14feab 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs @@ -1,7 +1,3 @@ -use flowy_grid_data_model::entities::FieldType; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - // #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] // pub struct TypeOptionData { // #[pb(index = 1)] 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 3ca651f5dc..edfce7a736 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,10 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{ - default_type_option_builder_from_type, type_option_builder_from_bytes, type_option_builder_from_json_str, - FieldBuilder, -}; +use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 31ee76712e..138ccf4bba 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -6,7 +6,8 @@ use flowy_grid::services::field::{ }; use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataSerde, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ - CellMetaChangeset, FieldChangeset, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, + CellMetaChangeset, FieldChangesetParams, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, + TypeOptionDataEntry, }; #[tokio::test] @@ -55,7 +56,7 @@ async fn grid_create_duplicate_field() { async fn grid_update_field_with_empty_change() { let mut test = GridEditorTest::new().await; let (params, field_meta) = create_single_select_field(&test.grid_id); - let changeset = FieldChangeset { + let changeset = FieldChangesetParams { field_id: field_meta.id.clone(), grid_id: test.grid_id.clone(), name: None, @@ -84,9 +85,9 @@ async fn grid_update_field() { let (single_select_params, single_select_field) = create_single_select_field(&test.grid_id); let mut cloned_field = single_select_field.clone(); - let mut single_select_type_options = SingleSelectTypeOption::from(&single_select_field); - single_select_type_options.options.push(SelectOption::new("Unknown")); - let changeset = FieldChangeset { + let mut single_select_type_option = SingleSelectTypeOption::from(&single_select_field); + single_select_type_option.options.push(SelectOption::new("Unknown")); + let changeset = FieldChangesetParams { field_id: single_select_field.id.clone(), grid_id: test.grid_id.clone(), name: None, @@ -95,12 +96,12 @@ async fn grid_update_field() { frozen: Some(true), visibility: None, width: Some(1000), - type_option_data: Some(single_select_type_options.clone().into()), + type_option_data: Some(single_select_type_option.protobuf_bytes().to_vec()), }; cloned_field.frozen = true; cloned_field.width = 1000; - cloned_field.type_option_json = single_select_type_options.into(); + cloned_field.insert_type_option_entry(&single_select_type_option); let scripts = vec![ CreateField { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 49fc16bb5a..4dbb5c7a0c 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -3,10 +3,9 @@ use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, - GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, + BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangesetParams, FieldMeta, FieldType, + GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, TypeOptionDataEntry, }; -use flowy_grid_data_model::parser::CreateFieldParams; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; use flowy_test::helper::ViewTest; @@ -22,7 +21,7 @@ pub enum EditorScript { params: CreateFieldParams, }, UpdateField { - changeset: FieldChangeset, + changeset: FieldChangesetParams, }, DeleteField { field_meta: FieldMeta, @@ -255,6 +254,12 @@ pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { let cloned_field_meta = field_meta.clone(); + let type_option_data = field_meta + .get_type_option_entry::(None) + .unwrap() + .protobuf_bytes() + .to_vec(); + let field = Field { id: field_meta.id, name: field_meta.name, @@ -268,7 +273,7 @@ pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, FieldMeta) { let params = CreateFieldParams { grid_id: grid_id.to_owned(), field, - type_option_data: field_meta.type_option_json.as_bytes().to_vec(), + type_option_data, start_field_id: None, }; (params, cloned_field_meta) @@ -281,6 +286,11 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMet let field_meta = FieldBuilder::new(single_select).name("Name").visibility(true).build(); let cloned_field_meta = field_meta.clone(); + let type_option_data = field_meta + .get_type_option_entry::(None) + .unwrap() + .protobuf_bytes() + .to_vec(); let field = Field { id: field_meta.id, @@ -295,7 +305,7 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, FieldMet let params = CreateFieldParams { grid_id: grid_id.to_owned(), field, - type_option_data: field_meta.type_option_json.as_bytes().to_vec(), + type_option_data, start_field_id: None, }; (params, cloned_field_meta) diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index a09ced64b8..ad81fc532a 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -3,9 +3,7 @@ use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error_code::ErrorCode; use serde::{Deserialize, Serialize}; -use std::any::Any; use std::collections::HashMap; -use std::ops::Deref; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; pub const DEFAULT_ROW_HEIGHT: i32 = 36; @@ -79,7 +77,7 @@ pub struct GridBlockMetaSerde { pub row_metas: Vec, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, Eq, PartialEq)] pub struct FieldMeta { #[pb(index = 1)] pub id: String, @@ -120,11 +118,27 @@ impl FieldMeta { } } - pub fn get_type_option_str(&self) -> Option { - match self.type_option_by_field_type_id.get(&self.field_type) { - None => None, - Some(s) => Some(s.to_owned()), - } + pub fn insert_type_option_entry(&mut self, entry: &T) { + self.type_option_by_field_type_id + .insert(entry.field_type().type_id(), entry.json_str()); + } + + pub fn get_type_option_entry(&self, field_type: Option) -> Option { + let field_type = field_type.as_ref().unwrap_or(&self.field_type); + self.type_option_by_field_type_id + .get(&field_type.type_id()) + .map(|s| T::from_json_str(s)) + } + + pub fn insert_type_option_str(&mut self, field_type: &FieldType, json_str: String) { + self.type_option_by_field_type_id.insert(field_type.type_id(), json_str); + } + + pub fn get_type_option_str(&self, field_type: Option) -> Option { + let field_type = field_type.as_ref().unwrap_or(&self.field_type); + self.type_option_by_field_type_id + .get(&field_type.type_id()) + .map(|s| s.to_owned()) } } @@ -134,38 +148,28 @@ pub trait TypeOptionDataEntry { fn protobuf_bytes(&self) -> Bytes; } -pub trait TypeOptionDataFrom { +pub trait TypeOptionDataEntity { fn from_json_str(s: &str) -> Self; fn from_protobuf_bytes(bytes: Bytes) -> Self; } -#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] +#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf, PartialEq, Eq)] pub struct TypeOptionDataByFieldTypeId { #[pb(index = 1)] pub map: HashMap, } -impl TypeOptionDataByFieldTypeId { - pub fn insert_entry(&mut self, entry: &T) { - self.map.insert(entry.field_type().type_id(), entry.json_str()); - } +impl std::ops::Deref for TypeOptionDataByFieldTypeId { + type Target = HashMap; - pub fn insert(&mut self, field_type: &FieldType, json_str: String) { - self.map.insert(field_type.type_id(), json_str); + fn deref(&self) -> &Self::Target { + &self.map } +} - pub fn get_entry(&self, field_type: &FieldType) -> Option { - match self.map.get(&field_type.type_id()) { - None => None, - Some(s) => Some(T::from_json_str(s)), - } - } - - pub fn get(&self, field_type: &FieldType) -> Option { - match self.map.get(&field_type.type_id()) { - None => None, - Some(s) => Some(s.to_owned()), - } +impl std::ops::DerefMut for TypeOptionDataByFieldTypeId { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.map } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index eac4b97be9..2d32fd1d9e 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -4,13 +4,13 @@ use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; use flowy_grid_data_model::entities::{ FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta, GridBlockMetaChangeset, GridMeta, - RepeatedFieldOrder, TypeOptionDataEntry, + RepeatedFieldOrder, }; use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use std::collections::HashMap; -use std::string::FromUtf8Error; + use std::sync::Arc; pub type GridMetaDelta = PlainTextDelta; @@ -107,11 +107,9 @@ impl GridMetaPad { Ok(None) } Some(field_meta) => { - if field_meta.get_type_option_str().is_none() { + if field_meta.get_type_option_str(Some(field_type.clone())).is_none() { let type_option_json = type_option_json_builder(&field_type); - field_meta - .type_option_by_field_type_id - .insert(&field_type, type_option_json); + field_meta.insert_type_option_str(&field_type, type_option_json); } field_meta.field_type = field_type; @@ -162,7 +160,8 @@ impl GridMetaPad { if let Some(type_option_data) = changeset.type_option_data { match deserializer.deserialize(type_option_data) { Ok(json_str) => { - field.type_option_by_field_type_id.insert(&field.field_type, json_str); + let field_type = field.field_type.clone(); + field.insert_type_option_str(&field_type, json_str); is_changed = Some(()) } Err(err) => { From 2262dd0d7b4f95aaef8af34b6974ddeff15e820e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 2 Apr 2022 10:54:01 +0800 Subject: [PATCH 27/47] chore: get cell metas --- .../flowy-grid-data-model/meta.pb.dart | 36 ++++----- .../flowy-grid-data-model/meta.pbjson.dart | 14 ++-- .../src/services/block_meta_editor.rs | 71 +++++++++--------- .../flowy-grid/src/services/grid_editor.rs | 75 +++++++++---------- .../flowy-grid/src/services/row/row_loader.rs | 59 +++++++-------- .../rust-lib/flowy-grid/tests/grid/script.rs | 2 +- .../src/entities/meta.rs | 6 +- .../src/protobuf/model/meta.rs | 74 +++++++++--------- .../src/protobuf/proto/meta.proto | 4 +- .../src/client_grid/grid_block_meta_pad.rs | 29 +++++-- .../src/client_grid/grid_builder.rs | 4 +- .../src/client_grid/grid_meta_pad.rs | 6 +- 12 files changed, 191 insertions(+), 189 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index c391040543..9e730b17d2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -151,15 +151,15 @@ class GridBlockMeta extends $pb.GeneratedMessage { void clearRowCount() => clearField(3); } -class GridBlockMetaSerde extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMetaSerde', createEmptyInstance: create) +class GridBlockMetaData extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMetaData', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowMetas', $pb.PbFieldType.PM, subBuilder: RowMeta.create) ..hasRequiredFields = false ; - GridBlockMetaSerde._() : super(); - factory GridBlockMetaSerde({ + GridBlockMetaData._() : super(); + factory GridBlockMetaData({ $core.String? blockId, $core.Iterable? rowMetas, }) { @@ -172,26 +172,26 @@ class GridBlockMetaSerde extends $pb.GeneratedMessage { } return _result; } - factory GridBlockMetaSerde.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory GridBlockMetaSerde.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory GridBlockMetaData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GridBlockMetaData.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') - GridBlockMetaSerde clone() => GridBlockMetaSerde()..mergeFromMessage(this); + GridBlockMetaData clone() => GridBlockMetaData()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - GridBlockMetaSerde copyWith(void Function(GridBlockMetaSerde) updates) => super.copyWith((message) => updates(message as GridBlockMetaSerde)) as GridBlockMetaSerde; // ignore: deprecated_member_use + GridBlockMetaData copyWith(void Function(GridBlockMetaData) updates) => super.copyWith((message) => updates(message as GridBlockMetaData)) as GridBlockMetaData; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static GridBlockMetaSerde create() => GridBlockMetaSerde._(); - GridBlockMetaSerde createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static GridBlockMetaData create() => GridBlockMetaData._(); + GridBlockMetaData createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static GridBlockMetaSerde getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static GridBlockMetaSerde? _defaultInstance; + static GridBlockMetaData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GridBlockMetaData? _defaultInstance; @$pb.TagNumber(1) $core.String get blockId => $_getSZ(0); @@ -1078,7 +1078,7 @@ class BuildGridContext extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BuildGridContext', createEmptyInstance: create) ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldMetas', $pb.PbFieldType.PM, subBuilder: FieldMeta.create) ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetas', subBuilder: GridBlockMeta.create) - ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetaData', subBuilder: GridBlockMetaSerde.create) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetaData', subBuilder: GridBlockMetaData.create) ..hasRequiredFields = false ; @@ -1086,7 +1086,7 @@ class BuildGridContext extends $pb.GeneratedMessage { factory BuildGridContext({ $core.Iterable? fieldMetas, GridBlockMeta? blockMetas, - GridBlockMetaSerde? blockMetaData, + GridBlockMetaData? blockMetaData, }) { final _result = create(); if (fieldMetas != null) { @@ -1136,14 +1136,14 @@ class BuildGridContext extends $pb.GeneratedMessage { GridBlockMeta ensureBlockMetas() => $_ensure(1); @$pb.TagNumber(3) - GridBlockMetaSerde get blockMetaData => $_getN(2); + GridBlockMetaData get blockMetaData => $_getN(2); @$pb.TagNumber(3) - set blockMetaData(GridBlockMetaSerde v) { setField(3, v); } + set blockMetaData(GridBlockMetaData v) { setField(3, v); } @$pb.TagNumber(3) $core.bool hasBlockMetaData() => $_has(2); @$pb.TagNumber(3) void clearBlockMetaData() => clearField(3); @$pb.TagNumber(3) - GridBlockMetaSerde ensureBlockMetaData() => $_ensure(2); + GridBlockMetaData ensureBlockMetaData() => $_ensure(2); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 74a4ffe802..65e813160f 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -47,17 +47,17 @@ const GridBlockMeta$json = const { /// Descriptor for `GridBlockMeta`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List gridBlockMetaDescriptor = $convert.base64Decode('Cg1HcmlkQmxvY2tNZXRhEhkKCGJsb2NrX2lkGAEgASgJUgdibG9ja0lkEiYKD3N0YXJ0X3Jvd19pbmRleBgCIAEoBVINc3RhcnRSb3dJbmRleBIbCglyb3dfY291bnQYAyABKAVSCHJvd0NvdW50'); -@$core.Deprecated('Use gridBlockMetaSerdeDescriptor instead') -const GridBlockMetaSerde$json = const { - '1': 'GridBlockMetaSerde', +@$core.Deprecated('Use gridBlockMetaDataDescriptor instead') +const GridBlockMetaData$json = const { + '1': 'GridBlockMetaData', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, const {'1': 'row_metas', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rowMetas'}, ], }; -/// Descriptor for `GridBlockMetaSerde`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockMetaSerdeDescriptor = $convert.base64Decode('ChJHcmlkQmxvY2tNZXRhU2VyZGUSGQoIYmxvY2tfaWQYASABKAlSB2Jsb2NrSWQSJQoJcm93X21ldGFzGAIgAygLMgguUm93TWV0YVIIcm93TWV0YXM='); +/// Descriptor for `GridBlockMetaData`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIlCglyb3dfbWV0YXMYAiADKAsyCC5Sb3dNZXRhUghyb3dNZXRhcw=='); @$core.Deprecated('Use fieldMetaDescriptor instead') const FieldMeta$json = const { '1': 'FieldMeta', @@ -220,9 +220,9 @@ const BuildGridContext$json = const { '2': const [ const {'1': 'field_metas', '3': 1, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fieldMetas'}, const {'1': 'block_metas', '3': 2, '4': 1, '5': 11, '6': '.GridBlockMeta', '10': 'blockMetas'}, - const {'1': 'block_meta_data', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMetaSerde', '10': 'blockMetaData'}, + const {'1': 'block_meta_data', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMetaData', '10': 'blockMetaData'}, ], }; /// Descriptor for `BuildGridContext`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi8KC2Jsb2NrX21ldGFzGAIgASgLMg4uR3JpZEJsb2NrTWV0YVIKYmxvY2tNZXRhcxI7Cg9ibG9ja19tZXRhX2RhdGEYAyABKAsyEy5HcmlkQmxvY2tNZXRhU2VyZGVSDWJsb2NrTWV0YURhdGE='); +final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi8KC2Jsb2NrX21ldGFzGAIgASgLMg4uR3JpZEJsb2NrTWV0YVIKYmxvY2tNZXRhcxI6Cg9ibG9ja19tZXRhX2RhdGEYAyABKAsyEi5HcmlkQmxvY2tNZXRhRGF0YVINYmxvY2tNZXRhRGF0YQ=='); 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 65e80136c3..58e8e2ca9e 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,12 +1,12 @@ -use crate::manager::GridUser; -use crate::services::row::{make_cell, make_row_ids_per_block, GridBlockMetaData}; -use bytes::Bytes; - use crate::dart_notification::{send_dart_notification, GridNotification}; +use crate::manager::GridUser; +use crate::services::row::{make_cell, make_row_ids_per_block, GridBlockSnapshot}; +use bytes::Bytes; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, RowMetaChangeset, RowOrder, + CellMeta, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, + RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{ @@ -116,7 +116,8 @@ impl GridBlockMetaEditorManager { pub async fn get_row(&self, block_id: &str, row_id: &str) -> FlowyResult>> { let editor = self.get_editor(block_id).await?; - let mut row_metas = editor.get_row_metas(Some(vec![row_id.to_owned()])).await?; + let row_ids = vec![row_id.to_owned()]; + let mut row_metas = editor.get_row_metas(&Some(row_ids)).await?; if row_metas.is_empty() { Ok(None) } else { @@ -131,42 +132,35 @@ impl GridBlockMetaEditorManager { Ok(()) } - pub(crate) async fn get_block_meta_data_from_blocks( - &self, - grid_blocks: Vec, - ) -> FlowyResult> { + pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { let mut snapshots = vec![]; - for grid_block in grid_blocks { - let editor = self.get_editor(&grid_block.block_id).await?; - let row_metas = editor.get_row_metas(None).await?; + for block_id in block_ids { + let editor = self.get_editor(&block_id).await?; + let row_metas = editor.get_row_metas(&None).await?; row_metas.iter().for_each(|row_meta| { self.block_id_by_row_id .insert(row_meta.id.clone(), row_meta.block_id.clone()); }); - snapshots.push(GridBlockMetaData { - block_id: grid_block.block_id, - row_metas, - }); + snapshots.push(GridBlockSnapshot { block_id, row_metas }); } Ok(snapshots) } - pub(crate) async fn get_block_meta_data(&self, block_ids: &[String]) -> FlowyResult> { - let mut snapshots = vec![]; + // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage. + pub async fn get_cell_metas( + &self, + block_ids: Option, + field_id: &str, + row_ids: Option>, + ) -> FlowyResult> { + let mut block_cell_metas = vec![]; for block_id in block_ids { - let editor = self.get_editor(block_id).await?; - let row_metas = editor.get_row_metas(None).await?; - row_metas.iter().for_each(|row_meta| { - self.block_id_by_row_id - .insert(row_meta.id.clone(), row_meta.block_id.clone()); - }); - snapshots.push(GridBlockMetaData { - block_id: block_id.clone(), - row_metas, - }); + let editor = self.get_editor(&block_id).await?; + let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?; + block_cell_metas.extend(cell_metas); } - Ok(snapshots) + Ok(block_cell_metas) } async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { @@ -178,10 +172,7 @@ impl GridBlockMetaEditorManager { ); Err(FlowyError::internal().context(msg)) } - Some(block_id) => { - let editor = self.get_editor(&block_id).await?; - Ok(editor) - } + Some(block_id) => Ok(self.get_editor(&block_id).await?), } } @@ -301,7 +292,8 @@ impl ClientGridBlockMetaEditor { pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult { let row_id = changeset.row_id.clone(); let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?; - let mut row_metas = self.get_row_metas(Some(vec![row_id.clone()])).await?; + let row_ids = vec![row_id.clone()]; + let mut row_metas = self.get_row_metas(&Some(row_ids)).await?; debug_assert_eq!(row_metas.len(), 1); if row_metas.is_empty() { @@ -312,12 +304,17 @@ impl ClientGridBlockMetaEditor { } } - pub async fn get_row_metas(&self, row_ids: Option>) -> FlowyResult>> { + pub async fn get_row_metas(&self, row_ids: &Option>) -> FlowyResult>> { let row_metas = self.pad.read().await.get_row_metas(row_ids)?; Ok(row_metas) } - pub async fn get_row_orders(&self, row_ids: Option>) -> FlowyResult> { + pub async fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> FlowyResult> { + let cell_metas = self.pad.read().await.get_cell_metas(field_id, row_ids)?; + Ok(cell_metas) + } + + pub async fn get_row_orders(&self, row_ids: &Option>) -> FlowyResult> { let row_orders = self .pad .read() 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 edfce7a736..88738aa082 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -37,8 +37,9 @@ impl ClientGridEditor { let rev_manager = Arc::new(rev_manager); let pad = Arc::new(RwLock::new(grid_pad)); - let block_meta_manager = - Arc::new(GridBlockMetaEditorManager::new(grid_id, &user, pad.read().await.get_blocks().clone()).await?); + let block_meta_manager = Arc::new( + GridBlockMetaEditorManager::new(grid_id, &user, pad.read().await.get_block_metas().clone()).await?, + ); Ok(Arc::new(Self { grid_id: grid_id.to_owned(), @@ -113,8 +114,11 @@ impl ClientGridEditor { } pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> { - let type_option_json_builder = - |field_type: &FieldType| -> String { default_type_option_builder_from_type(field_type).entry().json_str() }; + // let cell_metas = self.block_meta_manager.get_cell_metas(None, field_id, None).await?; + + let type_option_json_builder = |field_type: &FieldType| -> String { + return default_type_option_builder_from_type(field_type).entry().json_str(); + }; let _ = self .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) @@ -137,12 +141,12 @@ impl ClientGridEditor { } pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?; + let _ = self.modify(|grid| Ok(grid.create_block_meta(grid_block)?)).await?; Ok(()) } pub async fn update_block(&self, changeset: GridBlockMetaChangeset) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.update_block(changeset)?)).await?; + let _ = self.modify(|grid| Ok(grid.update_block_meta(changeset)?)).await?; Ok(()) } @@ -192,12 +196,15 @@ impl ClientGridEditor { pub async fn get_rows(&self, block_id: &str) -> FlowyResult { let block_ids = vec![block_id.to_owned()]; - let mut block_meta_data_vec = self.get_block_meta_data_vec(Some(&block_ids)).await?; - debug_assert_eq!(block_meta_data_vec.len(), 1); - if block_meta_data_vec.len() == 1 { - let block_meta_data = block_meta_data_vec.pop().unwrap(); + let mut grid_block_snapshot = self.grid_block_snapshots(Some(block_ids)).await?; + + // For the moment, we only support one block. + // We can save the rows into multiple blocks and load them asynchronously in the future. + debug_assert_eq!(grid_block_snapshot.len(), 1); + if grid_block_snapshot.len() == 1 { + let snapshot = grid_block_snapshot.pop().unwrap(); let field_metas = self.get_field_metas(None).await?; - let rows = make_rows_from_row_metas(&field_metas, &block_meta_data.row_metas); + let rows = make_rows_from_row_metas(&field_metas, &snapshot.row_metas); Ok(rows.into()) } else { Ok(vec![].into()) @@ -240,15 +247,12 @@ impl ClientGridEditor { } pub async fn get_blocks(&self, block_ids: Option>) -> FlowyResult { - let block_meta_data_vec = self.get_block_meta_data_vec(block_ids.as_ref()).await?; - match block_ids { - None => make_grid_blocks(block_meta_data_vec), - Some(block_ids) => make_grid_block_from_block_metas(&block_ids, block_meta_data_vec), - } + let block_snapshots = self.grid_block_snapshots(block_ids.clone()).await?; + make_grid_blocks(block_ids, block_snapshots) } pub async fn get_block_metas(&self) -> FlowyResult> { - let grid_blocks = self.pad.read().await.get_blocks(); + let grid_blocks = self.pad.read().await.get_block_metas(); Ok(grid_blocks) } @@ -266,7 +270,7 @@ impl ClientGridEditor { .pad .read() .await - .get_blocks() + .get_block_metas() .into_iter() .map(|grid_block_meta| GridBlockOrder { block_id: grid_block_meta.block_id, @@ -285,27 +289,18 @@ impl ClientGridEditor { Ok(field_metas) } - pub async fn get_block_meta_data_vec( - &self, - block_ids: Option<&Vec>, - ) -> FlowyResult> { - match block_ids { - None => { - let grid_blocks = self.pad.read().await.get_blocks(); - let row_metas_per_block = self - .block_meta_manager - .get_block_meta_data_from_blocks(grid_blocks) - .await?; - Ok(row_metas_per_block) - } - Some(block_ids) => { - let row_metas_per_block = self - .block_meta_manager - .get_block_meta_data(block_ids.as_slice()) - .await?; - Ok(row_metas_per_block) - } - } + pub async fn grid_block_snapshots(&self, block_ids: Option>) -> FlowyResult> { + let block_ids = block_ids.unwrap_or( + self.pad + .read() + .await + .get_block_metas() + .into_iter() + .map(|block_meta| block_meta.block_id) + .collect::>(), + ); + let snapshots = self.block_meta_manager.make_block_snapshots(block_ids).await?; + Ok(snapshots) } pub async fn delta_bytes(&self) -> Bytes { @@ -347,7 +342,7 @@ impl ClientGridEditor { } async fn block_id(&self) -> FlowyResult { - match self.pad.read().await.get_blocks().last() { + match self.pad.read().await.get_block_metas().last() { None => Err(FlowyError::internal().context("There is no grid block in this grid")), Some(grid_block) => Ok(grid_block.block_id.clone()), } 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 70cea1b4c8..55ee0ec8c8 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 @@ -22,7 +22,7 @@ impl RowIdsPerBlock { } } -pub struct GridBlockMetaData { +pub struct GridBlockSnapshot { pub(crate) block_id: String, pub row_metas: Vec>, } @@ -40,20 +40,6 @@ pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec>() } -pub(crate) fn make_grid_blocks(block_meta_snapshots: Vec) -> FlowyResult { - Ok(block_meta_snapshots - .into_iter() - .map(|block_meta_data| { - let row_orders = make_row_orders_from_row_metas(&block_meta_data.row_metas); - GridBlock { - id: block_meta_data.block_id, - row_orders, - } - }) - .collect::>() - .into()) -} - #[inline(always)] pub fn make_cell( field_map: &HashMap<&String, &FieldMeta>, @@ -101,25 +87,36 @@ pub(crate) fn make_rows_from_row_metas(fields: &[FieldMeta], row_metas: &[Arc>() } -pub(crate) fn make_grid_block_from_block_metas( - block_ids: &[String], - block_meta_data_vec: Vec, +pub(crate) fn make_grid_blocks( + block_ids: Option>, + block_snapshots: Vec, ) -> FlowyResult { - let block_meta_data_map: HashMap<&String, &Vec>> = block_meta_data_vec - .iter() - .map(|data| (&data.block_id, &data.row_metas)) - .collect(); + match block_ids { + None => Ok(block_snapshots + .into_iter() + .map(|snapshot| { + let row_orders = make_row_orders_from_row_metas(&snapshot.row_metas); + GridBlock::new(&snapshot.block_id, row_orders) + }) + .collect::>() + .into()), + Some(block_ids) => { + let block_meta_data_map: HashMap<&String, &Vec>> = block_snapshots + .iter() + .map(|data| (&data.block_id, &data.row_metas)) + .collect(); - let mut grid_blocks = vec![]; - for block_id in block_ids { - match block_meta_data_map.get(&block_id) { - None => {} - Some(row_metas) => { - let row_orders = make_row_orders_from_row_metas(row_metas); - grid_blocks.push(GridBlock::new(block_id, row_orders)); + let mut grid_blocks = vec![]; + for block_id in block_ids { + match block_meta_data_map.get(&block_id) { + None => {} + Some(row_metas) => { + let row_orders = make_row_orders_from_row_metas(row_metas); + grid_blocks.push(GridBlock::new(&block_id, row_orders)); + } + } } + Ok(grid_blocks.into()) } } - - Ok(grid_blocks.into()) } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 4dbb5c7a0c..858e9826cf 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -238,7 +238,7 @@ impl GridEditorTest { async fn get_row_metas(editor: &Arc) -> Vec> { editor - .get_block_meta_data_vec(None) + .grid_block_snapshots(None) .await .unwrap() .pop() diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index ad81fc532a..edb5236139 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -69,7 +69,7 @@ impl GridBlockMetaChangeset { } #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] -pub struct GridBlockMetaSerde { +pub struct GridBlockMetaData { #[pb(index = 1)] pub block_id: String, @@ -431,13 +431,13 @@ pub struct BuildGridContext { pub block_metas: GridBlockMeta, #[pb(index = 3)] - pub block_meta_data: GridBlockMetaSerde, + pub block_meta_data: GridBlockMetaData, } impl std::default::Default for BuildGridContext { fn default() -> Self { let grid_block = GridBlockMeta::new(); - let grid_block_meta_data = GridBlockMetaSerde { + let grid_block_meta_data = GridBlockMetaData { block_id: grid_block.block_id.clone(), row_metas: vec![], }; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index 4b0de2d3fb..97e14eb738 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -510,7 +510,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockMeta { } #[derive(PartialEq,Clone,Default)] -pub struct GridBlockMetaSerde { +pub struct GridBlockMetaData { // message fields pub block_id: ::std::string::String, pub row_metas: ::protobuf::RepeatedField, @@ -519,14 +519,14 @@ pub struct GridBlockMetaSerde { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a GridBlockMetaSerde { - fn default() -> &'a GridBlockMetaSerde { - ::default_instance() +impl<'a> ::std::default::Default for &'a GridBlockMetaData { + fn default() -> &'a GridBlockMetaData { + ::default_instance() } } -impl GridBlockMetaSerde { - pub fn new() -> GridBlockMetaSerde { +impl GridBlockMetaData { + pub fn new() -> GridBlockMetaData { ::std::default::Default::default() } @@ -582,7 +582,7 @@ impl GridBlockMetaSerde { } } -impl ::protobuf::Message for GridBlockMetaSerde { +impl ::protobuf::Message for GridBlockMetaData { fn is_initialized(&self) -> bool { for v in &self.row_metas { if !v.is_initialized() { @@ -665,8 +665,8 @@ impl ::protobuf::Message for GridBlockMetaSerde { Self::descriptor_static() } - fn new() -> GridBlockMetaSerde { - GridBlockMetaSerde::new() + fn new() -> GridBlockMetaData { + GridBlockMetaData::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -675,29 +675,29 @@ impl ::protobuf::Message for GridBlockMetaSerde { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "block_id", - |m: &GridBlockMetaSerde| { &m.block_id }, - |m: &mut GridBlockMetaSerde| { &mut m.block_id }, + |m: &GridBlockMetaData| { &m.block_id }, + |m: &mut GridBlockMetaData| { &mut m.block_id }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "row_metas", - |m: &GridBlockMetaSerde| { &m.row_metas }, - |m: &mut GridBlockMetaSerde| { &mut m.row_metas }, + |m: &GridBlockMetaData| { &m.row_metas }, + |m: &mut GridBlockMetaData| { &mut m.row_metas }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "GridBlockMetaSerde", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "GridBlockMetaData", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static GridBlockMetaSerde { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(GridBlockMetaSerde::new) + fn default_instance() -> &'static GridBlockMetaData { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(GridBlockMetaData::new) } } -impl ::protobuf::Clear for GridBlockMetaSerde { +impl ::protobuf::Clear for GridBlockMetaData { fn clear(&mut self) { self.block_id.clear(); self.row_metas.clear(); @@ -705,13 +705,13 @@ impl ::protobuf::Clear for GridBlockMetaSerde { } } -impl ::std::fmt::Debug for GridBlockMetaSerde { +impl ::std::fmt::Debug for GridBlockMetaData { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for GridBlockMetaSerde { +impl ::protobuf::reflect::ProtobufValue for GridBlockMetaData { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -3331,7 +3331,7 @@ pub struct BuildGridContext { // message fields pub field_metas: ::protobuf::RepeatedField, pub block_metas: ::protobuf::SingularPtrField, - pub block_meta_data: ::protobuf::SingularPtrField, + pub block_meta_data: ::protobuf::SingularPtrField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -3406,11 +3406,11 @@ impl BuildGridContext { self.block_metas.take().unwrap_or_else(|| GridBlockMeta::new()) } - // .GridBlockMetaSerde block_meta_data = 3; + // .GridBlockMetaData block_meta_data = 3; - pub fn get_block_meta_data(&self) -> &GridBlockMetaSerde { - self.block_meta_data.as_ref().unwrap_or_else(|| ::default_instance()) + pub fn get_block_meta_data(&self) -> &GridBlockMetaData { + self.block_meta_data.as_ref().unwrap_or_else(|| ::default_instance()) } pub fn clear_block_meta_data(&mut self) { self.block_meta_data.clear(); @@ -3421,13 +3421,13 @@ impl BuildGridContext { } // Param is passed by value, moved - pub fn set_block_meta_data(&mut self, v: GridBlockMetaSerde) { + pub fn set_block_meta_data(&mut self, v: GridBlockMetaData) { self.block_meta_data = ::protobuf::SingularPtrField::some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_block_meta_data(&mut self) -> &mut GridBlockMetaSerde { + pub fn mut_block_meta_data(&mut self) -> &mut GridBlockMetaData { if self.block_meta_data.is_none() { self.block_meta_data.set_default(); } @@ -3435,8 +3435,8 @@ impl BuildGridContext { } // Take field - pub fn take_block_meta_data(&mut self) -> GridBlockMetaSerde { - self.block_meta_data.take().unwrap_or_else(|| GridBlockMetaSerde::new()) + pub fn take_block_meta_data(&mut self) -> GridBlockMetaData { + self.block_meta_data.take().unwrap_or_else(|| GridBlockMetaData::new()) } } @@ -3566,7 +3566,7 @@ impl ::protobuf::Message for BuildGridContext { |m: &BuildGridContext| { &m.block_metas }, |m: &mut BuildGridContext| { &mut m.block_metas }, )); - fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( "block_meta_data", |m: &BuildGridContext| { &m.block_meta_data }, |m: &mut BuildGridContext| { &mut m.block_meta_data }, @@ -3674,10 +3674,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\ s\x12/\n\x0bblock_metas\x18\x03\x20\x03(\x0b2\x0e.GridBlockMetaR\nblockM\ etas\"o\n\rGridBlockMeta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07bl\ ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ - \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"V\n\x12GridBlockMet\ - aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\ - metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\x99\x02\n\tFieldM\ - eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ + \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"U\n\x11GridBlockMet\ + aData\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_m\ + etas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\x99\x02\n\tFieldMe\ + ta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ @@ -3717,11 +3717,11 @@ static file_descriptor_proto_data: &'static [u8] = b"\ (\tR\x04data\"\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\ \x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05ro\ wId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04da\ - ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10Bui\ + ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xac\x01\n\x10Bui\ ldGridContext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\n\ fieldMetas\x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMeta\ - R\nblockMetas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBl\ - ockMetaSerdeR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\ + R\nblockMetas\x12:\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x12.GridBl\ + ockMetaDataR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\ \x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSi\ ngleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbo\ x\x10\x05b\x06proto3\ diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 897143247b..ca00b88b57 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -10,7 +10,7 @@ message GridBlockMeta { int32 start_row_index = 2; int32 row_count = 3; } -message GridBlockMetaSerde { +message GridBlockMetaData { string block_id = 1; repeated RowMeta row_metas = 2; } @@ -68,7 +68,7 @@ message CellMetaChangeset { message BuildGridContext { repeated FieldMeta field_metas = 1; GridBlockMeta block_metas = 2; - GridBlockMetaSerde block_meta_data = 3; + GridBlockMetaData block_meta_data = 3; } enum FieldType { RichText = 0; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index 768c7bf60a..0b9459a625 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -1,10 +1,11 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; -use flowy_grid_data_model::entities::{GridBlockMetaSerde, RowMeta, RowMetaChangeset}; +use flowy_grid_data_model::entities::{CellMeta, GridBlockMetaData, RowMeta, RowMetaChangeset}; use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -25,12 +26,12 @@ impl GridBlockMetaPad { let s = delta.to_str()?; tracing::info!("delta: {}", delta); tracing::info!("{}", s); - let block_meta: GridBlockMetaSerde = serde_json::from_str(&s).map_err(|e| { + let meta_data: GridBlockMetaData = serde_json::from_str(&s).map_err(|e| { let msg = format!("Deserialize delta to block meta failed: {}", e); CollaborateError::internal().context(msg) })?; - let block_id = block_meta.block_id; - let rows = block_meta + let block_id = meta_data.block_id; + let rows = meta_data .row_metas .into_iter() .map(Arc::new) @@ -78,7 +79,7 @@ impl GridBlockMetaPad { }) } - pub fn get_row_metas(&self, row_ids: Option>) -> CollaborateResult>> { + pub fn get_row_metas(&self, row_ids: &Option>) -> CollaborateResult>> { match row_ids { None => Ok(self.row_metas.to_vec()), Some(row_ids) => { @@ -102,6 +103,18 @@ impl GridBlockMetaPad { } } + pub fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> CollaborateResult> { + let rows = self.get_row_metas(row_ids)?; + let cell_metas = rows + .iter() + .flat_map(|row| { + let cell_meta = row.cell_by_field_id.get(field_id)?; + Some(cell_meta.clone()) + }) + .collect::>(); + Ok(cell_metas) + } + pub fn number_of_rows(&self) -> i32 { self.row_metas.len() as i32 } @@ -186,12 +199,12 @@ pub struct GridBlockMetaChange { pub md5: String, } -pub fn make_block_meta_delta(grid_block_meta_data: &GridBlockMetaSerde) -> GridBlockMetaDelta { +pub fn make_block_meta_delta(grid_block_meta_data: &GridBlockMetaData) -> GridBlockMetaDelta { let json = serde_json::to_string(&grid_block_meta_data).unwrap(); PlainTextDeltaBuilder::new().insert(&json).build() } -pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlockMetaSerde) -> RepeatedRevision { +pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlockMetaData) -> RepeatedRevision { let delta = make_block_meta_delta(grid_block_meta_data); let bytes = delta.to_delta_bytes(); let revision = Revision::initial_revision(user_id, &grid_block_meta_data.block_id, bytes); @@ -200,7 +213,7 @@ pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlock impl std::default::Default for GridBlockMetaPad { fn default() -> Self { - let block_meta_data = GridBlockMetaSerde { + let block_meta_data = GridBlockMetaData { block_id: uuid(), row_metas: vec![], }; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs index 2875a8968c..2b91e1352c 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs @@ -41,7 +41,7 @@ fn check_rows(fields: &[FieldMeta], rows: &[RowMeta]) -> CollaborateResult<()> { mod tests { use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBuilder}; - use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMetaSerde, GridMeta}; + use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMetaData, GridMeta}; #[test] fn create_default_grid_test() { @@ -64,6 +64,6 @@ mod tests { let _: GridMeta = serde_json::from_str(&grid_meta_delta.to_str().unwrap()).unwrap(); let grid_block_meta_delta = make_block_meta_delta(&build_context.block_meta_data); - let _: GridBlockMetaSerde = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap(); + let _: GridBlockMetaData = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap(); } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 2d32fd1d9e..513a1ea9ec 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -212,7 +212,7 @@ impl GridMetaPad { } } - pub fn create_block(&mut self, block: GridBlockMeta) -> CollaborateResult> { + pub fn create_block_meta(&mut self, block: GridBlockMeta) -> CollaborateResult> { self.modify_grid(|grid| { if grid.block_metas.iter().any(|b| b.block_id == block.block_id) { tracing::warn!("Duplicate grid block"); @@ -235,11 +235,11 @@ impl GridMetaPad { }) } - pub fn get_blocks(&self) -> Vec { + pub fn get_block_metas(&self) -> Vec { self.grid_meta.block_metas.clone() } - pub fn update_block(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult> { + pub fn update_block_meta(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult> { let block_id = changeset.block_id.clone(); self.modify_block(&block_id, |block| { let mut is_changed = None; From ca45673a9ea159eb7ee97f1db984b594b9f2adfa Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 2 Apr 2022 21:17:20 +0800 Subject: [PATCH 28/47] chore: transform cell data --- .../src/services/block_meta_editor.rs | 3 +- .../type_options/checkbox_type_option.rs | 35 ++++- .../field/type_options/date_type_option.rs | 95 +++++++----- .../field/type_options/number_type_option.rs | 146 +++++++++++------- .../type_options/selection_type_option.rs | 48 +++++- .../field/type_options/text_type_option.rs | 82 +++++++++- .../field/type_options/type_option_data.rs | 6 +- .../flowy-grid/src/services/grid_editor.rs | 18 ++- .../src/services/row/cell_data_serde.rs | 67 +++++++- .../src/entities/meta.rs | 13 +- .../src/client_grid/grid_block_meta_pad.rs | 2 +- 11 files changed, 376 insertions(+), 139 deletions(-) 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 58e8e2ca9e..353185f498 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 @@ -148,9 +148,10 @@ impl GridBlockMetaEditorManager { } // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage. + #[allow(dead_code)] pub async fn get_cell_metas( &self, - block_ids: Option, + block_ids: Vec, field_id: &str, row_ids: Option>, ) -> FlowyResult> { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 3611f5a0db..84d693edd0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,11 +1,12 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::CellDataSerde; +use crate::services::row::{CellDataSerde, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; +use std::str::FromStr; #[derive(Default)] pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); @@ -36,17 +37,30 @@ pub struct CheckboxTypeOption { } impl_type_option!(CheckboxTypeOption, FieldType::Checkbox); +const YES: &str = "Yes"; +const NO: &str = "No"; + impl CellDataSerde for CheckboxTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - data + fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if !type_option_cell_data.is_text() || !type_option_cell_data.is_checkbox() { + return String::new(); + } + let cell_data = type_option_cell_data.data; + if cell_data == YES || cell_data == NO { + return cell_data; + } + } + + String::new() } fn serialize_cell_data(&self, data: &str) -> Result { let s = match string_to_bool(data) { - true => "No", - false => "Yes", + true => YES, + false => NO, }; - Ok(s.to_owned()) + Ok(TypeOptionCellData::new(s, self.field_type()).json()) } } @@ -66,11 +80,15 @@ fn string_to_bool(bool_str: &str) -> bool { #[cfg(test)] mod tests { use crate::services::field::CheckboxTypeOption; + use crate::services::field::FieldBuilder; use crate::services::row::CellDataSerde; + use flowy_grid_data_model::entities::FieldType; #[test] fn checkout_box_description_test() { let type_option = CheckboxTypeOption::default(); + let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); + assert_eq!(type_option.serialize_cell_data("true").unwrap(), "1".to_owned()); assert_eq!(type_option.serialize_cell_data("1").unwrap(), "1".to_owned()); assert_eq!(type_option.serialize_cell_data("yes").unwrap(), "1".to_owned()); @@ -79,6 +97,9 @@ mod tests { assert_eq!(type_option.serialize_cell_data("no").unwrap(), "0".to_owned()); assert_eq!(type_option.serialize_cell_data("123").unwrap(), "0".to_owned()); - assert_eq!(type_option.deserialize_cell_data("1".to_owned()), "1".to_owned()); + assert_eq!( + type_option.deserialize_cell_data("1".to_owned(), &field_meta), + "1".to_owned() + ); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 86c15e13c5..5dd88a4a67 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,5 +1,5 @@ use crate::impl_type_option; -use crate::services::row::CellDataSerde; +use crate::services::row::{CellDataSerde, TypeOptionCellData}; use bytes::Bytes; use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; @@ -7,6 +7,7 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; +use std::str::FromStr; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use strum_macros::EnumIter; @@ -32,25 +33,34 @@ impl DateTypeOption { fn today_from_native(&self, naive: chrono::NaiveDateTime) -> String { let utc: chrono::DateTime = chrono::DateTime::from_utc(naive, chrono::Utc); let local: chrono::DateTime = chrono::DateTime::from(utc); - - let fmt_str = format!("{} {}", self.date_format.format_str(), self.time_format.format_str()); - let output = format!("{}", local.format_with_items(StrftimeItems::new(&fmt_str))); + let output = format!("{}", local.format_with_items(StrftimeItems::new(&self.fmt_str()))); output } + + fn fmt_str(&self) -> String { + format!("{} {}", self.date_format.format_str(), self.time_format.format_str()) + } } impl CellDataSerde for DateTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - match data.parse::() { - Ok(timestamp) => { - let native = NaiveDateTime::from_timestamp(timestamp, 0); - self.today_from_native(native) + fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if !type_option_cell_data.is_date() { + return String::new(); } - Err(e) => { - tracing::debug!("DateDescription format {} fail. error: {:?}", data, e); - String::new() + + let cell_data = type_option_cell_data.data; + if let Ok(timestamp) = cell_data.parse::() { + let native = NaiveDateTime::from_timestamp(timestamp, 0); + return self.today_from_native(native); + } + + if NaiveDateTime::parse_from_str(&cell_data, &self.fmt_str()).is_ok() { + return cell_data; } } + + String::new() } fn serialize_cell_data(&self, data: &str) -> Result { @@ -58,7 +68,8 @@ impl CellDataSerde for DateTypeOption { tracing::error!("Parse {} to i64 failed: {}", data, e); return Err(FlowyError::internal().context(e)); }; - Ok(data.to_owned()) + + Ok(TypeOptionCellData::new(data, self.field_type()).json()) } } @@ -172,56 +183,59 @@ impl std::default::Default for TimeFormat { #[cfg(test)] mod tests { + use crate::services::field::FieldBuilder; use crate::services::field::{DateFormat, DateTypeOption, TimeFormat}; - use crate::services::row::CellDataSerde; + use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use flowy_grid_data_model::entities::FieldType; use strum::IntoEnumIterator; #[test] - fn date_description_date_format_test() { - let mut description = DateTypeOption::default(); - let _timestamp = 1647251762; + fn date_description_invalid_input_test() { + let type_option = DateTypeOption::default(); + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); + assert_eq!( + "".to_owned(), + type_option.deserialize_cell_data("1e".to_owned(), &field_meta) + ); + } + #[test] + fn date_description_date_format_test() { + let mut type_option = DateTypeOption::default(); + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); for date_format in DateFormat::iter() { - description.date_format = date_format; + type_option.date_format = date_format; match date_format { DateFormat::Friendly => { assert_eq!( "Mar 14,2022 17:56".to_owned(), - description.today_from_timestamp(1647251762) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); assert_eq!( "Mar 14,2022 17:56".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("Mar 14,2022 17:56"), &field_meta) ); } DateFormat::US => { assert_eq!( "2022/03/14 17:56".to_owned(), - description.today_from_timestamp(1647251762) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); assert_eq!( "2022/03/14 17:56".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("2022/03/14 17:56"), &field_meta) ); } DateFormat::ISO => { assert_eq!( "2022-03-14 17:56".to_owned(), - description.today_from_timestamp(1647251762) - ); - assert_eq!( - "2022-03-14 17:56".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); } DateFormat::Local => { assert_eq!( "2022/03/14 17:56".to_owned(), - description.today_from_timestamp(1647251762) - ); - assert_eq!( - "2022/03/14 17:56".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); } } @@ -230,28 +244,29 @@ mod tests { #[test] fn date_description_time_format_test() { - let mut description = DateTypeOption::default(); + let mut type_option = DateTypeOption::default(); + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); for time_format in TimeFormat::iter() { - description.time_format = time_format; + type_option.time_format = time_format; match time_format { TimeFormat::TwentyFourHour => { assert_eq!( "Mar 14,2022 17:56".to_owned(), - description.today_from_timestamp(1647251762) + type_option.today_from_timestamp(1647251762) ); assert_eq!( "Mar 14,2022 17:56".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); } TimeFormat::TwelveHour => { assert_eq!( "Mar 14,2022 05:56:02 PM".to_owned(), - description.today_from_timestamp(1647251762) + type_option.today_from_timestamp(1647251762) ); assert_eq!( "Mar 14,2022 05:56:02 PM".to_owned(), - description.deserialize_cell_data("1647251762".to_owned()) + type_option.deserialize_cell_data(data("1647251762"), &field_meta) ); } } @@ -264,4 +279,8 @@ mod tests { let type_option = DateTypeOption::default(); type_option.serialize_cell_data("he").unwrap(); } + + fn data(s: &str) -> String { + TypeOptionCellData::new(s, FieldType::DateTime).json() + } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 7e557955df..7cee8a3b39 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -1,10 +1,10 @@ use crate::impl_type_option; -use crate::services::row::CellDataSerde; +use crate::services::row::{CellDataSerde, TypeOptionCellData}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use lazy_static::lazy_static; -use rust_decimal::prelude::Zero; + use rust_decimal::Decimal; use rusty_money::iso::{Currency, CNY, EUR, USD}; use serde::{Deserialize, Serialize}; @@ -76,6 +76,42 @@ pub struct NumberTypeOption { } impl_type_option!(NumberTypeOption, FieldType::Number); +impl CellDataSerde for NumberTypeOption { + fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if type_option_cell_data.is_date() { + return String::new(); + } + + let cell_data = type_option_cell_data.data; + match self.format { + NumberFormat::Number => { + if cell_data.parse::().is_ok() { + cell_data + } else { + String::new() + } + } + NumberFormat::USD => self.money_from_str(&cell_data, USD), + NumberFormat::CNY => self.money_from_str(&cell_data, CNY), + NumberFormat::EUR => self.money_from_str(&cell_data, EUR), + } + } else { + String::new() + } + } + + fn serialize_cell_data(&self, data: &str) -> Result { + let data = self.strip_symbol(data); + + if !data.chars().all(char::is_numeric) { + return Err(FlowyError::invalid_data().context("Should only contain numbers")); + } + + Ok(TypeOptionCellData::new(&data, self.field_type()).json()) + } +} + impl std::default::Default for NumberTypeOption { fn default() -> Self { let format = NumberFormat::default(); @@ -96,22 +132,21 @@ impl NumberTypeOption { self.symbol = format.symbol(); } - fn decimal_from_str(&self, s: &str) -> Decimal { - let mut decimal = Decimal::from_str(s).unwrap_or_else(|_| Decimal::zero()); - match decimal.set_scale(self.scale) { - Ok(_) => {} - Err(e) => { - tracing::error!("Set decimal scale failed: {:?}", e); - } - } - decimal.set_sign_positive(self.sign_positive); - decimal - } - fn money_from_str(&self, s: &str, currency: &'static Currency) -> String { - let decimal = self.decimal_from_str(s); - let money = rusty_money::Money::from_decimal(decimal, currency); - money.to_string() + match Decimal::from_str(s) { + Ok(mut decimal) => { + match decimal.set_scale(self.scale) { + Ok(_) => {} + Err(e) => { + tracing::error!("Set decimal scale failed: {:?}", e); + } + } + decimal.set_sign_positive(self.sign_positive); + let money = rusty_money::Money::from_decimal(decimal, currency); + money.to_string() + } + Err(_) => String::new(), + } } fn strip_symbol(&self, s: &str) -> String { @@ -158,26 +193,6 @@ impl NumberFormat { } } -impl CellDataSerde for NumberTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - match self.format { - NumberFormat::Number => data, - NumberFormat::USD => self.money_from_str(&data, USD), - NumberFormat::CNY => self.money_from_str(&data, CNY), - NumberFormat::EUR => self.money_from_str(&data, EUR), - } - } - - fn serialize_cell_data(&self, data: &str) -> Result { - let data = self.strip_symbol(data); - - if !data.chars().all(char::is_numeric) { - return Err(FlowyError::invalid_data().context("Should only contain numbers")); - } - Ok(data) - } -} - fn make_strip_symbol() -> Vec { let mut symbols = vec![",".to_owned(), ".".to_owned()]; for format in NumberFormat::iter() { @@ -188,41 +203,60 @@ fn make_strip_symbol() -> Vec { #[cfg(test)] mod tests { + use crate::services::field::FieldBuilder; use crate::services::field::{NumberFormat, NumberTypeOption}; - use crate::services::row::CellDataSerde; + use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use flowy_grid_data_model::entities::FieldType; use strum::IntoEnumIterator; + #[test] + fn number_description_invalid_input_test() { + let type_option = NumberTypeOption::default(); + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); + assert_eq!("".to_owned(), type_option.deserialize_cell_data(data(""), &field_meta)); + assert_eq!( + "".to_owned(), + type_option.deserialize_cell_data(data("abc"), &field_meta) + ); + } + #[test] fn number_description_test() { let mut type_option = NumberTypeOption::default(); - assert_eq!(type_option.serialize_cell_data("Â¥18,443").unwrap(), "18443".to_owned()); - assert_eq!(type_option.serialize_cell_data("$18,443").unwrap(), "18443".to_owned()); - assert_eq!(type_option.serialize_cell_data("€18.443").unwrap(), "18443".to_owned()); + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); + assert_eq!(type_option.strip_symbol("Â¥18,443"), "18443".to_owned()); + assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned()); + assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned()); for format in NumberFormat::iter() { type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "$18,443".to_owned() ); + assert_eq!(type_option.deserialize_cell_data(data(""), &field_meta), "".to_owned()); + assert_eq!( + type_option.deserialize_cell_data(data("abc"), &field_meta), + "".to_owned() + ); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "€18.443".to_owned() ); } @@ -230,37 +264,42 @@ mod tests { } } + fn data(s: &str) -> String { + TypeOptionCellData::new(s, FieldType::Number).json() + } + #[test] fn number_description_scale_test() { let mut type_option = NumberTypeOption { scale: 1, ..Default::default() }; + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); for format in NumberFormat::iter() { type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "$1,844.3".to_owned() ); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "Â¥1,844.3".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "€1.844,3".to_owned() ); } @@ -274,31 +313,32 @@ mod tests { sign_positive: false, ..Default::default() }; + let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); for format in NumberFormat::iter() { type_option.format = format; match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "-$18,443".to_owned() ); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "-Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data("18443".to_owned()), + type_option.deserialize_cell_data(data("18443"), &field_meta), "-€18.443".to_owned() ); } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index abc9c81288..5768a92f70 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,6 +1,6 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::CellDataSerde; +use crate::services::row::{CellDataSerde, TypeOptionCellData}; use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -8,6 +8,7 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; +use std::str::FromStr; use uuid::Uuid; pub const SELECTION_IDS_SEPARATOR: &str = ","; @@ -24,12 +25,25 @@ pub struct SingleSelectTypeOption { impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl CellDataSerde for SingleSelectTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - data + fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { + return String::new(); + } + + let option_id = type_option_cell_data.data; + match self.options.iter().find(|option| option.id == option_id) { + None => String::new(), + Some(option) => option.name.clone(), + } + } else { + String::new() + } } fn serialize_cell_data(&self, data: &str) -> Result { - single_select_option_id_from_data(data.to_owned()) + let data = single_select_option_id_from_data(data.to_owned())?; + Ok(TypeOptionCellData::new(&data, self.field_type()).json()) } } @@ -67,12 +81,32 @@ pub struct MultiSelectTypeOption { impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); impl CellDataSerde for MultiSelectTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - data + fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { + return String::new(); + } + + match select_option_ids(type_option_cell_data.data) { + Ok(option_ids) => { + // + self.options + .iter() + .filter(|option| option_ids.contains(&option.id)) + .map(|option| option.name.clone()) + .collect::>() + .join(SELECTION_IDS_SEPARATOR) + } + Err(_) => String::new(), + } + } else { + String::new() + } } fn serialize_cell_data(&self, data: &str) -> Result { - multi_select_option_id_from_data(data.to_owned()) + let data = multi_select_option_id_from_data(data.to_owned())?; + Ok(TypeOptionCellData::new(&data, self.field_type()).json()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 6bffc8606f..87434a3cdb 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,11 +1,12 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::CellDataSerde; +use crate::services::row::{deserialize_cell_data, CellDataSerde, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; +use std::str::FromStr; #[derive(Default)] pub struct RichTextTypeOptionBuilder(RichTextTypeOption); @@ -30,8 +31,20 @@ pub struct RichTextTypeOption { impl_type_option!(RichTextTypeOption, FieldType::RichText); impl CellDataSerde for RichTextTypeOption { - fn deserialize_cell_data(&self, data: String) -> String { - data + fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { + if type_option_cell_data.is_date() + || type_option_cell_data.is_single_select() + || type_option_cell_data.is_multi_select() + || type_option_cell_data.is_number() + { + deserialize_cell_data(data, field_meta).unwrap_or_else(|_| "".to_owned()) + } else { + type_option_cell_data.data + } + } else { + String::new() + } } fn serialize_cell_data(&self, data: &str) -> Result { @@ -39,7 +52,68 @@ impl CellDataSerde for RichTextTypeOption { if data.len() > 10000 { Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000")) } else { - Ok(data) + Ok(TypeOptionCellData::new(&data, self.field_type()).json()) } } } + +#[cfg(test)] +mod tests { + use crate::services::field::FieldBuilder; + use crate::services::field::*; + use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use flowy_grid_data_model::entities::FieldType; + + #[test] + fn text_description_test() { + let type_option = RichTextTypeOption::default(); + + // date + let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); + let data = TypeOptionCellData::new("1647251762", FieldType::DateTime).json(); + assert_eq!( + type_option.deserialize_cell_data(data, &date_time_field_meta), + "Mar 14,2022 17:56".to_owned() + ); + + // Single select + let done_option = SelectOption::new("Done"); + let done_option_id = done_option.id.clone(); + let single_select = SingleSelectTypeOptionBuilder::default().option(done_option); + let single_select_field_meta = FieldBuilder::new(single_select).build(); + let data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); + assert_eq!( + type_option.deserialize_cell_data(data, &single_select_field_meta), + "Done".to_owned() + ); + + // Multiple select + let google_option = SelectOption::new("Google"); + let google_option_id = google_option.id.clone(); + let facebook_option = SelectOption::new("Facebook"); + let face_option_id = facebook_option.id.clone(); + let multi_select = MultiSelectTypeOptionBuilder::default() + .option(google_option) + .option(facebook_option) + .option(SelectOption::new("Twitter")); + let multi_select_field_meta = FieldBuilder::new(multi_select).build(); + let data = TypeOptionCellData::new( + &vec![google_option_id, face_option_id].join(SELECTION_IDS_SEPARATOR), + FieldType::SingleSelect, + ) + .json(); + assert_eq!( + type_option.deserialize_cell_data(data, &multi_select_field_meta), + "Google,Facebook".to_owned() + ); + + //Number + let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD); + let number_field_meta = FieldBuilder::new(number).build(); + let data = TypeOptionCellData::new("18443", FieldType::Number).json(); + assert_eq!( + type_option.deserialize_cell_data(data, &number_field_meta), + "$18,443".to_owned() + ); + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs index fbba14feab..8b13789179 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs @@ -1,5 +1 @@ -// #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] -// pub struct TypeOptionData { -// #[pb(index = 1)] -// pub map: HashMap, -// } + 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 88738aa082..e7d57634b8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -114,7 +114,16 @@ impl ClientGridEditor { } pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> { - // let cell_metas = self.block_meta_manager.get_cell_metas(None, field_id, None).await?; + // let block_ids = self + // .get_block_metas() + // .await? + // .into_iter() + // .map(|block_meta| block_meta.block_id) + // .collect(); + // let cell_metas = self + // .block_meta_manager + // .get_cell_metas(block_ids, field_id, None) + // .await?; let type_option_json_builder = |field_type: &FieldType| -> String { return default_type_option_builder_from_type(field_type).entry().json_str(); @@ -290,15 +299,16 @@ impl ClientGridEditor { } pub async fn grid_block_snapshots(&self, block_ids: Option>) -> FlowyResult> { - let block_ids = block_ids.unwrap_or( - self.pad + let block_ids = match block_ids { + None => self.pad .read() .await .get_block_metas() .into_iter() .map(|block_meta| block_meta.block_id) .collect::>(), - ); + Some(block_ids) => block_ids, + }; let snapshots = self.block_meta_manager.make_block_snapshots(block_ids).await?; Ok(snapshots) } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs index 1e60583df8..259e052ab7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs @@ -1,12 +1,65 @@ use crate::services::field::*; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use serde::{Deserialize, Serialize}; pub trait CellDataSerde { - fn deserialize_cell_data(&self, data: String) -> String; + fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String; fn serialize_cell_data(&self, data: &str) -> Result; } +#[derive(Serialize, Deserialize)] +pub struct TypeOptionCellData { + pub data: String, + pub field_type: FieldType, +} + +impl std::str::FromStr for TypeOptionCellData { + type Err = FlowyError; + + fn from_str(s: &str) -> Result { + let type_option_cell_data: TypeOptionCellData = serde_json::from_str(s)?; + Ok(type_option_cell_data) + } +} + +impl TypeOptionCellData { + pub fn new(data: &str, field_type: FieldType) -> Self { + TypeOptionCellData { + data: data.to_owned(), + field_type, + } + } + + pub fn json(&self) -> String { + serde_json::to_string(self).unwrap_or_else(|_| "".to_owned()) + } + + pub fn is_number(&self) -> bool { + self.field_type == FieldType::Number + } + + pub fn is_text(&self) -> bool { + self.field_type == FieldType::RichText + } + + pub fn is_checkbox(&self) -> bool { + self.field_type == FieldType::Checkbox + } + + pub fn is_date(&self) -> bool { + self.field_type == FieldType::DateTime + } + + pub fn is_single_select(&self) -> bool { + self.field_type == FieldType::SingleSelect + } + + pub fn is_multi_select(&self) -> bool { + self.field_type == FieldType::MultiSelect + } +} + #[allow(dead_code)] pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result { match field_meta.field_type { @@ -21,12 +74,12 @@ pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result Result { let s = match field_meta.field_type { - FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), }; Ok(s) } diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index edb5236139..a543085a78 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -246,6 +246,7 @@ impl TryInto for FieldChangesetPayload { #[derive( Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumCountMacro, EnumString, EnumIter, Display, Serialize, Deserialize, )] +#[repr(u8)] pub enum FieldType { RichText = 0, Number = 1, @@ -278,18 +279,6 @@ impl FieldType { let ty = self.clone(); format!("{}", ty as u8) } - - pub fn from_type_id(type_id: &str) -> Result { - match type_id { - "0" => Ok(FieldType::RichText), - "1" => Ok(FieldType::Number), - "2" => Ok(FieldType::DateTime), - "3" => Ok(FieldType::SingleSelect), - "4" => Ok(FieldType::MultiSelect), - "5" => Ok(FieldType::Checkbox), - _ => Err(format!("Invalid type_id: {}", type_id)), - } - } } #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index 0b9459a625..c0b86ac4af 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -5,7 +5,7 @@ use flowy_grid_data_model::entities::{CellMeta, GridBlockMetaData, RowMeta, RowM use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; -use std::borrow::Cow; + use std::collections::HashMap; use std::sync::Arc; From 6ac2617113c15311245e5df730c3528e129493d2 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 2 Apr 2022 23:48:56 +0800 Subject: [PATCH 29/47] chore: update row state using provider --- .../application/grid/row/row_bloc.dart | 10 --- .../grid/src/widgets/content/grid_row.dart | 65 ++++++++++++------- .../flowy-grid/src/services/grid_editor.rs | 8 ++- .../src/client_grid/grid_block_meta_pad.rs | 3 +- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index ac99eac67b..6fc7221a76 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -41,12 +41,6 @@ class RowBloc extends Bloc { createRow: (_CreateRow value) { rowService.createRow(); }, - activeRow: (_ActiveRow value) { - emit(state.copyWith(active: true)); - }, - disactiveRow: (_DisactiveRow value) { - emit(state.copyWith(active: false)); - }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { emit(state.copyWith(fields: value.fields)); add(const RowEvent.didUpdateCell()); @@ -133,8 +127,6 @@ class RowBloc extends Bloc { class RowEvent with _$RowEvent { const factory RowEvent.initial() = _InitialRow; const factory RowEvent.createRow() = _CreateRow; - const factory RowEvent.activeRow() = _ActiveRow; - const factory RowEvent.disactiveRow() = _DisactiveRow; const factory RowEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; const factory RowEvent.didUpdateCell() = _DidUpdateCell; } @@ -143,7 +135,6 @@ class RowEvent with _$RowEvent { class RowState with _$RowState { const factory RowState({ required String rowId, - required bool active, required double rowHeight, required List fields, required Future> row, @@ -152,7 +143,6 @@ class RowState with _$RowState { factory RowState.initial(GridRowData data) => RowState( rowId: data.rowId, - active: false, rowHeight: data.height, fields: data.fields, row: Future(() => none()), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index b8834cd213..23918401c4 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -6,6 +6,7 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; import 'cell_builder.dart'; import 'cell_container.dart'; @@ -19,10 +20,12 @@ class GridRowWidget extends StatefulWidget { class _GridRowWidgetState extends State { late RowBloc _rowBloc; + late RowRegionStateNotifier _rowStateNotifier; @override void initState() { _rowBloc = getIt(param1: widget.data)..add(const RowEvent.initial()); + _rowStateNotifier = RowRegionStateNotifier(); super.initState(); } @@ -30,25 +33,28 @@ class _GridRowWidgetState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _rowBloc, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), - onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), - child: BlocBuilder( - buildWhen: (p, c) => p.rowHeight != c.rowHeight, - builder: (context, state) { - return SizedBox( - height: _rowBloc.state.rowHeight, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: const [ - _RowLeading(), - _RowCells(), - _RowTrailing(), - ], - ), - ); - }, + child: ChangeNotifierProvider.value( + value: _rowStateNotifier, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (p) => _rowStateNotifier.onEnter = true, + onExit: (p) => _rowStateNotifier.onEnter = false, + child: BlocBuilder( + buildWhen: (p, c) => p.rowHeight != c.rowHeight, + builder: (context, state) { + return SizedBox( + height: _rowBloc.state.rowHeight, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: const [ + _RowLeading(), + _RowCells(), + _RowTrailing(), + ], + ), + ); + }, + ), ), ), ); @@ -57,6 +63,7 @@ class _GridRowWidgetState extends State { @override Future dispose() async { _rowBloc.close(); + _rowStateNotifier.dispose(); super.dispose(); } } @@ -66,10 +73,9 @@ class _RowLeading extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocSelector( - selector: (state) => state.active, - builder: (context, isActive) { - return SizedBox(width: GridSize.leadingHeaderPadding, child: isActive ? _activeWidget() : null); + return Consumer( + builder: (context, state, _) { + return SizedBox(width: GridSize.leadingHeaderPadding, child: state.onEnter ? _activeWidget() : null); }, ); } @@ -133,3 +139,16 @@ class _RowCells extends StatelessWidget { ); } } + +class RowRegionStateNotifier extends ChangeNotifier { + bool _onEnter = false; + + set onEnter(bool value) { + if (_onEnter != value) { + _onEnter = value; + notifyListeners(); + } + } + + bool get onEnter => _onEnter; +} 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 e7d57634b8..3925f80b24 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -233,7 +233,7 @@ impl ClientGridEditor { } } - pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { + pub async fn update_cell(&self, mut changeset: CellMetaChangeset) -> FlowyResult<()> { if let Some(cell_data) = changeset.data.as_ref() { match self.pad.read().await.get_field(&changeset.field_id) { None => { @@ -241,7 +241,8 @@ impl ClientGridEditor { .context(format!("Can not find the field with id: {}", &changeset.field_id))); } Some(field_meta) => { - let _ = serialize_cell_data(cell_data, field_meta)?; + let cell_data = serialize_cell_data(cell_data, field_meta)?; + changeset.data = Some(cell_data); } } } @@ -300,7 +301,8 @@ impl ClientGridEditor { pub async fn grid_block_snapshots(&self, block_ids: Option>) -> FlowyResult> { let block_ids = match block_ids { - None => self.pad + None => self + .pad .read() .await .get_block_metas() diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index c0b86ac4af..688b32cccc 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -24,8 +24,7 @@ pub struct GridBlockMetaPad { impl GridBlockMetaPad { pub fn from_delta(delta: GridBlockMetaDelta) -> CollaborateResult { let s = delta.to_str()?; - tracing::info!("delta: {}", delta); - tracing::info!("{}", s); + tracing::trace!("{}", s); let meta_data: GridBlockMetaData = serde_json::from_str(&s).map_err(|e| { let msg = format!("Deserialize delta to block meta failed: {}", e); CollaborateError::internal().context(msg) From 147e948b350e6f89b7bd7831618f1be1184b7c4f Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 2 Apr 2022 23:54:48 +0800 Subject: [PATCH 30/47] chore: add grid setting --- .../grid/src/widgets/header/grid_setting.dart | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart new file mode 100644 index 0000000000..dff1058c52 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart @@ -0,0 +1,35 @@ +enum GridSetting { + filter, + sortBy, + properties, +} + +extension _GridSettingExtension on GridSetting { + String iconName() { + switch (this) { + case GridSetting.filter: + // TODO: Handle this case. + break; + case GridSetting.sortBy: + // TODO: Handle this case. + break; + case GridSetting.properties: + // TODO: Handle this case. + break; + } + } + + String title() { + switch (this) { + case GridSetting.filter: + // TODO: Handle this case. + break; + case GridSetting.sortBy: + // TODO: Handle this case. + break; + case GridSetting.properties: + // TODO: Handle this case. + break; + } + } +} From 5d007c53598a5965549d76246539ebc10e55b79e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 3 Apr 2022 10:53:24 +0800 Subject: [PATCH 31/47] chore: grid setting list --- .../assets/images/editor/Icons 16/Yen.svg | 3 - .../setting/ascending.svg} | 0 .../setting/descending.svg} | 0 .../Filter.svg => grid/setting/filter.svg} | 0 .../setting/properties.svg} | 0 .../assets/images/grid/setting/setting.svg | 4 + .../assets/images/grid/setting/sort.svg | 4 + .../app_flowy/assets/translations/en.json | 5 + .../lib/user/presentation/sign_in_screen.dart | 4 +- .../lib/user/presentation/sign_up_screen.dart | 8 +- .../user/presentation/widgets/background.dart | 2 +- .../workspace/application/grid/prelude.dart | 3 + .../grid/setting/setting_bloc.dart | 47 ++++++ .../workspace/application/view/view_ext.dart | 2 +- .../home/menu/app/header/add_button.dart | 2 +- .../home/menu/app/header/header.dart | 4 +- .../menu/app/section/disclosure_action.dart | 2 +- .../home/menu/app/section/item.dart | 8 +- .../presentation/home/menu/menu.dart | 2 +- .../presentation/home/menu/menu_user.dart | 2 +- .../presentation/home/navigation.dart | 2 +- .../plugins/doc/src/widget/style_widgets.dart | 2 +- .../doc/src/widget/toolbar/link_button.dart | 4 +- .../widget/toolbar/toolbar_icon_button.dart | 2 +- .../plugins/grid/src/grid_page.dart | 2 + .../grid/src/widgets/content/grid_row.dart | 2 +- .../grid/src/widgets/footer/grid_footer.dart | 2 +- .../grid/src/widgets/header/field_list.dart | 13 +- .../widgets/header/field_operation_list.dart | 8 +- .../src/widgets/header/field_switcher.dart | 4 +- .../header/grid_field_action_sheet.dart | 14 +- .../src/widgets/header/grid_field_editor.dart | 6 +- .../grid/src/widgets/header/grid_header.dart | 2 +- .../src/widgets/header/grid_header_cell.dart | 17 +- .../grid/src/widgets/header/grid_setting.dart | 35 ---- .../src/widgets/header/type_option/date.dart | 8 +- .../type_option/edit_option_pannel.dart | 16 +- .../widgets/header/type_option/number.dart | 16 +- .../header/type_option/option_pannel.dart | 20 +-- .../src/widgets/toolbar/grid_property.dart | 19 +++ .../src/widgets/toolbar/grid_setting.dart | 152 ++++++++++++++++++ .../src/widgets/toolbar/grid_toolbar.dart | 44 +++++ .../presentation/plugins/trash/menu.dart | 2 +- .../plugins/trash/src/trash_cell.dart | 4 +- .../presentation/plugins/trash/trash.dart | 4 +- .../packages/flowy_infra/lib/image.dart | 4 +- .../lib/style_widget/button.dart | 3 + .../lib/style_widget/hover.dart | 9 +- .../lib/style_widget/icon_button.dart | 2 +- frontend/app_flowy/pubspec.yaml | 1 + 50 files changed, 384 insertions(+), 137 deletions(-) delete mode 100644 frontend/app_flowy/assets/images/editor/Icons 16/Yen.svg rename frontend/app_flowy/assets/images/{editor/Icons 16/Sort/Ascending.svg => grid/setting/ascending.svg} (100%) rename frontend/app_flowy/assets/images/{editor/Icons 16/Sort/Descending.svg => grid/setting/descending.svg} (100%) rename frontend/app_flowy/assets/images/{editor/Icons 16/Filter.svg => grid/setting/filter.svg} (100%) rename frontend/app_flowy/assets/images/{editor/Icons 16/Properties.svg => grid/setting/properties.svg} (100%) create mode 100644 frontend/app_flowy/assets/images/grid/setting/setting.svg create mode 100644 frontend/app_flowy/assets/images/grid/setting/sort.svg create mode 100644 frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart delete mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart diff --git a/frontend/app_flowy/assets/images/editor/Icons 16/Yen.svg b/frontend/app_flowy/assets/images/editor/Icons 16/Yen.svg deleted file mode 100644 index b7cf1d361d..0000000000 --- a/frontend/app_flowy/assets/images/editor/Icons 16/Yen.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/app_flowy/assets/images/editor/Icons 16/Sort/Ascending.svg b/frontend/app_flowy/assets/images/grid/setting/ascending.svg similarity index 100% rename from frontend/app_flowy/assets/images/editor/Icons 16/Sort/Ascending.svg rename to frontend/app_flowy/assets/images/grid/setting/ascending.svg diff --git a/frontend/app_flowy/assets/images/editor/Icons 16/Sort/Descending.svg b/frontend/app_flowy/assets/images/grid/setting/descending.svg similarity index 100% rename from frontend/app_flowy/assets/images/editor/Icons 16/Sort/Descending.svg rename to frontend/app_flowy/assets/images/grid/setting/descending.svg diff --git a/frontend/app_flowy/assets/images/editor/Icons 16/Filter.svg b/frontend/app_flowy/assets/images/grid/setting/filter.svg similarity index 100% rename from frontend/app_flowy/assets/images/editor/Icons 16/Filter.svg rename to frontend/app_flowy/assets/images/grid/setting/filter.svg diff --git a/frontend/app_flowy/assets/images/editor/Icons 16/Properties.svg b/frontend/app_flowy/assets/images/grid/setting/properties.svg similarity index 100% rename from frontend/app_flowy/assets/images/editor/Icons 16/Properties.svg rename to frontend/app_flowy/assets/images/grid/setting/properties.svg diff --git a/frontend/app_flowy/assets/images/grid/setting/setting.svg b/frontend/app_flowy/assets/images/grid/setting/setting.svg new file mode 100644 index 0000000000..3d632703ab --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/setting/setting.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/images/grid/setting/sort.svg b/frontend/app_flowy/assets/images/grid/setting/sort.svg new file mode 100644 index 0000000000..06e17d62a9 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/setting/sort.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index b9ab426fbd..9d73711cc7 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -143,6 +143,11 @@ } }, "grid": { + "settings": { + "filter": "Filter", + "sortBy": "Sort by", + "Properties": "Properties" + }, "field": { "hide": "Hide", "insertLeft": "Insert Left", diff --git a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart index 8124241cf4..9a02863345 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart @@ -170,8 +170,8 @@ class PasswordTextField extends StatelessWidget { return RoundedInputField( obscureText: true, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), - obscureIcon: svg("home/hide"), - obscureHideIcon: svg("home/show"), + obscureIcon: svgWidget("home/hide"), + obscureHideIcon: svgWidget("home/show"), hintText: LocaleKeys.signIn_passwordHint.tr(), normalBorderColor: theme.shader4, errorBorderColor: theme.red, diff --git a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart index 06d4db6da2..9f95a1db75 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart @@ -134,8 +134,8 @@ class PasswordTextField extends StatelessWidget { builder: (context, state) { return RoundedInputField( obscureText: true, - obscureIcon: svg("home/hide"), - obscureHideIcon: svg("home/show"), + obscureIcon: svgWidget("home/hide"), + obscureHideIcon: svgWidget("home/show"), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), hintText: LocaleKeys.signUp_passwordHint.tr(), normalBorderColor: theme.shader4, @@ -162,8 +162,8 @@ class RepeatPasswordTextField extends StatelessWidget { builder: (context, state) { return RoundedInputField( obscureText: true, - obscureIcon: svg("home/hide"), - obscureHideIcon: svg("home/show"), + obscureIcon: svgWidget("home/hide"), + obscureHideIcon: svgWidget("home/show"), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), hintText: LocaleKeys.signUp_repeatPasswordHint.tr(), normalBorderColor: theme.shader4, diff --git a/frontend/app_flowy/lib/user/presentation/widgets/background.dart b/frontend/app_flowy/lib/user/presentation/widgets/background.dart index 86dfab7ffe..225f7f0080 100644 --- a/frontend/app_flowy/lib/user/presentation/widgets/background.dart +++ b/frontend/app_flowy/lib/user/presentation/widgets/background.dart @@ -44,7 +44,7 @@ class FlowyLogoTitle extends StatelessWidget { children: [ SizedBox.fromSize( size: logoSize, - child: svg("flowy_logo"), + child: svgWidget("flowy_logo"), ), const VSpace(30), Text( diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 8b13a4f34d..6c766ee218 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -23,3 +23,6 @@ export 'cell_bloc/selection_cell_bloc.dart'; export 'cell_bloc/date_cell_bloc.dart'; export 'cell_bloc/checkbox_cell_bloc.dart'; export 'cell_bloc/cell_service.dart'; + +// Setting +export 'setting/setting_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart new file mode 100644 index 0000000000..38071155af --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart @@ -0,0 +1,47 @@ +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'setting_bloc.freezed.dart'; + +class GridSettingBloc extends Bloc { + final String gridId; + GridSettingBloc({required this.gridId}) : super(GridSettingState.initial()) { + on( + (event, emit) async { + event.map(performAction: (_PerformAction value) { + emit(state.copyWith(selectedAction: Some(value.action))); + }); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class GridSettingEvent with _$GridSettingEvent { + const factory GridSettingEvent.performAction(GridSettingAction action) = _PerformAction; +} + +@freezed +class GridSettingState with _$GridSettingState { + const factory GridSettingState({ + required Option selectedAction, + }) = _GridSettingState; + + factory GridSettingState.initial() => GridSettingState( + selectedAction: none(), + ); +} + +enum GridSettingAction { + filter, + sortBy, + properties, +} diff --git a/frontend/app_flowy/lib/workspace/application/view/view_ext.dart b/frontend/app_flowy/lib/workspace/application/view/view_ext.dart index cf80a820a0..78230e1311 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_ext.dart @@ -39,7 +39,7 @@ extension ViewExtension on View { thumbnail = "file_icon"; } - final Widget widget = svg(thumbnail, color: iconColor); + final Widget widget = svgWidget(thumbnail, color: iconColor); return widget; } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart index 9e696e8a73..6df78a67cc 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart @@ -28,7 +28,7 @@ class AddButton extends StatelessWidget { onSelected: onSelected, ).show(context); }, - icon: svg("home/add").padding(horizontal: 3, vertical: 3), + icon: svgWidget("home/add").padding(horizontal: 3, vertical: 3), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart index b773814f2d..ff1d6e6822 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart @@ -153,9 +153,9 @@ extension AppDisclosureExtension on AppDisclosureAction { Widget get icon { switch (this) { case AppDisclosureAction.rename: - return svg('editor/edit', color: const Color(0xffe5e5e5)); + return svgWidget('editor/edit', color: const Color(0xffe5e5e5)); case AppDisclosureAction.delete: - return svg('editor/delete', color: const Color(0xffe5e5e5)); + return svgWidget('editor/delete', color: const Color(0xffe5e5e5)); } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart index a706ae5019..c9a02a9de7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/disclosure_action.dart @@ -32,7 +32,7 @@ class ViewDisclosureButton extends StatelessWidget with ActionList _render(context, onHover, state, theme.iconColor), - isOnSelected: () => state.isEditing || isSelected, + setSelected: () => state.isEditing || isSelected, ), ); }, @@ -126,11 +126,11 @@ extension ViewDisclosureExtension on ViewDisclosureAction { Widget get icon { switch (this) { case ViewDisclosureAction.rename: - return svg('editor/edit', color: const Color(0xff999999)); + return svgWidget('editor/edit', color: const Color(0xff999999)); case ViewDisclosureAction.delete: - return svg('editor/delete', color: const Color(0xff999999)); + return svgWidget('editor/delete', color: const Color(0xff999999)); case ViewDisclosureAction.duplicate: - return svg('editor/copy', color: const Color(0xff999999)); + return svgWidget('editor/copy', color: const Color(0xff999999)); } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart index 73771596cb..395a85bf45 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart @@ -186,7 +186,7 @@ class MenuTopBar extends StatelessWidget { width: 28, onPressed: () => context.read().add(const MenuEvent.collapse()), iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), - icon: svg("home/hide_menu", color: theme.iconColor), + icon: svgWidget("home/hide_menu", color: theme.iconColor), ) ], ), diff --git a/frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart index fb0a4284d8..3a1674e486 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart @@ -80,7 +80,7 @@ class MenuUser extends StatelessWidget { }, icon: SizedBox.square( dimension: 20, - child: svg("home/settings", color: theme.iconColor), + child: svgWidget("home/settings", color: theme.iconColor), ), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart index 511b94db90..b6947c79fe 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -97,7 +97,7 @@ class FlowyNavigation extends StatelessWidget { notifier.value = false; }, iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), - icon: svg("home/hide_menu", color: theme.iconColor), + icon: svgWidget("home/hide_menu", color: theme.iconColor), ), ); } else { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart index 9d307b3ace..4f09b64053 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/style_widgets.dart @@ -51,7 +51,7 @@ class _FlowyEditorCheckboxState extends State { @override Widget build(BuildContext context) { - final icon = isChecked ? svg('editor/editor_check') : svg('editor/editor_uncheck'); + final icon = isChecked ? svgWidget('editor/editor_check') : svgWidget('editor/editor_uncheck'); return Align( alignment: Alignment.centerLeft, child: FlowyIconButton( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart index 3daa9f0679..60b654302f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/link_button.dart @@ -54,11 +54,11 @@ class _FlowyLinkStyleButtonState extends State { final isEnabled = !widget.controller.selection.isCollapsed; final pressedHandler = isEnabled ? () => _openLinkDialog(context) : null; final icon = isEnabled - ? svg( + ? svgWidget( 'editor/share', color: theme.iconColor, ) - : svg( + : svgWidget( 'editor/share', color: theme.disableIconColor, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart index 500f683355..b6dddefbb3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/widget/toolbar/toolbar_icon_button.dart @@ -29,7 +29,7 @@ class ToolbarIconButton extends StatelessWidget { iconPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), onPressed: onPressed, width: width, - icon: isToggled == true ? svg(iconName, color: Colors.white) : svg(iconName), + icon: isToggled == true ? svgWidget(iconName, color: Colors.white) : svgWidget(iconName), fillColor: isToggled == true ? theme.main1 : theme.shader6, hoverColor: isToggled == true ? theme.main1 : theme.shader5, tooltipText: tooltipText, 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 984ed147a1..1a8b5f4036 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 @@ -13,6 +13,7 @@ import 'layout/sizes.dart'; import 'widgets/content/grid_row.dart'; import 'widgets/footer/grid_footer.dart'; import 'widgets/header/grid_header.dart'; +import 'widgets/toolbar/grid_toolbar.dart'; class GridPage extends StatefulWidget { final View view; @@ -99,6 +100,7 @@ class _FlowyGridState extends State { physics: StyledScrollPhysics(), controller: _scrollController.verticalController, slivers: [ + SliverToBoxAdapter(child: GridToolbar(gridId: gridId)), _buildHeader(gridId), _buildRows(context), const GridFooter(), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index 23918401c4..53c27d62b4 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -110,7 +110,7 @@ class AppendRowButton extends StatelessWidget { width: 22, onPressed: () => context.read().add(const RowEvent.createRow()), iconPadding: const EdgeInsets.all(3), - icon: svg("home/add"), + icon: svgWidget("home/add"), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart index 7528c3c00a..8d9719ae75 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/footer/grid_footer.dart @@ -39,7 +39,7 @@ class _AddRowButton extends StatelessWidget { text: const FlowyText.medium('New row', fontSize: 12), hoverColor: theme.hover, onTap: () => context.read().add(const GridEvent.createRow()), - leftIcon: svg("home/add"), + leftIcon: svgWidget("home/add"), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart index 4511a84a1f..b83ad267f9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -13,14 +14,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; typedef SelectFieldCallback = void Function(FieldType); -class FieldTypeList extends StatelessWidget { +class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate { final SelectFieldCallback onSelectField; const FieldTypeList({required this.onSelectField, Key? key}) : super(key: key); - static void hide(BuildContext context) { - FlowyOverlay.of(context).remove(FieldTypeList.identifier()); - } - @override Widget build(BuildContext context) { final cells = FieldType.values.map((fieldType) { @@ -40,7 +37,7 @@ class FieldTypeList extends StatelessWidget { controller: ScrollController(), itemCount: cells.length, separatorBuilder: (context, index) { - return const VSpace(10); + return VSpace(GridSize.typeOptionSeparatorHeight); }, physics: StyledScrollPhysics(), itemBuilder: (BuildContext context, int index) { @@ -69,12 +66,12 @@ class FieldTypeCell extends StatelessWidget { final theme = context.watch(); return SizedBox( - height: 26, + height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(fieldType.title(), fontSize: 12), hoverColor: theme.hover, onTap: () => onSelectField(fieldType), - leftIcon: svg(fieldType.iconName(), color: theme.iconColor), + leftIcon: svgWidget(fieldType.iconName(), color: theme.iconColor), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart index 956060039d..789b4f98bd 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart @@ -9,7 +9,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class FieldOperationList extends StatelessWidget { - final List actions; + final List actions; const FieldOperationList({required this.actions, Key? key}) : super(key: key); @override @@ -27,12 +27,12 @@ class FieldOperationList extends StatelessWidget { } } -class FieldActionItem extends StatelessWidget { +class FieldActionCell extends StatelessWidget { final String fieldId; final VoidCallback onTap; final FieldAction action; - const FieldActionItem({ + const FieldActionCell({ required this.fieldId, required this.action, required this.onTap, @@ -49,7 +49,7 @@ class FieldActionItem extends StatelessWidget { action.run(context); onTap(); }, - leftIcon: svg(action.iconName(), color: theme.iconColor), + leftIcon: svgWidget(action.iconName(), color: theme.iconColor), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart index 5f11d750d8..7c52c29a7e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart @@ -83,8 +83,8 @@ class _FieldSwitcherState extends State { }); _showOverlay(context, list); }, - leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor), - rightIcon: svg("grid/more", color: theme.iconColor), + leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + rightIcon: svgWidget("grid/more", color: theme.iconColor), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart index 13f9fbaba5..79dd083fab 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart @@ -17,16 +17,16 @@ class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate { final VoidCallback onEdited; const GridFieldActionSheet({required this.fieldData, required this.onEdited, Key? key}) : super(key: key); - static void show(BuildContext overlayContext, GridFieldData fieldData, final VoidCallback onEdited) { - final editor = GridFieldActionSheet(fieldData: fieldData, onEdited: onEdited); + void show(BuildContext overlayContext) { FlowyOverlay.of(overlayContext).insertWithAnchor( widget: OverlayContainer( - child: editor, + child: this, constraints: BoxConstraints.loose(const Size(240, 200)), ), - identifier: editor.identifier(), + identifier: identifier(), anchorContext: overlayContext, anchorDirection: AnchorDirection.bottomWithLeftAligned, + delegate: this, ); } @@ -56,7 +56,9 @@ class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate { } @override - bool asBarrier() => true; + bool asBarrier() { + return true; + } } class _EditFieldButton extends StatelessWidget { @@ -90,7 +92,7 @@ class _FieldOperationList extends StatelessWidget { Widget build(BuildContext context) { final actions = FieldAction.values .map( - (action) => FieldActionItem( + (action) => FieldActionCell( fieldId: fieldData.field.id, action: action, onTap: onDismissed, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart index 085f051699..4f349b9347 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart @@ -25,7 +25,7 @@ class FieldEditor extends FlowyOverlayDelegate { void show(BuildContext context) { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: _EditFieldPannelWidget(_fieldEditorBloc), + child: _FieldEditorWidget(_fieldEditorBloc), constraints: BoxConstraints.loose(const Size(220, 400)), ), identifier: identifier(), @@ -49,9 +49,9 @@ class FieldEditor extends FlowyOverlayDelegate { bool asBarrier() => true; } -class _EditFieldPannelWidget extends StatelessWidget { +class _FieldEditorWidget extends StatelessWidget { final FieldEditorBloc editorBloc; - const _EditFieldPannelWidget(this.editorBloc, {Key? key}) : super(key: key); + const _FieldEditorWidget(this.editorBloc, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index 6125cf4526..faf17e8c13 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -121,7 +121,7 @@ class CreateFieldButton extends StatelessWidget { gridId: gridId, fieldContextLoader: NewFieldContextLoader(gridId: gridId), ).show(context), - leftIcon: svg("home/add"), + leftIcon: svgWidget("home/add"), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart index 4efedbfe6d..253f935bbd 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart @@ -19,13 +19,16 @@ class GridHeaderCell extends StatelessWidget { final theme = context.watch(); final button = FlowyButton( hoverColor: theme.hover, - onTap: () => GridFieldActionSheet.show(context, fieldData, () { - FieldEditor( - gridId: fieldData.gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldData), - ).show(context); - }), - rightIcon: svg("editor/details", color: theme.iconColor), + onTap: () => GridFieldActionSheet( + fieldData: fieldData, + onEdited: () { + FieldEditor( + gridId: fieldData.gridId, + fieldContextLoader: FieldContextLoaderAdaptor(fieldData), + ).show(context); + }, + ).show(context), + rightIcon: svgWidget("editor/details", color: theme.iconColor), text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart deleted file mode 100644 index dff1058c52..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_setting.dart +++ /dev/null @@ -1,35 +0,0 @@ -enum GridSetting { - filter, - sortBy, - properties, -} - -extension _GridSettingExtension on GridSetting { - String iconName() { - switch (this) { - case GridSetting.filter: - // TODO: Handle this case. - break; - case GridSetting.sortBy: - // TODO: Handle this case. - break; - case GridSetting.properties: - // TODO: Handle this case. - break; - } - } - - String title() { - switch (this) { - case GridSetting.filter: - // TODO: Handle this case. - break; - case GridSetting.sortBy: - // TODO: Handle this case. - break; - case GridSetting.properties: - // TODO: Handle this case. - break; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 5057d5caee..bae78c02f8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -75,7 +75,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { ); overlayDelegate.showOverlay(context, list); }, - rightIcon: svg("grid/more", color: theme.iconColor), + rightIcon: svgWidget("grid/more", color: theme.iconColor), ), ); } @@ -96,7 +96,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { }); overlayDelegate.showOverlay(context, list); }, - rightIcon: svg("grid/more", color: theme.iconColor), + rightIcon: svgWidget("grid/more", color: theme.iconColor), ), ); } @@ -156,7 +156,7 @@ class DateFormatItem extends StatelessWidget { final theme = context.watch(); Widget? checkmark; if (isSelected) { - checkmark = svg("grid/checkmark"); + checkmark = svgWidget("grid/checkmark"); } return SizedBox( @@ -246,7 +246,7 @@ class TimeFormatItem extends StatelessWidget { final theme = context.watch(); Widget? checkmark; if (isSelected) { - checkmark = svg("grid/checkmark"); + checkmark = svgWidget("grid/checkmark"); } return SizedBox( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index e7999b7e4c..4f133090de 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -79,7 +79,7 @@ class _DeleteTag extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr(), fontSize: 12), hoverColor: theme.hover, - leftIcon: svg("grid/delete", color: theme.iconColor), + leftIcon: svgWidget("grid/delete", color: theme.iconColor), onTap: () { context.read().add(const EditOptionEvent.delete()); }, @@ -110,8 +110,8 @@ class SelectOptionColorList extends StatelessWidget { @override Widget build(BuildContext context) { - final optionItems = SelectOptionColor.values.map((color) { - return _SelectOptionColorItem(color: color, isSelected: selectedColor == color); + final cells = SelectOptionColor.values.map((color) { + return _SelectOptionColorCell(color: color, isSelected: selectedColor == color); }).toList(); return Column( @@ -135,10 +135,10 @@ class SelectOptionColorList extends StatelessWidget { separatorBuilder: (context, index) { return VSpace(GridSize.typeOptionSeparatorHeight); }, - itemCount: optionItems.length, + itemCount: cells.length, physics: StyledScrollPhysics(), itemBuilder: (BuildContext context, int index) { - return optionItems[index]; + return cells[index]; }, ), ], @@ -146,17 +146,17 @@ class SelectOptionColorList extends StatelessWidget { } } -class _SelectOptionColorItem extends StatelessWidget { +class _SelectOptionColorCell extends StatelessWidget { final SelectOptionColor color; final bool isSelected; - const _SelectOptionColorItem({required this.color, required this.isSelected, Key? key}) : super(key: key); + const _SelectOptionColorCell({required this.color, required this.isSelected, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); Widget? checkmark; if (isSelected) { - checkmark = svg("grid/checkmark"); + checkmark = svgWidget("grid/checkmark"); } final colorIcon = SizedBox.square( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index bbff9dd5ad..a12b7e2be9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -59,7 +59,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { }); overlayDelegate.showOverlay(context, list); }, - rightIcon: svg("grid/more", color: theme.iconColor), + rightIcon: svgWidget("grid/more", color: theme.iconColor), ); }, ), @@ -76,8 +76,8 @@ class NumberFormatList extends StatelessWidget { @override Widget build(BuildContext context) { - final formatItems = NumberFormat.values.map((format) { - return NumberFormatItem( + final cells = NumberFormat.values.map((format) { + return NumberFormatCell( format: format, onSelected: (format) { onSelected(format); @@ -93,9 +93,9 @@ class NumberFormatList extends StatelessWidget { separatorBuilder: (context, index) { return VSpace(GridSize.typeOptionSeparatorHeight); }, - itemCount: formatItems.length, + itemCount: cells.length, itemBuilder: (BuildContext context, int index) { - return formatItems[index]; + return cells[index]; }, ), ); @@ -106,10 +106,10 @@ class NumberFormatList extends StatelessWidget { } } -class NumberFormatItem extends StatelessWidget { +class NumberFormatCell extends StatelessWidget { final NumberFormat format; final Function(NumberFormat format) onSelected; - const NumberFormatItem({required this.format, required this.onSelected, Key? key}) : super(key: key); + const NumberFormatCell({required this.format, required this.onSelected, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -120,7 +120,7 @@ class NumberFormatItem extends StatelessWidget { text: FlowyText.medium(format.title(), fontSize: 12), hoverColor: theme.hover, onTap: () => onSelected(format), - leftIcon: svg(format.iconName(), color: theme.iconColor), + leftIcon: svgWidget(format.iconName(), color: theme.iconColor), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart index b4039bbce1..7c93f63ee7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart @@ -132,8 +132,8 @@ class _OptionList extends StatelessWidget { return previous.options != current.options; }, builder: (context, state) { - final optionItems = state.options.map((option) { - return _makeOptionItem(context, option); + final cells = state.options.map((option) { + return _makeOptionCell(context, option); }).toList(); return ListView.separated( @@ -142,17 +142,17 @@ class _OptionList extends StatelessWidget { separatorBuilder: (context, index) { return VSpace(GridSize.typeOptionSeparatorHeight); }, - itemCount: optionItems.length, + itemCount: cells.length, itemBuilder: (BuildContext context, int index) { - return optionItems[index]; + return cells[index]; }, ); }, ); } - _OptionItem _makeOptionItem(BuildContext context, SelectOption option) { - return _OptionItem( + _OptionCell _makeOptionCell(BuildContext context, SelectOption option) { + return _OptionCell( option: option, onEdited: (option) { final pannel = EditSelectOptionPannel( @@ -173,10 +173,10 @@ class _OptionList extends StatelessWidget { } } -class _OptionItem extends StatelessWidget { +class _OptionCell extends StatelessWidget { final SelectOption option; final Function(SelectOption) onEdited; - const _OptionItem({ + const _OptionCell({ required this.option, required this.onEdited, Key? key, @@ -191,7 +191,7 @@ class _OptionItem extends StatelessWidget { text: FlowyText.medium(option.name, fontSize: 12), hoverColor: theme.hover, onTap: () => onEdited(option), - rightIcon: svg("grid/details", color: theme.iconColor), + rightIcon: svgWidget("grid/details", color: theme.iconColor), ), ); } @@ -211,7 +211,7 @@ class _AddOptionButton extends StatelessWidget { onTap: () { context.read().add(const OptionPannelEvent.beginAddingOption()); }, - leftIcon: svg("home/add", color: theme.iconColor), + leftIcon: svgWidget("home/add", color: theme.iconColor), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart new file mode 100644 index 0000000000..756b7cdf17 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class GridPropertyList extends StatelessWidget { + const GridPropertyList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} + +class _GridPropertyCell extends StatelessWidget { + const _GridPropertyCell({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart new file mode 100644 index 0000000000..784fd62bcf --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart @@ -0,0 +1,152 @@ +import 'package:app_flowy/workspace/application/grid/setting/setting_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; + +class GridSettingContext { + final String gridId; + GridSettingContext({ + required this.gridId, + }); +} + +class GridSettingList extends StatelessWidget with FlowyOverlayDelegate { + final GridSettingContext settingContext; + const GridSettingList({required this.settingContext, Key? key}) : super(key: key); + + void show(BuildContext context) { + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: this, + constraints: BoxConstraints.loose(const Size(140, 400)), + ), + identifier: identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomRight, + style: FlowyOverlayStyle(blur: false), + delegate: this, + ); + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => GridSettingBloc(gridId: settingContext.gridId), + child: BlocListener( + listenWhen: (previous, current) => previous.selectedAction != current.selectedAction, + listener: (context, state) { + state.selectedAction.foldLeft(null, (_, action) { + switch (action) { + case GridSettingAction.filter: + // TODO: Handle this case. + break; + case GridSettingAction.sortBy: + // TODO: Handle this case. + break; + case GridSettingAction.properties: + // TODO: Handle this case. + break; + } + }); + }, + child: BlocBuilder( + builder: (context, state) { + return _renderList(); + }, + ), + ), + ); + } + + String identifier() { + return toString(); + } + + Widget _renderList() { + final cells = GridSettingAction.values.map((action) { + return _SettingItem(action: action); + }).toList(); + + return SizedBox( + width: 140, + child: ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + itemCount: cells.length, + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ), + ); + } +} + +class _SettingItem extends StatelessWidget { + final GridSettingAction action; + + const _SettingItem({ + required this.action, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + final isSelected = context + .read() + .state + .selectedAction + .foldLeft(false, (_, selectedAction) => selectedAction == action); + + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + isSelected: isSelected, + text: FlowyText.medium(action.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + context.read().add(GridSettingEvent.performAction(action)); + }, + leftIcon: svgWidget(action.iconName(), color: theme.iconColor), + ), + ); + } +} + +extension _GridSettingExtension on GridSettingAction { + String iconName() { + switch (this) { + case GridSettingAction.filter: + return 'grid/setting/filter'; + case GridSettingAction.sortBy: + return 'grid/setting/sort'; + case GridSettingAction.properties: + return 'grid/setting/properties'; + } + } + + String title() { + switch (this) { + case GridSettingAction.filter: + return LocaleKeys.grid_settings_filter.tr(); + case GridSettingAction.sortBy: + return LocaleKeys.grid_settings_sortBy.tr(); + case GridSettingAction.properties: + return LocaleKeys.grid_settings_Properties.tr(); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart new file mode 100644 index 0000000000..dd586d9d2f --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart @@ -0,0 +1,44 @@ +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra_ui/style_widget/extension.dart'; +import 'package:flutter/material.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'grid_setting.dart'; + +class GridToolbar extends StatelessWidget { + final String gridId; + const GridToolbar({required this.gridId, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 40, + child: Row( + children: [ + SizedBox(width: GridSize.leadingHeaderPadding), + _SettingButton(settingContext: GridSettingContext(gridId: gridId)), + const Spacer(), + ], + ), + ); + } +} + +class _SettingButton extends StatelessWidget { + final GridSettingContext settingContext; + const _SettingButton({required this.settingContext, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyIconButton( + hoverColor: theme.hover, + width: 22, + onPressed: () => GridSettingList(settingContext: settingContext).show(context), + icon: svgWidget("grid/setting/setting").padding(horizontal: 3, vertical: 3), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart index ccd1c85188..770889c610 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/menu.dart @@ -36,7 +36,7 @@ class MenuTrash extends StatelessWidget { child: Selector( selector: (ctx, notifier) => notifier.theme, builder: (ctx, theme, child) => - SizedBox(width: 16, height: 16, child: svg("home/trash", color: theme.iconColor)), + SizedBox(width: 16, height: 16, child: svgWidget("home/trash", color: theme.iconColor)), ), ), const HSpace(6), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart index 4ba52edfe1..2c9679d97d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/src/trash_cell.dart @@ -29,13 +29,13 @@ class TrashCell extends StatelessWidget { FlowyIconButton( width: 16, onPressed: onRestore, - icon: svg("editor/restore", color: theme.iconColor), + icon: svgWidget("editor/restore", color: theme.iconColor), ), const HSpace(20), FlowyIconButton( width: 16, onPressed: onDelete, - icon: svg("editor/delete", color: theme.iconColor), + icon: svgWidget("editor/delete", color: theme.iconColor), ), ], ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart index 14b12d77bf..324b676fc3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/trash/trash.dart @@ -146,7 +146,7 @@ class _TrashPageState extends State { size: const Size(102, 30), child: FlowyButton( text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), fontSize: 12), - leftIcon: svg('editor/restore', color: theme.iconColor), + leftIcon: svgWidget('editor/restore', color: theme.iconColor), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.restoreAll()), ), @@ -156,7 +156,7 @@ class _TrashPageState extends State { size: const Size(102, 30), child: FlowyButton( text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), fontSize: 12), - leftIcon: svg('editor/delete', color: theme.iconColor), + leftIcon: svgWidget('editor/delete', color: theme.iconColor), hoverColor: theme.hover, onTap: () => context.read().add(const TrashEvent.deleteAll()), ), diff --git a/frontend/app_flowy/packages/flowy_infra/lib/image.dart b/frontend/app_flowy/packages/flowy_infra/lib/image.dart index 68bea3cd6d..e70c8b4bff 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/image.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/image.dart @@ -1,7 +1,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; -Widget svg(String name, {Color? color}) { +Widget svgWidget(String name, {Color? color}) { final Widget svg = SvgPicture.asset('assets/images/$name.svg', color: color); return svg; @@ -10,6 +10,6 @@ Widget svg(String name, {Color? color}) { Widget svgWithSize(String name, Size size) { return SizedBox.fromSize( size: size, - child: svg(name), + child: svgWidget(name), ); } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index 13d02a0ea8..69cddbf2fb 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -11,6 +11,7 @@ class FlowyButton extends StatelessWidget { final Widget? leftIcon; final Widget? rightIcon; final Color hoverColor; + final bool isSelected; const FlowyButton({ Key? key, required this.text, @@ -19,6 +20,7 @@ class FlowyButton extends StatelessWidget { this.leftIcon, this.rightIcon, this.hoverColor = Colors.transparent, + this.isSelected = false, }) : super(key: key); @override @@ -27,6 +29,7 @@ class FlowyButton extends StatelessWidget { onTap: onTap, child: FlowyHover( config: HoverDisplayConfig(borderRadius: Corners.s6Border, hoverColor: hoverColor), + setSelected: () => isSelected, builder: (context, onHover) => _render(), ), ); diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart index b19578fe54..48a702c2e4 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart @@ -3,18 +3,17 @@ import 'package:flutter/material.dart'; import 'package:flowy_infra/time/duration.dart'; typedef HoverBuilder = Widget Function(BuildContext context, bool onHover); -typedef IsOnSelected = bool Function(); class FlowyHover extends StatefulWidget { final HoverDisplayConfig config; final HoverBuilder builder; - final IsOnSelected? isOnSelected; + final bool Function()? setSelected; const FlowyHover({ Key? key, required this.builder, required this.config, - this.isOnSelected, + this.setSelected, }) : super(key: key); @override @@ -36,8 +35,8 @@ class _FlowyHoverState extends State { Widget render() { var showHover = _onHover; - if (!showHover && widget.isOnSelected != null) { - showHover = widget.isOnSelected!(); + if (!showHover && widget.setSelected != null) { + showHover = widget.setSelected!(); } if (showHover) { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart index 79e9c648ea..f3ecd23005 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart @@ -77,7 +77,7 @@ class FlowyDropdownButton extends StatelessWidget { return FlowyIconButton( width: 16, onPressed: onPressed, - icon: svg("home/drop_down_show"), + icon: svgWidget("home/drop_down_show"), ); } } diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index 2cc96e75d6..ad1f6cd0e2 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -113,6 +113,7 @@ flutter: - assets/images/editor/ - assets/images/grid/ - assets/images/grid/field/ + - assets/images/grid/setting/ - assets/translations/ # - images/a_dot_ham.jpeg From 6a94594a35db7a5fb81103a3ee86abc6b89f2fe3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 3 Apr 2022 17:05:28 +0800 Subject: [PATCH 32/47] chore: grid property list --- .../app_flowy/lib/startup/deps_resolver.dart | 12 +- ...field_bloc.dart => action_sheet_bloc.dart} | 30 +-- ...field_bloc.dart => field_editor_bloc.dart} | 2 +- .../application/grid/field/field_service.dart | 6 +- ..._type_bloc.dart => field_switch_bloc.dart} | 6 +- .../grid/field/grid_header_bloc.dart | 6 +- .../workspace/application/grid/prelude.dart | 7 +- .../grid/setting/property_bloc.dart | 51 +++++ .../plugins/grid/src/grid_page.dart | 27 ++- .../grid/src/widgets/content/grid_row.dart | 1 + .../grid/src/widgets/header/field_cell.dart | 55 +++++ .../header/field_cell_action_sheet.dart | 195 ++++++++++++++++++ ...id_field_editor.dart => field_editor.dart} | 12 +- .../widgets/header/field_operation_list.dart | 99 --------- .../src/widgets/header/field_switcher.dart | 11 +- .../widgets/header/field_type_extension.dart | 44 ++++ .../{field_list.dart => field_type_list.dart} | 43 +--- .../header/grid_field_action_sheet.dart | 105 ---------- .../grid/src/widgets/header/grid_header.dart | 8 +- .../src/widgets/header/grid_header_cell.dart | 45 ---- .../src/widgets/header/type_option/date.dart | 24 +-- .../src/widgets/toolbar/grid_property.dart | 114 +++++++++- .../src/widgets/toolbar/grid_setting.dart | 48 +++-- .../src/widgets/toolbar/grid_toolbar.dart | 29 ++- .../flowy-grid/src/services/grid_editor.rs | 2 +- 25 files changed, 600 insertions(+), 382 deletions(-) rename frontend/app_flowy/lib/workspace/application/grid/field/{grid_field_bloc.dart => action_sheet_bloc.dart} (66%) rename frontend/app_flowy/lib/workspace/application/grid/field/{edit_field_bloc.dart => field_editor_bloc.dart} (98%) rename frontend/app_flowy/lib/workspace/application/grid/field/{switch_field_type_bloc.dart => field_switch_bloc.dart} (90%) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart create mode 100755 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{grid_field_editor.dart => field_editor.dart} (89%) delete mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{field_list.dart => field_type_list.dart} (64%) delete mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart delete mode 100755 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 1bb46f913f..9020101083 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -165,8 +165,8 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (data, _) => GridFieldBloc( + getIt.registerFactoryParam( + (data, _) => FieldActionSheetBloc( field: data.field, service: FieldService(gridId: data.gridId), ), @@ -214,8 +214,8 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => FieldSwitchBloc(context), + getIt.registerFactoryParam( + (context, _) => FieldSwitcherBloc(context), ); getIt.registerFactoryParam( @@ -233,4 +233,8 @@ void _resolveGridDeps(GetIt getIt) { getIt.registerFactoryParam( (typeOption, _) => NumberTypeOptionBloc(typeOption: typeOption), ); + + getIt.registerFactoryParam>( + (gridId, fields) => GridPropertyBloc(gridId: gridId, fields: fields), + ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart similarity index 66% rename from frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart index f3ec3b4cbe..5e8cb5a932 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/action_sheet_bloc.dart @@ -5,14 +5,14 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'field_service.dart'; -part 'grid_field_bloc.freezed.dart'; +part 'action_sheet_bloc.freezed.dart'; -class GridFieldBloc extends Bloc { +class FieldActionSheetBloc extends Bloc { final FieldService service; - GridFieldBloc({required Field field, required this.service}) - : super(GridFieldState.initial(EditFieldContext.create()..gridField = field)) { - on( + FieldActionSheetBloc({required Field field, required this.service}) + : super(ActionSheetState.initial(EditFieldContext.create()..gridField = field)) { + on( (event, emit) async { await event.map( updateFieldName: (_UpdateFieldName value) async { @@ -56,23 +56,23 @@ class GridFieldBloc extends Bloc { } @freezed -class GridFieldEvent with _$GridFieldEvent { - const factory GridFieldEvent.updateFieldName(String name) = _UpdateFieldName; - const factory GridFieldEvent.hideField() = _HideField; - const factory GridFieldEvent.duplicateField() = _DuplicateField; - const factory GridFieldEvent.deleteField() = _DeleteField; - const factory GridFieldEvent.saveField() = _SaveField; +class ActionSheetEvent with _$ActionSheetEvent { + const factory ActionSheetEvent.updateFieldName(String name) = _UpdateFieldName; + const factory ActionSheetEvent.hideField() = _HideField; + const factory ActionSheetEvent.duplicateField() = _DuplicateField; + const factory ActionSheetEvent.deleteField() = _DeleteField; + const factory ActionSheetEvent.saveField() = _SaveField; } @freezed -class GridFieldState with _$GridFieldState { - const factory GridFieldState({ +class ActionSheetState with _$ActionSheetState { + const factory ActionSheetState({ required EditFieldContext editContext, required String errorText, required String fieldName, - }) = _GridFieldState; + }) = _ActionSheetState; - factory GridFieldState.initial(EditFieldContext editContext) => GridFieldState( + factory ActionSheetState.initial(EditFieldContext editContext) => ActionSheetState( editContext: editContext, errorText: '', fieldName: editContext.gridField.name, diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart similarity index 98% rename from frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart index 749cde3420..4556e17d38 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'field_service.dart'; import 'package:dartz/dartz.dart'; -part 'edit_field_bloc.freezed.dart'; +part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { final FieldService service; diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 5bb80a0119..d47dab99d0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -98,11 +98,11 @@ class FieldService { } } -class GridFieldData extends Equatable { +class GridFieldCellContext extends Equatable { final String gridId; final Field field; - const GridFieldData({ + const GridFieldCellContext({ required this.gridId, required this.field, }); @@ -132,7 +132,7 @@ class NewFieldContextLoader extends FieldContextLoader { } class FieldContextLoaderAdaptor extends FieldContextLoader { - final GridFieldData data; + final GridFieldCellContext data; FieldContextLoaderAdaptor(this.data); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart similarity index 90% rename from frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart index edb0732ddf..802b39d95a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/switch_field_type_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart @@ -7,10 +7,10 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'field_service.dart'; -part 'switch_field_type_bloc.freezed.dart'; +part 'field_switch_bloc.freezed.dart'; -class FieldSwitchBloc extends Bloc { - FieldSwitchBloc(SwitchFieldContext editContext) : super(FieldSwitchState.initial(editContext)) { +class FieldSwitcherBloc extends Bloc { + FieldSwitcherBloc(SwitchFieldContext editContext) : super(FieldSwitchState.initial(editContext)) { on( (event, emit) async { await event.map( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart index d249e9b4c1..ae10505bc7 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -27,6 +27,7 @@ class GridHeaderBloc extends Bloc { createField: (_CreateField value) {}, insertField: (_InsertField value) {}, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + value.fields.retainWhere((field) => field.visibility); emit(state.copyWith(fields: value.fields)); }, ); @@ -64,5 +65,8 @@ class GridHeaderEvent with _$GridHeaderEvent { class GridHeaderState with _$GridHeaderState { const factory GridHeaderState({required List fields}) = _GridHeaderState; - factory GridHeaderState.initial(List fields) => GridHeaderState(fields: fields); + factory GridHeaderState.initial(List fields) { + fields.retainWhere((field) => field.visibility); + return GridHeaderState(fields: fields); + } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 6c766ee218..f941b01056 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -7,9 +7,9 @@ export 'data.dart'; // Field export 'field/field_service.dart'; export 'field/grid_header_bloc.dart'; -export 'field/grid_field_bloc.dart'; -export 'field/edit_field_bloc.dart'; -export 'field/switch_field_type_bloc.dart'; +export 'field/action_sheet_bloc.dart'; +export 'field/field_editor_bloc.dart'; +export 'field/field_switch_bloc.dart'; // Field Type Option export 'field/type_option/date_bloc.dart'; @@ -26,3 +26,4 @@ export 'cell_bloc/cell_service.dart'; // Setting export 'setting/setting_bloc.dart'; +export 'setting/property_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart new file mode 100644 index 0000000000..a0dd50a633 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart @@ -0,0 +1,51 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'package:dartz/dartz.dart'; + +part 'property_bloc.freezed.dart'; + +class GridPropertyBloc extends Bloc { + final FieldService _service; + GridPropertyBloc({required String gridId, required List fields}) + : _service = FieldService(gridId: gridId), + super(GridPropertyState.initial(gridId, fields)) { + on( + (event, emit) async { + await event.map(setFieldVisibility: (_SetFieldVisibility value) async { + final result = await _service.updateField(fieldId: value.fieldId, visibility: value.visibility); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class GridPropertyEvent with _$GridPropertyEvent { + const factory GridPropertyEvent.setFieldVisibility(String fieldId, bool visibility) = _SetFieldVisibility; +} + +@freezed +class GridPropertyState with _$GridPropertyState { + const factory GridPropertyState({ + required String gridId, + required List fields, + }) = _GridPropertyState; + + factory GridPropertyState.initial(String gridId, List fields) => GridPropertyState( + gridId: gridId, + fields: fields, + ); +} 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 1a8b5f4036..c8c5cfd7b2 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 @@ -100,9 +100,9 @@ class _FlowyGridState extends State { physics: StyledScrollPhysics(), controller: _scrollController.verticalController, slivers: [ - SliverToBoxAdapter(child: GridToolbar(gridId: gridId)), - _buildHeader(gridId), - _buildRows(context), + _renderToolbar(gridId), + _renderHeader(gridId), + _renderRows(context), const GridFooter(), ], ), @@ -129,12 +129,27 @@ class _FlowyGridState extends State { ); } - Widget _buildHeader(String gridId) { + Widget _renderToolbar(String gridId) { + return BlocBuilder( + builder: (context, state) { + final toolbarContext = GridToolbarContext( + gridId: gridId, + fields: state.fields, + ); + + return SliverToBoxAdapter( + child: GridToolbar(toolbarContext: toolbarContext), + ); + }, + ); + } + + Widget _renderHeader(String gridId) { return BlocBuilder( buildWhen: (previous, current) => previous.fields.length != current.fields.length, builder: (context, state) { return SliverPersistentHeader( - delegate: GridHeaderDelegate(gridId: gridId, fields: state.fields), + delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), floating: true, pinned: true, ); @@ -142,7 +157,7 @@ class _FlowyGridState extends State { ); } - Widget _buildRows(BuildContext context) { + Widget _renderRows(BuildContext context) { return BlocBuilder( buildWhen: (previous, current) { final rowChanged = previous.rows.length != current.rows.length; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index 53c27d62b4..73594de957 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -124,6 +124,7 @@ class _RowCells extends StatelessWidget { buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap, builder: (context, state) { final children = state.fields + .where((field) => field.visibility) .map((field) => CellContainer( width: field.width.toDouble(), child: buildGridCell( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart new file mode 100755 index 0000000000..6a2051318e --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart @@ -0,0 +1,55 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'field_type_extension.dart'; + +import 'field_cell_action_sheet.dart'; +import 'field_editor.dart'; + +class GridFieldCell extends StatelessWidget { + final GridFieldCellContext fieldCellContext; + const GridFieldCell(this.fieldCellContext, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + final field = fieldCellContext.field; + + final button = FlowyButton( + hoverColor: theme.hover, + onTap: () => _showActionSheet(context), + rightIcon: svgWidget("editor/details", color: theme.iconColor), + leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + text: FlowyText.medium(field.name, fontSize: 12), + padding: GridSize.cellContentInsets, + ); + + final borderSide = BorderSide(color: theme.shader4, width: 0.4); + final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); + + return Container( + width: field.width.toDouble(), + decoration: decoration, + child: button, + ); + } + + void _showActionSheet(BuildContext context) { + GridFieldCellActionSheet( + fieldCellContext: fieldCellContext, + onEdited: () => _showFieldEditor(context), + ).show(context); + } + + void _showFieldEditor(BuildContext context) { + FieldEditor( + gridId: fieldCellContext.gridId, + fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + ).show(context); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart new file mode 100644 index 0000000000..6cf62bf397 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart @@ -0,0 +1,195 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; + +class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate { + final GridFieldCellContext fieldCellContext; + final VoidCallback onEdited; + const GridFieldCellActionSheet({required this.fieldCellContext, required this.onEdited, Key? key}) : super(key: key); + + void show(BuildContext overlayContext) { + FlowyOverlay.of(overlayContext).insertWithAnchor( + widget: OverlayContainer( + child: this, + constraints: BoxConstraints.loose(const Size(240, 200)), + ), + identifier: identifier(), + anchorContext: overlayContext, + anchorDirection: AnchorDirection.bottomWithLeftAligned, + delegate: this, + ); + } + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: fieldCellContext), + child: SingleChildScrollView( + child: Column( + children: [ + _EditFieldButton( + onEdited: () { + FlowyOverlay.of(context).remove(identifier()); + onEdited(); + }, + ), + const VSpace(6), + _FieldOperationList(fieldCellContext, () => FlowyOverlay.of(context).remove(identifier())), + ], + ), + ), + ); + } + + String identifier() { + return toString(); + } + + @override + bool asBarrier() { + return true; + } +} + +class _EditFieldButton extends StatelessWidget { + final Function() onEdited; + const _EditFieldButton({required this.onEdited, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocBuilder( + builder: (context, state) { + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), + hoverColor: theme.hover, + onTap: onEdited, + ), + ); + }, + ); + } +} + +class _FieldOperationList extends StatelessWidget { + final GridFieldCellContext fieldData; + final VoidCallback onDismissed; + const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final actions = FieldAction.values + .map( + (action) => FieldActionCell( + fieldId: fieldData.field.id, + action: action, + onTap: onDismissed, + ), + ) + .toList(); + + return FieldOperationList(actions: actions); + } +} + +class FieldOperationList extends StatelessWidget { + final List actions; + const FieldOperationList({required this.actions, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GridView( + // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html + shrinkWrap: true, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 4.0, + mainAxisSpacing: 8, + ), + children: actions, + ); + } +} + +class FieldActionCell extends StatelessWidget { + final String fieldId; + final VoidCallback onTap; + final FieldAction action; + + const FieldActionCell({ + required this.fieldId, + required this.action, + required this.onTap, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyButton( + text: FlowyText.medium(action.title(), fontSize: 12), + hoverColor: theme.hover, + onTap: () { + action.run(context); + onTap(); + }, + leftIcon: svgWidget(action.iconName(), color: theme.iconColor), + ); + } +} + +enum FieldAction { + hide, + duplicate, + delete, +} + +extension _FieldActionExtension on FieldAction { + String iconName() { + switch (this) { + case FieldAction.hide: + return 'grid/hide'; + case FieldAction.duplicate: + return 'grid/duplicate'; + case FieldAction.delete: + return 'grid/delete'; + } + } + + String title() { + switch (this) { + case FieldAction.hide: + return LocaleKeys.grid_field_hide.tr(); + case FieldAction.duplicate: + return LocaleKeys.grid_field_duplicate.tr(); + case FieldAction.delete: + return LocaleKeys.grid_field_delete.tr(); + } + } + + void run(BuildContext context) { + switch (this) { + case FieldAction.hide: + context.read().add(const ActionSheetEvent.hideField()); + break; + case FieldAction.duplicate: + context.read().add(const ActionSheetEvent.duplicateField()); + break; + case FieldAction.delete: + context.read().add(const ActionSheetEvent.deleteField()); + break; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart similarity index 89% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index 4f349b9347..d568829558 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/field/edit_field_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; -import 'package:app_flowy/workspace/application/grid/field/switch_field_type_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_switch_bloc.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -22,7 +22,11 @@ class FieldEditor extends FlowyOverlayDelegate { _fieldEditorBloc.add(const FieldEditorEvent.initial()); } - void show(BuildContext context) { + void show( + BuildContext context, { + AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned, + }) { + FlowyOverlay.of(context).remove(identifier()); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: _FieldEditorWidget(_fieldEditorBloc), @@ -30,7 +34,7 @@ class FieldEditor extends FlowyOverlayDelegate { ), identifier: identifier(), anchorContext: context, - anchorDirection: AnchorDirection.bottomWithLeftAligned, + anchorDirection: anchorDirection, style: FlowyOverlayStyle(blur: false), delegate: this, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart deleted file mode 100644 index 789b4f98bd..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_operation_list.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'package:app_flowy/workspace/application/grid/field/grid_field_bloc.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flutter/material.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -class FieldOperationList extends StatelessWidget { - final List actions; - const FieldOperationList({required this.actions, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return GridView( - // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html - shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 4.0, - mainAxisSpacing: 8, - ), - children: actions, - ); - } -} - -class FieldActionCell extends StatelessWidget { - final String fieldId; - final VoidCallback onTap; - final FieldAction action; - - const FieldActionCell({ - required this.fieldId, - required this.action, - required this.onTap, - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return FlowyButton( - text: FlowyText.medium(action.title(), fontSize: 12), - hoverColor: theme.hover, - onTap: () { - action.run(context); - onTap(); - }, - leftIcon: svgWidget(action.iconName(), color: theme.iconColor), - ); - } -} - -enum FieldAction { - hide, - duplicate, - delete, -} - -extension _FieldActionExtension on FieldAction { - String iconName() { - switch (this) { - case FieldAction.hide: - return 'grid/hide'; - case FieldAction.duplicate: - return 'grid/duplicate'; - case FieldAction.delete: - return 'grid/delete'; - } - } - - String title() { - switch (this) { - case FieldAction.hide: - return LocaleKeys.grid_field_hide.tr(); - case FieldAction.duplicate: - return LocaleKeys.grid_field_duplicate.tr(); - case FieldAction.delete: - return LocaleKeys.grid_field_delete.tr(); - } - } - - void run(BuildContext context) { - switch (this) { - case FieldAction.hide: - context.read().add(const GridFieldEvent.hideField()); - break; - case FieldAction.duplicate: - context.read().add(const GridFieldEvent.duplicateField()); - break; - case FieldAction.delete: - context.read().add(const GridFieldEvent.deleteField()); - break; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart index 7c52c29a7e..63816c7d74 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart @@ -15,7 +15,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; +import 'field_type_extension.dart'; import 'type_option/multi_select.dart'; import 'type_option/number.dart'; @@ -43,8 +44,8 @@ class _FieldSwitcherState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: widget.switchContext), - child: BlocConsumer( + create: (context) => getIt(param1: widget.switchContext), + child: BlocConsumer( listener: (context, state) { widget.onUpdated(state.field, state.typeOptionData); }, @@ -79,7 +80,7 @@ class _FieldSwitcherState extends State { hoverColor: theme.hover, onTap: () { final list = FieldTypeList(onSelectField: (fieldType) { - context.read().add(FieldSwitchEvent.toFieldType(fieldType)); + context.read().add(FieldSwitchEvent.toFieldType(fieldType)); }); _showOverlay(context, list); }, @@ -100,7 +101,7 @@ class _FieldSwitcherState extends State { ); final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { - context.read().add(FieldSwitchEvent.didUpdateTypeOptionData(data)); + context.read().add(FieldSwitchEvent.didUpdateTypeOptionData(data)); }); final builder = _makeTypeOptionBuild( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart new file mode 100644 index 0000000000..ce37afe861 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart @@ -0,0 +1,44 @@ + +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:easy_localization/easy_localization.dart'; + +extension FieldTypeListExtension on FieldType { + String iconName() { + switch (this) { + case FieldType.Checkbox: + return "grid/field/checkbox"; + case FieldType.DateTime: + return "grid/field/date"; + case FieldType.MultiSelect: + return "grid/field/multi_select"; + case FieldType.Number: + return "grid/field/number"; + case FieldType.RichText: + return "grid/field/text"; + case FieldType.SingleSelect: + return "grid/field/single_select"; + default: + throw UnimplementedError; + } + } + + String title() { + switch (this) { + case FieldType.Checkbox: + return LocaleKeys.grid_field_checkboxFieldName.tr(); + case FieldType.DateTime: + return LocaleKeys.grid_field_dateFieldName.tr(); + case FieldType.MultiSelect: + return LocaleKeys.grid_field_multiSelectFieldName.tr(); + case FieldType.Number: + return LocaleKeys.grid_field_numberFieldName.tr(); + case FieldType.RichText: + return LocaleKeys.grid_field_textFieldName.tr(); + case FieldType.SingleSelect: + return LocaleKeys.grid_field_singleSelectFieldName.tr(); + default: + throw UnimplementedError; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart similarity index 64% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index b83ad267f9..2965556f60 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -8,8 +8,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/material.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'package:easy_localization/easy_localization.dart'; +import 'field_type_extension.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; typedef SelectFieldCallback = void Function(FieldType); @@ -76,43 +75,3 @@ class FieldTypeCell extends StatelessWidget { ); } } - -extension FieldTypeListExtension on FieldType { - String iconName() { - switch (this) { - case FieldType.Checkbox: - return "grid/field/checkbox"; - case FieldType.DateTime: - return "grid/field/date"; - case FieldType.MultiSelect: - return "grid/field/multi_select"; - case FieldType.Number: - return "grid/field/number"; - case FieldType.RichText: - return "grid/field/text"; - case FieldType.SingleSelect: - return "grid/field/single_select"; - default: - throw UnimplementedError; - } - } - - String title() { - switch (this) { - case FieldType.Checkbox: - return LocaleKeys.grid_field_checkboxFieldName.tr(); - case FieldType.DateTime: - return LocaleKeys.grid_field_dateFieldName.tr(); - case FieldType.MultiSelect: - return LocaleKeys.grid_field_multiSelectFieldName.tr(); - case FieldType.Number: - return LocaleKeys.grid_field_numberFieldName.tr(); - case FieldType.RichText: - return LocaleKeys.grid_field_textFieldName.tr(); - case FieldType.SingleSelect: - return LocaleKeys.grid_field_singleSelectFieldName.tr(); - default: - throw UnimplementedError; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart deleted file mode 100644 index 79dd083fab..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_field_action_sheet.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'field_operation_list.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:app_flowy/generated/locale_keys.g.dart'; - -class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate { - final GridFieldData fieldData; - final VoidCallback onEdited; - const GridFieldActionSheet({required this.fieldData, required this.onEdited, Key? key}) : super(key: key); - - void show(BuildContext overlayContext) { - FlowyOverlay.of(overlayContext).insertWithAnchor( - widget: OverlayContainer( - child: this, - constraints: BoxConstraints.loose(const Size(240, 200)), - ), - identifier: identifier(), - anchorContext: overlayContext, - anchorDirection: AnchorDirection.bottomWithLeftAligned, - delegate: this, - ); - } - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: fieldData), - child: SingleChildScrollView( - child: Column( - children: [ - _EditFieldButton( - onEdited: () { - FlowyOverlay.of(context).remove(identifier()); - onEdited(); - }, - ), - const VSpace(6), - _FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())), - ], - ), - ), - ); - } - - String identifier() { - return toString(); - } - - @override - bool asBarrier() { - return true; - } -} - -class _EditFieldButton extends StatelessWidget { - final Function() onEdited; - const _EditFieldButton({required this.onEdited, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - return BlocBuilder( - builder: (context, state) { - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), - hoverColor: theme.hover, - onTap: onEdited, - ), - ); - }, - ); - } -} - -class _FieldOperationList extends StatelessWidget { - final GridFieldData fieldData; - final VoidCallback onDismissed; - const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final actions = FieldAction.values - .map( - (action) => FieldActionCell( - fieldId: fieldData.field.id, - action: action, - onTap: onDismissed, - ), - ) - .toList(); - - return FieldOperationList(actions: actions); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index faf17e8c13..be025501a0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -9,8 +9,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'grid_field_editor.dart'; -import 'grid_header_cell.dart'; +import 'field_editor.dart'; +import 'field_cell.dart'; class GridHeaderDelegate extends SliverPersistentHeaderDelegate { final String gridId; @@ -55,8 +55,8 @@ class GridHeader extends StatelessWidget { child: BlocBuilder( builder: (context, state) { final cells = state.fields.map( - (field) => GridHeaderCell( - GridFieldData(gridId: gridId, field: field), + (field) => GridFieldCell( + GridFieldCellContext(gridId: gridId, field: field), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart deleted file mode 100755 index 253f935bbd..0000000000 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header_cell.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -import 'grid_field_editor.dart'; -import 'grid_field_action_sheet.dart'; - -class GridHeaderCell extends StatelessWidget { - final GridFieldData fieldData; - const GridHeaderCell(this.fieldData, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - final button = FlowyButton( - hoverColor: theme.hover, - onTap: () => GridFieldActionSheet( - fieldData: fieldData, - onEdited: () { - FieldEditor( - gridId: fieldData.gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldData), - ).show(context); - }, - ).show(context), - rightIcon: svgWidget("editor/details", color: theme.iconColor), - text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)), - ); - - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); - - return Container( - width: fieldData.field.width.toDouble(), - decoration: decoration, - padding: GridSize.headerContentInsets, - child: button, - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index bae78c02f8..a31d371b09 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -109,8 +109,8 @@ class DateFormatList extends StatelessWidget { @override Widget build(BuildContext context) { - final formatItems = DateFormat.values.map((format) { - return DateFormatItem( + final cells = DateFormat.values.map((format) { + return DateFormatCell( dateFormat: format, onSelected: (format) { onSelected(format); @@ -127,9 +127,9 @@ class DateFormatList extends StatelessWidget { separatorBuilder: (context, index) { return VSpace(GridSize.typeOptionSeparatorHeight); }, - itemCount: formatItems.length, + itemCount: cells.length, itemBuilder: (BuildContext context, int index) { - return formatItems[index]; + return cells[index]; }, ), ); @@ -140,11 +140,11 @@ class DateFormatList extends StatelessWidget { } } -class DateFormatItem extends StatelessWidget { +class DateFormatCell extends StatelessWidget { final bool isSelected; final DateFormat dateFormat; final Function(DateFormat format) onSelected; - const DateFormatItem({ + const DateFormatCell({ required this.dateFormat, required this.onSelected, required this.isSelected, @@ -199,8 +199,8 @@ class TimeFormatList extends StatelessWidget { @override Widget build(BuildContext context) { - final formatItems = TimeFormat.values.map((format) { - return TimeFormatItem( + final cells = TimeFormat.values.map((format) { + return TimeFormatCell( isSelected: format == selectedFormat, timeFormat: format, onSelected: (format) { @@ -217,9 +217,9 @@ class TimeFormatList extends StatelessWidget { separatorBuilder: (context, index) { return VSpace(GridSize.typeOptionSeparatorHeight); }, - itemCount: formatItems.length, + itemCount: cells.length, itemBuilder: (BuildContext context, int index) { - return formatItems[index]; + return cells[index]; }, ), ); @@ -230,11 +230,11 @@ class TimeFormatList extends StatelessWidget { } } -class TimeFormatItem extends StatelessWidget { +class TimeFormatCell extends StatelessWidget { final TimeFormat timeFormat; final bool isSelected; final Function(TimeFormat format) onSelected; - const TimeFormatItem({ + const TimeFormatCell({ required this.timeFormat, required this.onSelected, required this.isSelected, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart index 756b7cdf17..b1c57a1530 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -1,19 +1,123 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/application/grid/setting/property_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_extension.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:styled_widget/styled_widget.dart'; -class GridPropertyList extends StatelessWidget { - const GridPropertyList({Key? key}) : super(key: key); +class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { + final String gridId; + final List fields; + const GridPropertyList({ + required this.gridId, + required this.fields, + Key? key, + }) : super(key: key); + + void show(BuildContext context) { + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: this, + constraints: BoxConstraints.loose(const Size(260, 400)), + ), + identifier: identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomRight, + style: FlowyOverlayStyle(blur: false), + delegate: this, + ); + } @override Widget build(BuildContext context) { - return Container(); + return BlocProvider( + create: (context) => getIt(param1: gridId, param2: fields), + child: BlocBuilder( + builder: (context, state) { + final cells = state.fields.map((field) { + return _GridPropertyCell(gridId: gridId, field: field); + }).toList(); + + return ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: cells.length, + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ); + }, + ), + ); } + + String identifier() { + return toString(); + } + + @override + bool asBarrier() => true; } class _GridPropertyCell extends StatelessWidget { - const _GridPropertyCell({Key? key}) : super(key: key); + final Field field; + final String gridId; + const _GridPropertyCell({required this.gridId, required this.field, Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return Container(); + final theme = context.watch(); + + final checkmark = field.visibility + ? svgWidget('home/show', color: theme.iconColor) + : svgWidget('home/hide', color: theme.iconColor); + + return Row( + children: [ + Expanded( + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(field.name, fontSize: 12), + hoverColor: theme.hover, + leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + onTap: () { + final fieldCellContext = GridFieldCellContext( + gridId: gridId, + field: field, + ); + + FieldEditor( + gridId: gridId, + fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + ).show(context, anchorDirection: AnchorDirection.bottomRight); + }, + ), + ), + ), + FlowyIconButton( + hoverColor: theme.hover, + width: GridSize.typeOptionItemHeight, + onPressed: () { + context.read().add(GridPropertyEvent.setFieldVisibility(field.id, !field.visibility)); + }, + icon: checkmark.padding(all: 6), + ) + ], + ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart index 784fd62bcf..e8a792025d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_setting.dart @@ -7,34 +7,57 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'grid_property.dart'; + class GridSettingContext { final String gridId; + final List fields; + GridSettingContext({ required this.gridId, + required this.fields, }); } -class GridSettingList extends StatelessWidget with FlowyOverlayDelegate { +class GridSettingList extends StatelessWidget { final GridSettingContext settingContext; - const GridSettingList({required this.settingContext, Key? key}) : super(key: key); + final Function(GridSettingAction, GridSettingContext) onAction; + const GridSettingList({required this.settingContext, required this.onAction, Key? key}) : super(key: key); + + static void show(BuildContext context, GridSettingContext settingContext) { + final list = GridSettingList( + settingContext: settingContext, + onAction: (action, settingContext) { + switch (action) { + case GridSettingAction.filter: + // TODO: Handle this case. + break; + case GridSettingAction.sortBy: + // TODO: Handle this case. + break; + case GridSettingAction.properties: + GridPropertyList(gridId: settingContext.gridId, fields: settingContext.fields).show(context); + break; + } + }, + ); - void show(BuildContext context) { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: this, + child: list, constraints: BoxConstraints.loose(const Size(140, 400)), ), - identifier: identifier(), + identifier: list.identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomRight, style: FlowyOverlayStyle(blur: false), - delegate: this, ); } @@ -46,17 +69,8 @@ class GridSettingList extends StatelessWidget with FlowyOverlayDelegate { listenWhen: (previous, current) => previous.selectedAction != current.selectedAction, listener: (context, state) { state.selectedAction.foldLeft(null, (_, action) { - switch (action) { - case GridSettingAction.filter: - // TODO: Handle this case. - break; - case GridSettingAction.sortBy: - // TODO: Handle this case. - break; - case GridSettingAction.properties: - // TODO: Handle this case. - break; - } + FlowyOverlay.of(context).remove(identifier()); + onAction(action, settingContext); }); }, child: BlocBuilder( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart index dd586d9d2f..9569f95225 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_toolbar.dart @@ -1,25 +1,40 @@ -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:flowy_infra_ui/style_widget/extension.dart'; -import 'package:flutter/material.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; + import 'grid_setting.dart'; -class GridToolbar extends StatelessWidget { +class GridToolbarContext { final String gridId; - const GridToolbar({required this.gridId, Key? key}) : super(key: key); + final List fields; + GridToolbarContext({ + required this.gridId, + required this.fields, + }); +} + +class GridToolbar extends StatelessWidget { + final GridToolbarContext toolbarContext; + const GridToolbar({required this.toolbarContext, Key? key}) : super(key: key); @override Widget build(BuildContext context) { + final settingContext = GridSettingContext( + gridId: toolbarContext.gridId, + fields: toolbarContext.fields, + ); return SizedBox( height: 40, child: Row( children: [ SizedBox(width: GridSize.leadingHeaderPadding), - _SettingButton(settingContext: GridSettingContext(gridId: gridId)), + _SettingButton(settingContext: settingContext), const Spacer(), ], ), @@ -37,7 +52,7 @@ class _SettingButton extends StatelessWidget { return FlowyIconButton( hoverColor: theme.hover, width: 22, - onPressed: () => GridSettingList(settingContext: settingContext).show(context), + onPressed: () => GridSettingList.show(context, settingContext), icon: svgWidget("grid/setting/setting").padding(horizontal: 3, vertical: 3), ); } 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 3925f80b24..95c23f489b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -295,7 +295,7 @@ impl ClientGridEditor { pub async fn get_field_metas(&self, field_orders: Option) -> FlowyResult> { let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?; - field_metas.retain(|field_meta| field_meta.visibility); + // field_metas.retain(|field_meta| field_meta.visibility); Ok(field_metas) } From aa9e3d065b74d2ebca69627bdfd9837977120bb6 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 3 Apr 2022 20:29:06 +0800 Subject: [PATCH 33/47] chore: show and hide property --- .../grid/setting/property_bloc.dart | 42 +++++++-- .../plugins/grid/src/grid_page.dart | 12 +-- .../grid/src/widgets/content/number_cell.dart | 2 +- .../grid/src/widgets/header/grid_header.dart | 87 ++++++++++++------- .../src/widgets/toolbar/grid_property.dart | 3 +- 5 files changed, 98 insertions(+), 48 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart index a0dd50a633..ab618b0fa9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/setting/property_bloc.dart @@ -1,40 +1,66 @@ import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'package:dartz/dartz.dart'; part 'property_bloc.freezed.dart'; class GridPropertyBloc extends Bloc { final FieldService _service; + final GridFieldsListener _fieldListener; + GridPropertyBloc({required String gridId, required List fields}) : _service = FieldService(gridId: gridId), + _fieldListener = GridFieldsListener(gridId: gridId), super(GridPropertyState.initial(gridId, fields)) { on( (event, emit) async { - await event.map(setFieldVisibility: (_SetFieldVisibility value) async { - final result = await _service.updateField(fieldId: value.fieldId, visibility: value.visibility); - result.fold( - (l) => null, - (err) => Log.error(err), - ); - }); + await event.map( + initial: (_Initial value) { + _startListening(); + }, + setFieldVisibility: (_SetFieldVisibility value) async { + final result = await _service.updateField(fieldId: value.fieldId, visibility: value.visibility); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(fields: value.fields)); + }, + ); }, ); } @override Future close() async { + await _fieldListener.stop(); return super.close(); } + + void _startListening() { + _fieldListener.updateFieldsNotifier.addPublishListener((result) { + result.fold( + (fields) { + add(GridPropertyEvent.didReceiveFieldUpdate(fields)); + }, + (err) => Log.error(err), + ); + }); + _fieldListener.start(); + } } @freezed class GridPropertyEvent with _$GridPropertyEvent { + const factory GridPropertyEvent.initial() = _Initial; const factory GridPropertyEvent.setFieldVisibility(String fieldId, bool visibility) = _SetFieldVisibility; + const factory GridPropertyEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; } @freezed 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 c8c5cfd7b2..83bce9c7ef 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 @@ -148,11 +148,13 @@ class _FlowyGridState extends State { return BlocBuilder( buildWhen: (previous, current) => previous.fields.length != current.fields.length, builder: (context, state) { - return SliverPersistentHeader( - delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), - floating: true, - pinned: true, - ); + return GridHeader(gridId: gridId, fields: List.from(state.fields)); + + // return SliverPersistentHeader( + // delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), + // floating: true, + // pinned: true, + // ); }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart index 6983cc1015..bc51829412 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart @@ -38,7 +38,7 @@ class _NumberCellState extends State { @override Future dispose() async { - await _cellBloc.close(); + _cellBloc.close(); super.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index be025501a0..80a7a51d59 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -12,15 +12,41 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_editor.dart'; import 'field_cell.dart'; -class GridHeaderDelegate extends SliverPersistentHeaderDelegate { +class GridHeader extends StatelessWidget { + final String gridId; + final List fields; + const GridHeader({Key? key, required this.gridId, required this.fields}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) { + final bloc = getIt(param1: gridId, param2: fields); + bloc.add(const GridHeaderEvent.initial()); + return bloc; + }, + child: BlocBuilder( + builder: (context, state) { + return SliverPersistentHeader( + delegate: _GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), + floating: true, + pinned: true, + ); + }, + ), + ); + } +} + +class _GridHeaderDelegate extends SliverPersistentHeaderDelegate { final String gridId; final List fields; - GridHeaderDelegate({required this.gridId, required this.fields}); + _GridHeaderDelegate({required this.gridId, required this.fields}); @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields)); + return _GridHeaderWidget(gridId: gridId, fields: fields, key: ObjectKey(fields)); } @override @@ -31,47 +57,42 @@ class GridHeaderDelegate extends SliverPersistentHeaderDelegate { @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { - if (oldDelegate is GridHeaderDelegate) { + if (oldDelegate is _GridHeaderDelegate) { return fields != oldDelegate.fields; } - return false; + return true; } } -class GridHeader extends StatelessWidget { - final List fields; +class _GridHeaderWidget extends StatelessWidget { final String gridId; - const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key); + final List fields; + + const _GridHeaderWidget({required this.gridId, required this.fields, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); - return BlocProvider( - create: (context) { - final bloc = getIt(param1: gridId, param2: fields); - bloc.add(const GridHeaderEvent.initial()); - return bloc; + return BlocBuilder( + builder: (context, state) { + final cells = state.fields.map( + (field) => GridFieldCell( + GridFieldCellContext(gridId: gridId, field: field), + ), + ); + + final row = Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const _HeaderLeading(), + ...cells, + _HeaderTrailing(gridId: gridId), + ], + key: UniqueKey(), + ); + + return Container(height: GridSize.headerHeight, color: theme.surface, child: row); }, - child: BlocBuilder( - builder: (context, state) { - final cells = state.fields.map( - (field) => GridFieldCell( - GridFieldCellContext(gridId: gridId, field: field), - ), - ); - - final row = Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const _HeaderLeading(), - ...cells, - _HeaderTrailing(gridId: gridId), - ], - ); - - return Container(color: theme.surface, child: row); - }, - ), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart index b1c57a1530..9951e6ba65 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -42,7 +42,8 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: gridId, param2: fields), + create: (context) => + getIt(param1: gridId, param2: fields)..add(const GridPropertyEvent.initial()), child: BlocBuilder( builder: (context, state) { final cells = state.fields.map((field) { From 5c3500e24cb65f986dd5782a6102aa7b86398b4e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 3 Apr 2022 22:22:54 +0800 Subject: [PATCH 34/47] chore: cell select option editor --- .../grid/cell_bloc/selection_editor_bloc.dart | 102 ++++++++++++++++++ .../grid/field/field_listener.dart | 51 +++++++++ .../application/grid/field/field_service.dart | 14 ++- .../plugins/grid/src/grid_page.dart | 19 +--- .../{content => cell}/cell_builder.dart | 2 +- .../{content => cell}/cell_container.dart | 0 .../{content => cell}/cell_decoration.dart | 0 .../{content => cell}/checkbox_cell.dart | 0 .../widgets/{content => cell}/date_cell.dart | 0 .../{content => cell}/number_cell.dart | 0 .../grid/src/widgets/cell/prelude.dart | 7 ++ .../cell/selection_cell/selection.dart | 77 +++++++++++++ .../selection_cell}/selection_cell.dart | 0 .../cell/selection_cell/selection_editor.dart | 45 ++++++++ .../widgets/{content => cell}/text_cell.dart | 0 .../grid/src/widgets/header/field_cell.dart | 5 +- .../type_option/edit_option_pannel.dart | 54 +--------- .../widgets/{content => row}/grid_row.dart | 3 +- .../src/widgets/toolbar/grid_property.dart | 7 +- .../flowy-grid/dart_notification.pbenum.dart | 6 +- .../flowy-grid/dart_notification.pbjson.dart | 5 +- .../flowy-grid/src/dart_notification.rs | 6 +- .../src/protobuf/model/dart_notification.rs | 17 +-- .../protobuf/proto/dart_notification.proto | 3 +- .../flowy-grid/src/services/grid_editor.rs | 31 +++++- .../src/entities/grid.rs | 12 +++ 26 files changed, 364 insertions(+), 102 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/cell_builder.dart (96%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/cell_container.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/cell_decoration.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/checkbox_cell.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/date_cell.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/number_cell.dart (100%) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell/selection_cell}/selection_cell.dart (100%) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => cell}/text_cell.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/{content => row}/grid_row.dart (97%) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart new file mode 100644 index 0000000000..7e617069c4 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -0,0 +1,102 @@ +import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'cell_service.dart'; + +part 'selection_editor_bloc.freezed.dart'; + +class SelectionEditorBloc extends Bloc { + final CellService service = CellService(); + final FieldListener _listener; + + SelectionEditorBloc({ + required String gridId, + required Field field, + }) : _listener = FieldListener(fieldId: field.id), + super(SelectionEditorState.initial(gridId, field)) { + on( + (event, emit) async { + await event.map( + initial: (_Initial value) async { + _startListening(); + _loadOptions(); + }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(field: value.field)); + _loadOptions(); + }, + didReceiveOptions: (_DidReceiveOptions value) { + emit(state.copyWith(options: value.options)); + }, + ); + }, + ); + } + + @override + Future close() async { + await _listener.stop(); + return super.close(); + } + + void _startListening() { + _listener.updateFieldNotifier.addPublishListener((result) { + result.fold( + (field) => add(SelectionEditorEvent.didReceiveFieldUpdate(field)), + (err) => Log.error(err), + ); + }); + } + + void _loadOptions() async { + final result = await FieldContextLoaderAdaptor(gridId: state.gridId, field: state.field).load(); + result.fold( + (context) { + List options = []; + switch (state.field.fieldType) { + case FieldType.MultiSelect: + options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + case FieldType.SingleSelect: + options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + default: + Log.error("Invalid field type, expect single select or multiple select"); + break; + } + add(SelectionEditorEvent.didReceiveOptions(options)); + }, + (err) => Log.error(err), + ); + } +} + +@freezed +class SelectionEditorEvent with _$SelectionEditorEvent { + const factory SelectionEditorEvent.initial() = _Initial; + const factory SelectionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; + const factory SelectionEditorEvent.didReceiveOptions(List options) = _DidReceiveOptions; +} + +@freezed +class SelectionEditorState with _$SelectionEditorState { + const factory SelectionEditorState({ + required String gridId, + required Field field, + required List options, + }) = _SelectionEditorState; + + factory SelectionEditorState.initial(String gridId, Field field) { + return SelectionEditorState( + gridId: gridId, + field: field, + options: [], + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart new file mode 100644 index 0000000000..eda5d83e69 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart @@ -0,0 +1,51 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +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/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'; + +typedef UpdateFieldNotifiedValue = Either; + +class FieldListener { + final String fieldId; + PublishNotifier updateFieldNotifier = PublishNotifier(); + StreamSubscription? _subscription; + GridNotificationParser? _parser; + + FieldListener({required this.fieldId}); + + void start() { + _parser = GridNotificationParser( + id: fieldId, + callback: (ty, result) { + _handleObservableType(ty, result); + }, + ); + + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); + } + + void _handleObservableType(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.DidUpdateField: + result.fold( + (payload) => updateFieldNotifier.value = left(Field.fromBuffer(payload)), + (error) => updateFieldNotifier.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + _parser = null; + await _subscription?.cancel(); + updateFieldNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index d47dab99d0..61ccad6b81 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -132,16 +132,20 @@ class NewFieldContextLoader extends FieldContextLoader { } class FieldContextLoaderAdaptor extends FieldContextLoader { - final GridFieldCellContext data; + final String gridId; + final Field field; - FieldContextLoaderAdaptor(this.data); + FieldContextLoaderAdaptor({ + required this.gridId, + required this.field, + }); @override Future> load() { final payload = GetEditFieldContextPayload.create() - ..gridId = data.gridId - ..fieldId = data.field.id - ..fieldType = data.field.fieldType; + ..gridId = gridId + ..fieldId = field.id + ..fieldType = field.fieldType; return GridEventGetEditFieldContext(payload).send(); } 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 83bce9c7ef..111235841f 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 @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import 'controller/grid_scroll.dart'; import 'layout/layout.dart'; import 'layout/sizes.dart'; -import 'widgets/content/grid_row.dart'; +import 'widgets/row/grid_row.dart'; import 'widgets/footer/grid_footer.dart'; import 'widgets/header/grid_header.dart'; import 'widgets/toolbar/grid_toolbar.dart'; @@ -101,7 +101,7 @@ class _FlowyGridState extends State { controller: _scrollController.verticalController, slivers: [ _renderToolbar(gridId), - _renderHeader(gridId), + GridHeader(gridId: gridId, fields: List.from(state.fields)), _renderRows(context), const GridFooter(), ], @@ -144,21 +144,6 @@ class _FlowyGridState extends State { ); } - Widget _renderHeader(String gridId) { - return BlocBuilder( - buildWhen: (previous, current) => previous.fields.length != current.fields.length, - builder: (context, state) { - return GridHeader(gridId: gridId, fields: List.from(state.fields)); - - // return SliverPersistentHeader( - // delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), - // floating: true, - // pinned: true, - // ); - }, - ); - } - Widget _renderRows(BuildContext context) { return BlocBuilder( buildWhen: (previous, current) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart similarity index 96% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 856338aea4..8a1b3a63ea 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; import 'date_cell.dart'; import 'number_cell.dart'; -import 'selection_cell.dart'; +import 'selection_cell/selection_cell.dart'; import 'text_cell.dart'; Widget buildGridCell(String rowId, Field field, FutureCellData cellData) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_decoration.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_decoration.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart new file mode 100644 index 0000000000..7fc3b3246f --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart @@ -0,0 +1,7 @@ +export 'cell_builder.dart'; +export 'cell_container.dart'; +export 'text_cell.dart'; +export 'number_cell.dart'; +export 'date_cell.dart'; +export 'checkbox_cell.dart'; +export 'selection_cell/selection_cell.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart new file mode 100644 index 0000000000..8f0f3dfc78 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart @@ -0,0 +1,77 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class SelectionBadge extends StatelessWidget { + final SelectOption option; + const SelectionBadge({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: option.color.make(context), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium(option.name, fontSize: 12), + ); + } +} + +extension SelectOptionColorExtension on SelectOptionColor { + Color make(BuildContext context) { + final theme = context.watch(); + switch (this) { + case SelectOptionColor.Purple: + return theme.tint1; + case SelectOptionColor.Pink: + return theme.tint2; + case SelectOptionColor.LightPink: + return theme.tint3; + case SelectOptionColor.Orange: + return theme.tint4; + case SelectOptionColor.Yellow: + return theme.tint5; + case SelectOptionColor.Lime: + return theme.tint6; + case SelectOptionColor.Green: + return theme.tint7; + case SelectOptionColor.Aqua: + return theme.tint8; + case SelectOptionColor.Blue: + return theme.tint9; + default: + throw ArgumentError; + } + } + + String optionName() { + switch (this) { + case SelectOptionColor.Purple: + return LocaleKeys.grid_selectOption_purpleColor.tr(); + case SelectOptionColor.Pink: + return LocaleKeys.grid_selectOption_pinkColor.tr(); + case SelectOptionColor.LightPink: + return LocaleKeys.grid_selectOption_lightPinkColor.tr(); + case SelectOptionColor.Orange: + return LocaleKeys.grid_selectOption_orangeColor.tr(); + case SelectOptionColor.Yellow: + return LocaleKeys.grid_selectOption_yellowColor.tr(); + case SelectOptionColor.Lime: + return LocaleKeys.grid_selectOption_limeColor.tr(); + case SelectOptionColor.Green: + return LocaleKeys.grid_selectOption_greenColor.tr(); + case SelectOptionColor.Aqua: + return LocaleKeys.grid_selectOption_aquaColor.tr(); + case SelectOptionColor.Blue: + return LocaleKeys.grid_selectOption_blueColor.tr(); + default: + throw ArgumentError; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart new file mode 100644 index 0000000000..de25430066 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -0,0 +1,45 @@ +import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'selection.dart'; + +class SelectionEditor extends StatelessWidget { + final GridCellData cellData; + const SelectionEditor({required this.cellData, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => SelectionEditorBloc(gridId: cellData.gridId, field: cellData.field), + child: BlocBuilder( + builder: (context, state) { + return Container(); + }, + ), + ); + } +} + +class _SelectionCell extends StatelessWidget { + final SelectOption option; + const _SelectionCell({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return InkWell( + onTap: () {}, + child: FlowyHover( + config: HoverDisplayConfig(hoverColor: theme.hover), + builder: (_, onHover) { + return SelectionBadge(option: option); + }, + ), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart index 6a2051318e..89cd0b60ff 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart @@ -49,7 +49,10 @@ class GridFieldCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: fieldCellContext.gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + fieldContextLoader: FieldContextLoaderAdaptor( + gridId: fieldCellContext.gridId, + field: fieldCellContext.field, + ), ).show(context); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index 4f133090de..a69575a409 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -183,56 +184,3 @@ class _SelectOptionColorCell extends StatelessWidget { ); } } - -extension SelectOptionColorExtension on SelectOptionColor { - Color color(BuildContext context) { - final theme = context.watch(); - switch (this) { - case SelectOptionColor.Purple: - return theme.tint1; - case SelectOptionColor.Pink: - return theme.tint2; - case SelectOptionColor.LightPink: - return theme.tint3; - case SelectOptionColor.Orange: - return theme.tint4; - case SelectOptionColor.Yellow: - return theme.tint5; - case SelectOptionColor.Lime: - return theme.tint6; - case SelectOptionColor.Green: - return theme.tint7; - case SelectOptionColor.Aqua: - return theme.tint8; - case SelectOptionColor.Blue: - return theme.tint9; - default: - throw ArgumentError; - } - } - - String optionName() { - switch (this) { - case SelectOptionColor.Purple: - return LocaleKeys.grid_selectOption_purpleColor.tr(); - case SelectOptionColor.Pink: - return LocaleKeys.grid_selectOption_pinkColor.tr(); - case SelectOptionColor.LightPink: - return LocaleKeys.grid_selectOption_lightPinkColor.tr(); - case SelectOptionColor.Orange: - return LocaleKeys.grid_selectOption_orangeColor.tr(); - case SelectOptionColor.Yellow: - return LocaleKeys.grid_selectOption_yellowColor.tr(); - case SelectOptionColor.Lime: - return LocaleKeys.grid_selectOption_limeColor.tr(); - case SelectOptionColor.Green: - return LocaleKeys.grid_selectOption_greenColor.tr(); - case SelectOptionColor.Aqua: - return LocaleKeys.grid_selectOption_aquaColor.tr(); - case SelectOptionColor.Blue: - return LocaleKeys.grid_selectOption_blueColor.tr(); - default: - throw ArgumentError; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart similarity index 97% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index 73594de957..c4c32bda3b 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -1,14 +1,13 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; -import 'cell_builder.dart'; -import 'cell_container.dart'; class GridRowWidget extends StatefulWidget { final GridRowData data; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart index 9951e6ba65..a34682d204 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -97,14 +97,9 @@ class _GridPropertyCell extends StatelessWidget { hoverColor: theme.hover, leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), onTap: () { - final fieldCellContext = GridFieldCellContext( - gridId: gridId, - field: field, - ); - FieldEditor( gridId: gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + fieldContextLoader: FieldContextLoaderAdaptor(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ), 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 index c000793a5e..634de1b7f2 100644 --- 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 @@ -11,17 +11,19 @@ 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 GridDidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateBlock'); + static const GridNotification DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock'); static const GridNotification DidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); + static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField'); static const $core.List values = [ Unknown, - GridDidCreateBlock, + DidCreateBlock, DidUpdateRow, GridDidUpdateCells, DidUpdateFields, + DidUpdateField, ]; static final $core.Map<$core.int, GridNotification> _byValue = $pb.ProtobufEnum.initByValue(values); 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 index 5dc1fbc1a5..571fe64399 100644 --- 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 @@ -13,12 +13,13 @@ const GridNotification$json = const { '1': 'GridNotification', '2': const [ const {'1': 'Unknown', '2': 0}, - const {'1': 'GridDidCreateBlock', '2': 11}, + const {'1': 'DidCreateBlock', '2': 11}, const {'1': 'DidUpdateRow', '2': 20}, const {'1': 'GridDidUpdateCells', '2': 30}, const {'1': 'DidUpdateFields', '2': 40}, + const {'1': 'DidUpdateField', '2': 41}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIQCgxEaWRVcGRhdGVSb3cQFBIWChJHcmlkRGlkVXBkYXRlQ2VsbHMQHhITCg9EaWRVcGRhdGVGaWVsZHMQKA=='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhAKDERpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk='); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 34c972a9bb..364c42f680 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -5,13 +5,11 @@ const OBSERVABLE_CATEGORY: &str = "Grid"; #[derive(ProtoBuf_Enum, Debug)] pub enum GridNotification { Unknown = 0, - - GridDidCreateBlock = 11, - + DidCreateBlock = 11, DidUpdateRow = 20, - GridDidUpdateCells = 30, DidUpdateFields = 40, + DidUpdateField = 41, } impl std::default::Default for GridNotification { 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 index 0dd067b3d5..32e697b36e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -26,10 +26,11 @@ #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum GridNotification { Unknown = 0, - GridDidCreateBlock = 11, + DidCreateBlock = 11, DidUpdateRow = 20, GridDidUpdateCells = 30, DidUpdateFields = 40, + DidUpdateField = 41, } impl ::protobuf::ProtobufEnum for GridNotification { @@ -40,10 +41,11 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), - 11 => ::std::option::Option::Some(GridNotification::GridDidCreateBlock), + 11 => ::std::option::Option::Some(GridNotification::DidCreateBlock), 20 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), + 41 => ::std::option::Option::Some(GridNotification::DidUpdateField), _ => ::std::option::Option::None } } @@ -51,10 +53,11 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn values() -> &'static [Self] { static values: &'static [GridNotification] = &[ GridNotification::Unknown, - GridNotification::GridDidCreateBlock, + GridNotification::DidCreateBlock, GridNotification::DidUpdateRow, GridNotification::GridDidUpdateCells, GridNotification::DidUpdateFields, + GridNotification::DidUpdateField, ]; values } @@ -83,10 +86,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*v\n\x10GridNotification\x12\x0b\n\x07Unkno\ - wn\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUpdateR\ - ow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDidUpdat\ - eFields\x10(b\x06proto3\ + \n\x17dart_notification.proto*\x86\x01\n\x10GridNotification\x12\x0b\n\ + \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUp\ + dateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDid\ + UpdateFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 index da1d193b21..176e0d83a4 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -2,8 +2,9 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; - GridDidCreateBlock = 11; + DidCreateBlock = 11; DidUpdateRow = 20; GridDidUpdateCells = 30; DidUpdateFields = 40; + DidUpdateField = 41; } 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 95c23f489b..443c1ee2bf 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -97,6 +97,7 @@ impl ClientGridEditor { } pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { + let field_id = params.field_id.clone(); let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { None => return Err(ErrorCode::FieldDoesNotExist.into()), Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), @@ -104,6 +105,7 @@ impl ClientGridEditor { let _ = self.modify(|grid| Ok(grid.update_field(params, deserializer)?)).await?; let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_field(&field_id).await?; Ok(()) } @@ -133,6 +135,7 @@ impl ClientGridEditor { .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) .await?; let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_field(field_id).await?; Ok(()) } @@ -294,7 +297,19 @@ impl ClientGridEditor { } pub async fn get_field_metas(&self, field_orders: Option) -> FlowyResult> { - let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?; + let expected_len = match field_orders.as_ref() { + None => 0, + Some(field_orders) => field_orders.len(), + }; + + let field_metas = self.pad.read().await.get_field_metas(field_orders)?; + debug_assert!(field_metas.len() == expected_len); + if field_metas.len() != expected_len { + tracing::error!( + "This is a bug. The len of the field_metas should equal to {}", + expected_len + ); + } // field_metas.retain(|field_meta| field_meta.visibility); Ok(field_metas) } @@ -368,6 +383,20 @@ impl ClientGridEditor { .send(); Ok(()) } + + async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> { + let field_orders: RepeatedFieldOrder = vec![FieldOrder::from(field_id)].into(); + let mut field_metas = self.get_field_metas(Some(field_orders)).await?; + debug_assert!(field_metas.len() == 1); + + if let Some(field_meta) = field_metas.pop() { + send_dart_notification(&self.grid_id, GridNotification::DidUpdateField) + .payload(field_meta) + .send(); + } + + Ok(()) + } } #[cfg(feature = "flowy_unit_test")] 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 b60aafedae..1dd2220f13 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -100,6 +100,12 @@ impl std::convert::From<&FieldMeta> for FieldOrder { } } +impl std::convert::From<&str> for FieldOrder { + fn from(s: &str) -> Self { + FieldOrder { field_id: s.to_owned() } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct GetEditFieldContextPayload { #[pb(index = 1)] @@ -193,6 +199,12 @@ impl std::ops::Deref for RepeatedFieldOrder { } } +impl std::convert::From> for RepeatedFieldOrder { + fn from(field_orders: Vec) -> Self { + RepeatedFieldOrder { items: field_orders } + } +} + #[derive(Debug, Default, Clone, ProtoBuf)] pub struct RowOrder { #[pb(index = 1)] From 1abf0b565f2191416bbf16199f100f350145c97e Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 4 Apr 2022 11:10:41 +0800 Subject: [PATCH 35/47] chore: cell highlight --- .../app_flowy/assets/translations/en.json | 3 +- .../grid/src/widgets/cell/cell_container.dart | 95 +++++++++++---- .../{selection.dart => extension.dart} | 112 +++++++++++++++--- .../cell/selection_cell/selection_cell.dart | 14 ++- .../cell/selection_cell/selection_editor.dart | 94 ++++++++++++++- .../grid/src/widgets/cell/text_cell.dart | 46 +++---- .../grid/src/widgets/header/grid_header.dart | 37 +++--- .../type_option/edit_option_pannel.dart | 4 +- frontend/app_flowy/pubspec.lock | 7 ++ frontend/app_flowy/pubspec.yaml | 2 +- .../flowy-grid/src/services/grid_editor.rs | 4 +- 11 files changed, 321 insertions(+), 97 deletions(-) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/{selection.dart => extension.dart} (52%) diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 9d73711cc7..55e57dfdc7 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -185,7 +185,8 @@ "aquaColor": "Aqua", "blueColor": "Blue", "deleteTag": "Delete tag", - "colorPannelTitle": "Colors" + "colorPannelTitle": "Colors", + "pannelTitle": "Select an option" } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart index 0bfcc10caa..8890dc7576 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart @@ -1,9 +1,23 @@ -import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; -class CellContainer extends StatefulWidget { +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; + +class CellStateNotifier extends ChangeNotifier { + bool _isFocus = false; + + set isFocus(bool value) { + if (_isFocus != value) { + _isFocus = value; + notifyListeners(); + } + } + + bool get isFocus => _isFocus; +} + +class CellContainer extends StatelessWidget { final Widget child; final double width; const CellContainer({ @@ -12,28 +26,65 @@ class CellContainer extends StatefulWidget { required this.width, }) : super(key: key); - @override - State createState() => _CellContainerState(); -} - -class _CellContainerState extends State { @override Widget build(BuildContext context) { - final theme = context.watch(); - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - return GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () {}, - child: Container( - constraints: BoxConstraints( - maxWidth: widget.width, - ), - decoration: BoxDecoration( - border: Border(right: borderSide, bottom: borderSide), - ), - padding: GridSize.cellContentInsets, - child: Center(child: IntrinsicHeight(child: widget.child)), + return ChangeNotifierProvider( + create: (_) => CellStateNotifier(), + child: Consumer( + builder: (context, state, _) { + return Container( + constraints: BoxConstraints( + maxWidth: width, + ), + decoration: _makeBoxDecoration(context, state), + padding: GridSize.cellContentInsets, + child: Center(child: IntrinsicHeight(child: child)), + ); + }, ), ); } + + BoxDecoration _makeBoxDecoration(BuildContext context, CellStateNotifier state) { + final theme = context.watch(); + if (state.isFocus) { + final borderSide = BorderSide(color: theme.main1, width: 1.0); + return BoxDecoration(border: Border.fromBorderSide(borderSide)); + } else { + final borderSide = BorderSide(color: theme.shader4, width: 0.4); + return BoxDecoration(border: Border(right: borderSide, bottom: borderSide)); + } + } +} + +abstract class GridCell extends StatefulWidget { + const GridCell({Key? key}) : super(key: key); + + void setFocus(BuildContext context, bool value) { + Provider.of(context, listen: false).isFocus = value; + } +} + +class CellFocusNode extends FocusNode { + VoidCallback? focusCallback; + + void addCallback(BuildContext context, VoidCallback callback) { + if (focusCallback != null) { + removeListener(focusCallback!); + } + focusCallback = () { + Provider.of(context, listen: false).isFocus = hasFocus; + callback(); + }; + + addListener(focusCallback!); + } + + @override + void dispose() { + if (focusCallback != null) { + removeListener(focusCallback!); + } + super.dispose(); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart similarity index 52% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index 8f0f3dfc78..7bf977d6a4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -5,23 +5,7 @@ import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - -class SelectionBadge extends StatelessWidget { - final SelectOption option; - const SelectionBadge({required this.option, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: option.color.make(context), - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(6.0), - ), - child: FlowyText.medium(option.name, fontSize: 12), - ); - } -} +import 'package:textfield_tags/textfield_tags.dart'; extension SelectOptionColorExtension on SelectOptionColor { Color make(BuildContext context) { @@ -75,3 +59,97 @@ extension SelectOptionColorExtension on SelectOptionColor { } } } + +class SelectOptionTextField extends StatelessWidget { + final TextEditingController _controller; + final FocusNode _focusNode; + + SelectOptionTextField({ + TextEditingController? controller, + FocusNode? focusNode, + Key? key, + }) : _controller = controller ?? TextEditingController(), + _focusNode = focusNode ?? FocusNode(), + super(key: key); + + @override + Widget build(BuildContext context) { + return TextFieldTags( + textEditingController: _controller, + initialTags: ["abc", "bdf"], + focusNode: _focusNode, + textSeparators: const [' ', ','], + inputfieldBuilder: ( + BuildContext context, + TextEditingController editController, + FocusNode focusNode, + String? error, + void Function(String)? onChanged, + void Function(String)? onSubmitted, + ) { + return ((context, sc, tags, onTagDelegate) { + return TextField( + controller: editController, + focusNode: focusNode, + onChanged: (value) {}, + onEditingComplete: () => focusNode.unfocus(), + maxLines: 1, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + isDense: true, + prefixIcon: _renderTags(tags, sc), + ), + ); + }); + }, + ); + } + + Widget? _renderTags(List tags, ScrollController sc) { + if (tags.isEmpty) { + return null; + } + + return SingleChildScrollView( + controller: sc, + scrollDirection: Axis.horizontal, + child: Row(children: [ + Container( + decoration: BoxDecoration( + color: Color.fromARGB(255, 74, 137, 92), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium("efc", fontSize: 12), + ), + Container( + decoration: BoxDecoration( + color: Color.fromARGB(255, 74, 137, 92), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium("abc", fontSize: 12), + ) + ]), + ); + } +} + +class SelectionBadge extends StatelessWidget { + final SelectOption option; + const SelectionBadge({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: option.color.make(context), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium(option.name, fontSize: 12), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 0b1b1828f3..8e7c59b02c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -1,7 +1,10 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart'; import 'package:flutter/material.dart'; +import 'extension.dart'; + class SingleSelectCell extends StatefulWidget { final FutureCellData cellData; @@ -15,22 +18,31 @@ class SingleSelectCell extends StatefulWidget { } class _SingleSelectCellState extends State { + late CellFocusNode _focusNode; late SelectionCellBloc _cellBloc; + late TextEditingController _controller; @override void initState() { _cellBloc = getIt(param1: widget.cellData); + _controller = TextEditingController(); + _focusNode = CellFocusNode(); super.initState(); } @override Widget build(BuildContext context) { - return Container(); + _focusNode.addCallback(context, () {}); + return SelectOptionTextField( + focusNode: _focusNode, + controller: _controller, + ); } @override Future dispose() async { _cellBloc.close(); + _focusNode.dispose(); super.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index de25430066..98e1774425 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -1,37 +1,108 @@ import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'selection.dart'; +import 'extension.dart'; class SelectionEditor extends StatelessWidget { final GridCellData cellData; const SelectionEditor({required this.cellData, Key? key}) : super(key: key); + void show(BuildContext context) { + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: this, + constraints: BoxConstraints.loose(const Size(240, 200)), + ), + identifier: toString(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomWithLeftAligned, + ); + } + @override Widget build(BuildContext context) { return BlocProvider( create: (context) => SelectionEditorBloc(gridId: cellData.gridId, field: cellData.field), child: BlocBuilder( builder: (context, state) { - return Container(); + return Column( + children: const [ + _Title(), + VSpace(10), + _OptionList(), + ], + ); }, ), ); } } +class _OptionList extends StatelessWidget { + const _OptionList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + final cells = state.options.map((option) => _SelectionCell(option)).toList(); + final list = ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + itemCount: cells.length, + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ); + return list; + }, + ); + } +} + +class _Title extends StatelessWidget { + const _Title({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyText.medium(LocaleKeys.grid_selectOption_pannelTitle.tr(), fontSize: 12), + ); + } +} + class _SelectionCell extends StatelessWidget { final SelectOption option; - const _SelectionCell({required this.option, Key? key}) : super(key: key); + const _SelectionCell(this.option, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); + + // return FlowyButton( + // text: FlowyText.medium(fieldType.title(), fontSize: 12), + // hoverColor: theme.hover, + // onTap: () => onSelectField(fieldType), + // leftIcon: svgWidget(fieldType.iconName(), color: theme.iconColor), + // ); + return InkWell( onTap: () {}, child: FlowyHover( @@ -43,3 +114,20 @@ class _SelectionCell extends StatelessWidget { ); } } + +class SelectionBadge extends StatelessWidget { + final SelectOption option; + const SelectionBadge({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: option.color.make(context), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium(option.name, fontSize: 12), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index e8c571bded..c4e272aeb4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -1,13 +1,11 @@ import 'dart:async'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'cell_container.dart'; -/// The interface of base cell. - -class GridTextCell extends StatefulWidget { +class GridTextCell extends GridCell { final FutureCellData cellData; const GridTextCell({ required this.cellData, @@ -19,21 +17,23 @@ class GridTextCell extends StatefulWidget { } class _GridTextCellState extends State { - late TextEditingController _controller; - Timer? _delayOperation; - final _focusNode = FocusNode(); late TextCellBloc _cellBloc; + late TextEditingController _controller; + late CellFocusNode _focusNode; + Timer? _delayOperation; @override void initState() { _cellBloc = getIt(param1: widget.cellData); _controller = TextEditingController(text: _cellBloc.state.content); - _focusNode.addListener(save); + _focusNode = CellFocusNode(); super.initState(); } @override Widget build(BuildContext context) { + _focusNode.addCallback(context, focusChanged); + return BlocProvider.value( value: _cellBloc, child: BlocConsumer( @@ -46,16 +46,8 @@ class _GridTextCellState extends State { return TextField( controller: _controller, focusNode: _focusNode, - onChanged: (value) { - Log.info("On change"); - save(); - }, - onEditingComplete: () { - Log.info("On complete"); - }, - onSubmitted: (value) { - Log.info("On submit"); - }, + onChanged: (value) => focusChanged(), + onEditingComplete: () => _focusNode.unfocus(), maxLines: 1, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), decoration: const InputDecoration( @@ -72,18 +64,18 @@ class _GridTextCellState extends State { @override Future dispose() async { _cellBloc.close(); - _focusNode.removeListener(save); _focusNode.dispose(); super.dispose(); } - Future save() async { - _delayOperation?.cancel(); - _delayOperation = Timer(const Duration(milliseconds: 300), () { - if (_cellBloc.isClosed == false) { - _cellBloc.add(TextCellEvent.updateText(_controller.text)); - } - }); - // and later, before the timer goes off... + Future focusChanged() async { + if (mounted) { + _delayOperation?.cancel(); + _delayOperation = Timer(const Duration(milliseconds: 300), () { + if (_cellBloc.isClosed == false) { + _cellBloc.add(TextCellEvent.updateText(_controller.text)); + } + }); + } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart index 80a7a51d59..2a7baaa773 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart @@ -46,7 +46,7 @@ class _GridHeaderDelegate extends SliverPersistentHeaderDelegate { @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return _GridHeaderWidget(gridId: gridId, fields: fields, key: ObjectKey(fields)); + return _GridHeaderWidget(gridId: gridId, fields: fields); } @override @@ -73,27 +73,22 @@ class _GridHeaderWidget extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); - return BlocBuilder( - builder: (context, state) { - final cells = state.fields.map( - (field) => GridFieldCell( - GridFieldCellContext(gridId: gridId, field: field), - ), - ); - - final row = Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const _HeaderLeading(), - ...cells, - _HeaderTrailing(gridId: gridId), - ], - key: UniqueKey(), - ); - - return Container(height: GridSize.headerHeight, color: theme.surface, child: row); - }, + final cells = fields.map( + (field) => GridFieldCell( + GridFieldCellContext(gridId: gridId, field: field), + ), ); + + final row = Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const _HeaderLeading(), + ...cells, + _HeaderTrailing(gridId: gridId), + ], + ); + + return Container(height: GridSize.headerHeight, color: theme.surface, child: row); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index a69575a409..1893a77846 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -164,7 +164,7 @@ class _SelectOptionColorCell extends StatelessWidget { dimension: 16, child: Container( decoration: BoxDecoration( - color: color.color(context), + color: color.make(context), shape: BoxShape.circle, ), ), diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index abd76b4448..90e6dda24c 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -1148,6 +1148,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.11" + textfield_tags: + dependency: "direct main" + description: + name: textfield_tags + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" textstyle_extensions: dependency: transitive description: diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index ad1f6cd0e2..4d8ec095d5 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -67,7 +67,7 @@ dependencies: clipboard: ^0.1.3 connectivity_plus: 2.2.0 easy_localization: ^3.0.0 - + textfield_tags: ^2.0.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 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 443c1ee2bf..59840d1e4f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -303,12 +303,12 @@ impl ClientGridEditor { }; let field_metas = self.pad.read().await.get_field_metas(field_orders)?; - debug_assert!(field_metas.len() == expected_len); - if field_metas.len() != expected_len { + if expected_len != 0 && field_metas.len() != expected_len { tracing::error!( "This is a bug. The len of the field_metas should equal to {}", expected_len ); + debug_assert!(field_metas.len() == expected_len); } // field_metas.retain(|field_meta| field_meta.visibility); Ok(field_metas) From 271a8485b6fc5eecb7aadc1f66b835217d4eba96 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 4 Apr 2022 14:37:08 +0800 Subject: [PATCH 36/47] chore: selection text field --- .../grid/cell_bloc/selection_cell_bloc.dart | 8 +++--- .../grid/cell_bloc/text_cell_bloc.dart | 22 +++++++--------- .../application/grid/row/row_bloc.dart | 26 ++++++++++--------- .../application/grid/row/row_service.dart | 2 +- .../grid/src/widgets/cell/cell_builder.dart | 10 +++---- .../cell/selection_cell/extension.dart | 14 ++++------ .../cell/selection_cell/selection_cell.dart | 19 +++++++++++--- .../cell/selection_cell/selection_editor.dart | 17 ------------ .../grid/src/widgets/row/grid_row.dart | 24 +++++++++-------- 9 files changed, 66 insertions(+), 76 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 917e848a78..7c1358bced 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -36,9 +37,10 @@ class SelectionCellEvent with _$SelectionCellEvent { @freezed class SelectionCellState with _$SelectionCellState { - const factory SelectionCellState({ - Cell? cell, - }) = _SelectionCellState; + const factory SelectionCellState() = _SelectionCellState; + // required String girdId, + // required Field field, + // required List options, factory SelectionCellState.initial() => const SelectionCellState(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index 985fad03be..f2162d8851 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -33,17 +33,15 @@ class TextCellBloc extends Bloc { } void updateCellContent(String content) { - if (state.cellData != null) { - final fieldId = state.cellData!.field.id; - final gridId = state.cellData!.gridId; - final rowId = state.cellData!.rowId; - service.updateCell( - data: content, - fieldId: fieldId, - gridId: gridId, - rowId: rowId, - ); - } + final fieldId = state.cellData.field.id; + final gridId = state.cellData.gridId; + final rowId = state.cellData.rowId; + service.updateCell( + data: content, + fieldId: fieldId, + gridId: gridId, + rowId: rowId, + ); } @override @@ -67,7 +65,7 @@ class TextCellState with _$TextCellState { }) = _TextCellState; factory TextCellState.initial(FutureCellData cellData) => TextCellState( - content: cellData?.cell?.content ?? "", + content: cellData.cell?.content ?? "", cellData: cellData, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 6fc7221a76..85e5c35650 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -13,7 +13,7 @@ import 'package:dartz/dartz.dart'; part 'row_bloc.freezed.dart'; -typedef CellDataMap = HashMap; +typedef CellDataMap = LinkedHashMap; class RowBloc extends Bloc { final RowService rowService; @@ -48,10 +48,10 @@ class RowBloc extends Bloc { didUpdateCell: (_DidUpdateCell value) async { final optionRow = await state.row; final CellDataMap cellDataMap = optionRow.fold( - () => HashMap.identity(), + () => CellDataMap.identity(), (row) => _makeCellDatas(row), ); - emit(state.copyWith(cellDataMap: cellDataMap)); + emit(state.copyWith(cellDataMap: Some(cellDataMap))); }, ); }, @@ -111,13 +111,15 @@ class RowBloc extends Bloc { CellDataMap _makeCellDatas(Row row) { var map = CellDataMap.new(); for (final field in state.fields) { - map[field.id] = GridCellData( - rowId: row.id, - gridId: rowService.gridId, - blockId: rowService.blockId, - cell: row.cellByFieldId[field.id], - field: field, - ); + if (field.visibility) { + map[field.id] = GridCellData( + rowId: row.id, + gridId: rowService.gridId, + blockId: rowService.blockId, + cell: row.cellByFieldId[field.id], + field: field, + ); + } } return map; } @@ -138,7 +140,7 @@ class RowState with _$RowState { required double rowHeight, required List fields, required Future> row, - required CellDataMap? cellDataMap, + required Option cellDataMap, }) = _RowState; factory RowState.initial(GridRowData data) => RowState( @@ -146,6 +148,6 @@ class RowState with _$RowState { rowHeight: data.height, fields: data.fields, row: Future(() => none()), - cellDataMap: null, + cellDataMap: none(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index d30a22b7d0..1ef7b58d4b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -29,7 +29,7 @@ class RowService { } } -typedef FutureCellData = GridCellData?; +typedef FutureCellData = GridCellData; class GridCellData extends Equatable { final String gridId; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 8a1b3a63ea..178a44f9d7 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -1,5 +1,4 @@ import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; @@ -8,12 +7,9 @@ import 'number_cell.dart'; import 'selection_cell/selection_cell.dart'; import 'text_cell.dart'; -Widget buildGridCell(String rowId, Field field, FutureCellData cellData) { - if (cellData == null) { - return const SizedBox(); - } - final key = ValueKey(field.id + rowId); - switch (field.fieldType) { +Widget buildGridCell(FutureCellData cellData) { + final key = ValueKey(cellData.field.id + cellData.rowId); + switch (cellData.field.fieldType) { case FieldType.Checkbox: return CheckboxCell(cellData: cellData, key: key); case FieldType.DateTime: diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index 7bf977d6a4..7d5793f768 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -79,19 +79,13 @@ class SelectOptionTextField extends StatelessWidget { initialTags: ["abc", "bdf"], focusNode: _focusNode, textSeparators: const [' ', ','], - inputfieldBuilder: ( - BuildContext context, - TextEditingController editController, - FocusNode focusNode, - String? error, - void Function(String)? onChanged, - void Function(String)? onSubmitted, - ) { + inputfieldBuilder: (BuildContext context, editController, focusNode, error, onChanged, onSubmitted) { return ((context, sc, tags, onTagDelegate) { return TextField( controller: editController, focusNode: focusNode, - onChanged: (value) {}, + onChanged: onChanged, + onSubmitted: onSubmitted, onEditingComplete: () => focusNode.unfocus(), maxLines: 1, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), @@ -131,6 +125,8 @@ class SelectOptionTextField extends StatelessWidget { borderRadius: BorderRadius.circular(6.0), ), child: FlowyText.medium("abc", fontSize: 12), + margin: const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), ) ]), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 8e7c59b02c..5584b7ded5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -1,7 +1,9 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'extension.dart'; @@ -32,10 +34,19 @@ class _SingleSelectCellState extends State { @override Widget build(BuildContext context) { - _focusNode.addCallback(context, () {}); - return SelectOptionTextField( - focusNode: _focusNode, - controller: _controller, + _focusNode.addCallback(context, () { + Log.info(_focusNode.hasFocus); + }); + return BlocProvider.value( + value: _cellBloc, + child: BlocBuilder( + builder: (context, state) { + return SelectOptionTextField( + focusNode: _focusNode, + controller: _controller, + ); + }, + ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 98e1774425..20e329c788 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -114,20 +114,3 @@ class _SelectionCell extends StatelessWidget { ); } } - -class SelectionBadge extends StatelessWidget { - final SelectOption option; - const SelectionBadge({required this.option, Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: option.color.make(context), - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(6.0), - ), - child: FlowyText.medium(option.name, fontSize: 12), - ); - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index c4c32bda3b..06218f5776 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -122,17 +122,19 @@ class _RowCells extends StatelessWidget { return BlocBuilder( buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap, builder: (context, state) { - final children = state.fields - .where((field) => field.visibility) - .map((field) => CellContainer( - width: field.width.toDouble(), - child: buildGridCell( - state.rowId, - field, - state.cellDataMap?[field.id], - ), - )) - .toList(); + final List children = state.cellDataMap.fold( + () => [], + (dataMap) { + return dataMap.values.map( + (value) { + return CellContainer( + width: value.field.width.toDouble(), + child: buildGridCell(value), + ); + }, + ).toList(); + }, + ); return Row(children: children); }, From 5358203a46e0b95a627b03fda43a431fa3c8c87d Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 4 Apr 2022 20:47:04 +0800 Subject: [PATCH 37/47] chore: config option editor ui --- .../app_flowy/assets/translations/en.json | 3 +- .../app_flowy/lib/startup/deps_resolver.dart | 12 +- .../grid/cell_bloc/checkbox_cell_bloc.dart | 4 +- .../grid/cell_bloc/date_cell_bloc.dart | 2 +- .../grid/cell_bloc/number_cell_bloc.dart | 2 +- .../grid/cell_bloc/selection_cell_bloc.dart | 63 +++++- .../grid/cell_bloc/selection_editor_bloc.dart | 43 ++-- .../grid/cell_bloc/text_cell_bloc.dart | 8 +- .../workspace/application/grid/grid_bloc.dart | 8 +- .../application/grid/row/row_bloc.dart | 8 +- .../application/grid/row/row_service.dart | 6 +- .../plugins/grid/src/grid_page.dart | 2 +- .../plugins/grid/src/layout/sizes.dart | 13 +- .../grid/src/widgets/cell/cell_builder.dart | 2 +- .../grid/src/widgets/cell/cell_container.dart | 2 +- .../grid/src/widgets/cell/checkbox_cell.dart | 2 +- .../grid/src/widgets/cell/date_cell.dart | 2 +- .../grid/src/widgets/cell/number_cell.dart | 2 +- .../cell/selection_cell/extension.dart | 88 +++++---- .../cell/selection_cell/selection_cell.dart | 26 ++- .../cell/selection_cell/selection_editor.dart | 184 +++++++++++++----- .../grid/src/widgets/cell/text_cell.dart | 2 +- .../src/widgets/row/cell/number_cell.dart | 44 +++++ .../grid/src/widgets/row/grid_row.dart | 2 +- .../grid/src/widgets/row/number_cell.dart | 44 +++++ .../flowy_infra_ui/lib/style_widget/text.dart | 2 +- .../src/entities/meta.rs | 2 +- 27 files changed, 412 insertions(+), 166 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 55e57dfdc7..7e20a947dc 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -186,7 +186,8 @@ "blueColor": "Blue", "deleteTag": "Delete tag", "colorPannelTitle": "Colors", - "pannelTitle": "Select an option" + "pannelTitle": "Select an option or create one", + "searchOption": "Search for an option" } } } diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 9020101083..c23b259bfe 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -151,7 +151,7 @@ void _resolveGridDeps(GetIt getIt) { (view, _) => GridBloc(view: view, service: GridService()), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (data, _) => RowBloc( rowData: data, rowlistener: RowListener(rowId: data.rowId), @@ -179,35 +179,35 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => TextCellBloc( service: CellService(), cellData: cellData, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => SelectionCellBloc( service: CellService(), cellData: cellData, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => NumberCellBloc( service: CellService(), cellData: cellData, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => DateCellBloc( service: CellService(), cellData: cellData, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => CheckboxCellBloc( service: CellService(), cellData: cellData, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index 3609f39de7..f5bc7e7c18 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -9,11 +9,11 @@ part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { final CellService service; - // final FutureCellData cellData; + // final CellData cellData; CheckboxCellBloc({ required this.service, - required FutureCellData cellData, + required CellData cellData, }) : super(CheckboxCellState.initial()) { on( (event, emit) async { diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart index 33829863dd..7a995aab28 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/date_cell_bloc.dart @@ -9,7 +9,7 @@ part 'date_cell_bloc.freezed.dart'; class DateCellBloc extends Bloc { final CellService service; - final FutureCellData cellData; + final CellData cellData; DateCellBloc({ required this.service, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart index 6e58d24a54..83d2eff57d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart @@ -12,7 +12,7 @@ class NumberCellBloc extends Bloc { NumberCellBloc({ required this.service, - required FutureCellData cellData, + required CellData cellData, }) : super(NumberCellState.initial()) { on( (event, emit) async { diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 7c1358bced..2cde7c6a96 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -1,5 +1,7 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -13,12 +15,17 @@ class SelectionCellBloc extends Bloc { SelectionCellBloc({ required this.service, - required FutureCellData cellData, - }) : super(SelectionCellState.initial()) { + required CellData cellData, + }) : super(SelectionCellState.initial(cellData)) { on( (event, emit) async { await event.map( - initial: (_InitialCell value) async {}, + initial: (_InitialCell value) async { + _loadOptions(); + }, + didReceiveOptions: (_DidReceiveOptions value) { + emit(state.copyWith(options: value.options, selectedOptions: value.selectedOptions)); + }, ); }, ); @@ -28,19 +35,57 @@ class SelectionCellBloc extends Bloc { Future close() async { return super.close(); } + + void _loadOptions() async { + final result = await FieldContextLoaderAdaptor( + gridId: state.cellData.gridId, + field: state.cellData.field, + ).load(); + + result.fold( + (context) { + List options = []; + switch (state.cellData.field.fieldType) { + case FieldType.MultiSelect: + options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + case FieldType.SingleSelect: + options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + default: + Log.error("Invalid field type, expect single select or multiple select"); + break; + } + + final ids = state.cellData.cell?.content.split(','); + final selectedOptions = ids?.map((id) => options.firstWhere((option) => option.id == id)).toList() ?? []; + add(SelectionCellEvent.didReceiveOptions(options, selectedOptions)); + }, + (err) => Log.error(err), + ); + } } @freezed class SelectionCellEvent with _$SelectionCellEvent { const factory SelectionCellEvent.initial() = _InitialCell; + const factory SelectionCellEvent.didReceiveOptions( + List options, + List selectedOptions, + ) = _DidReceiveOptions; } @freezed class SelectionCellState with _$SelectionCellState { - const factory SelectionCellState() = _SelectionCellState; - // required String girdId, - // required Field field, - // required List options, + const factory SelectionCellState({ + required CellData cellData, + required List options, + required List selectedOptions, + }) = _SelectionCellState; - factory SelectionCellState.initial() => const SelectionCellState(); + factory SelectionCellState.initial(CellData cellData) => SelectionCellState( + cellData: cellData, + options: [], + selectedOptions: [], + ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index 7e617069c4..e2109a4c57 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -11,16 +11,18 @@ import 'cell_service.dart'; part 'selection_editor_bloc.freezed.dart'; -class SelectionEditorBloc extends Bloc { +class SelectOptionEditorBloc extends Bloc { final CellService service = CellService(); final FieldListener _listener; - SelectionEditorBloc({ + SelectOptionEditorBloc({ required String gridId, required Field field, + required List options, + required List selectedOptions, }) : _listener = FieldListener(fieldId: field.id), - super(SelectionEditorState.initial(gridId, field)) { - on( + super(SelectOptionEditorState.initial(gridId, field, options, selectedOptions)) { + on( (event, emit) async { await event.map( initial: (_Initial value) async { @@ -34,6 +36,7 @@ class SelectionEditorBloc extends Bloc add(SelectionEditorEvent.didReceiveFieldUpdate(field)), + (field) => add(SelectOptionEditorEvent.didReceiveFieldUpdate(field)), (err) => Log.error(err), ); }); @@ -70,7 +73,7 @@ class SelectionEditorBloc extends Bloc Log.error(err), ); @@ -78,25 +81,33 @@ class SelectionEditorBloc extends Bloc options) = _DidReceiveOptions; +class SelectOptionEditorEvent with _$SelectOptionEditorEvent { + const factory SelectOptionEditorEvent.initial() = _Initial; + const factory SelectOptionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; + const factory SelectOptionEditorEvent.didReceiveOptions(List options) = _DidReceiveOptions; + const factory SelectOptionEditorEvent.newOption(String optionName) = _newOption; } @freezed -class SelectionEditorState with _$SelectionEditorState { - const factory SelectionEditorState({ +class SelectOptionEditorState with _$SelectOptionEditorState { + const factory SelectOptionEditorState({ required String gridId, required Field field, required List options, - }) = _SelectionEditorState; + required List selectedOptions, + }) = _SelectOptionEditorState; - factory SelectionEditorState.initial(String gridId, Field field) { - return SelectionEditorState( + factory SelectOptionEditorState.initial( + String gridId, + Field field, + List options, + List selectedOptions, + ) { + return SelectOptionEditorState( gridId: gridId, field: field, - options: [], + options: options, + selectedOptions: selectedOptions, ); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart index f2162d8851..5af39bbd9f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/text_cell_bloc.dart @@ -11,7 +11,7 @@ class TextCellBloc extends Bloc { TextCellBloc({ required this.service, - required FutureCellData cellData, + required CellData cellData, }) : super(TextCellState.initial(cellData)) { on( (event, emit) async { @@ -53,7 +53,7 @@ class TextCellBloc extends Bloc { @freezed class TextCellEvent with _$TextCellEvent { const factory TextCellEvent.initial() = _InitialCell; - const factory TextCellEvent.didReceiveCellData(GridCellData cellData) = _DidReceiveCellData; + const factory TextCellEvent.didReceiveCellData(CellData cellData) = _DidReceiveCellData; const factory TextCellEvent.updateText(String text) = _UpdateText; } @@ -61,10 +61,10 @@ class TextCellEvent with _$TextCellEvent { class TextCellState with _$TextCellState { const factory TextCellState({ required String content, - required FutureCellData cellData, + required CellData cellData, }) = _TextCellState; - factory TextCellState.initial(FutureCellData cellData) => TextCellState( + factory TextCellState.initial(CellData cellData) => TextCellState( content: cellData.cell?.content ?? "", cellData: cellData, ); 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 00f90e0bfc..4b63ec0251 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -169,14 +169,14 @@ class GridBlockRow { }); } -class GridRowData extends Equatable { +class RowData extends Equatable { final String gridId; final String rowId; final String blockId; final List fields; final double height; - const GridRowData({ + const RowData({ required this.gridId, required this.rowId, required this.blockId, @@ -184,8 +184,8 @@ class GridRowData extends Equatable { required this.height, }); - factory GridRowData.fromBlockRow(GridBlockRow row, List fields) { - return GridRowData( + factory RowData.fromBlockRow(GridBlockRow row, List fields) { + return RowData( gridId: row.gridId, rowId: row.rowId, blockId: row.blockId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 85e5c35650..14f30b4359 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -13,14 +13,14 @@ import 'package:dartz/dartz.dart'; part 'row_bloc.freezed.dart'; -typedef CellDataMap = LinkedHashMap; +typedef CellDataMap = LinkedHashMap; class RowBloc extends Bloc { final RowService rowService; final RowListener rowlistener; final GridFieldsListener fieldListener; - RowBloc({required GridRowData rowData, required this.rowlistener}) + RowBloc({required RowData rowData, required this.rowlistener}) : rowService = RowService( gridId: rowData.gridId, blockId: rowData.blockId, @@ -112,7 +112,7 @@ class RowBloc extends Bloc { var map = CellDataMap.new(); for (final field in state.fields) { if (field.visibility) { - map[field.id] = GridCellData( + map[field.id] = CellData( rowId: row.id, gridId: rowService.gridId, blockId: rowService.blockId, @@ -143,7 +143,7 @@ class RowState with _$RowState { required Option cellDataMap, }) = _RowState; - factory RowState.initial(GridRowData data) => RowState( + factory RowState.initial(RowData data) => RowState( rowId: data.rowId, rowHeight: data.height, fields: data.fields, diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 1ef7b58d4b..a65cb81b29 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -29,16 +29,14 @@ class RowService { } } -typedef FutureCellData = GridCellData; - -class GridCellData extends Equatable { +class CellData extends Equatable { final String gridId; final String rowId; final String blockId; final Field field; final Cell? cell; - const GridCellData({ + const CellData({ required this.rowId, required this.gridId, required this.blockId, 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 111235841f..936ad68c44 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 @@ -157,7 +157,7 @@ class _FlowyGridState extends State { (context, index) { final blockRow = context.read().state.rows[index]; final fields = context.read().state.fields; - final rowData = GridRowData.fromBlockRow(blockRow, fields); + final rowData = RowData.fromBlockRow(blockRow, fields); return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)); }, childCount: context.read().state.rows.length, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart index c24bdb4326..23a541e610 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart @@ -9,8 +9,9 @@ class GridSize { static double get leadingHeaderPadding => 30 * scale; static double get trailHeaderPadding => 140 * scale; static double get headerContainerPadding => 0 * scale; - static double get cellContentPadding => 10 * scale; - static double get typeOptionItemHeight => 30 * scale; + static double get cellHPadding => 10 * scale; + static double get cellVPadding => 8 * scale; + static double get typeOptionItemHeight => 32 * scale; static double get typeOptionSeparatorHeight => 6 * scale; // @@ -19,13 +20,13 @@ class GridSize { vertical: GridSize.headerContainerPadding, ); static EdgeInsets get cellContentInsets => EdgeInsets.symmetric( - horizontal: GridSize.cellContentPadding, - vertical: GridSize.cellContentPadding, + horizontal: GridSize.cellHPadding, + vertical: GridSize.cellVPadding, ); static EdgeInsets get fieldContentInsets => EdgeInsets.symmetric( - horizontal: GridSize.cellContentPadding, - vertical: GridSize.cellContentPadding, + horizontal: GridSize.cellHPadding, + vertical: GridSize.cellVPadding, ); static EdgeInsets get typeOptionContentInsets => const EdgeInsets.symmetric( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 178a44f9d7..3b84ac557a 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -7,7 +7,7 @@ import 'number_cell.dart'; import 'selection_cell/selection_cell.dart'; import 'text_cell.dart'; -Widget buildGridCell(FutureCellData cellData) { +Widget buildGridCell(CellData cellData) { final key = ValueKey(cellData.field.id + cellData.rowId); switch (cellData.field.fieldType) { case FieldType.Checkbox: diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart index 8890dc7576..57f3610be2 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart @@ -38,7 +38,7 @@ class CellContainer extends StatelessWidget { ), decoration: _makeBoxDecoration(context, state), padding: GridSize.cellContentInsets, - child: Center(child: IntrinsicHeight(child: child)), + child: Center(child: child), ); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index dc8f757e36..7e1fdf166a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CheckboxCell extends StatefulWidget { - final FutureCellData cellData; + final CellData cellData; const CheckboxCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart index ec1babd799..e3b48279c0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class DateCell extends StatefulWidget { - final FutureCellData cellData; + final CellData cellData; const DateCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index bc51829412..41b8cf6ee5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class NumberCell extends StatefulWidget { - final FutureCellData cellData; + final CellData cellData; const NumberCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index 7d5793f768..9a91999a9d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -1,3 +1,6 @@ +import 'dart:collection'; + +import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; @@ -61,10 +64,19 @@ extension SelectOptionColorExtension on SelectOptionColor { } class SelectOptionTextField extends StatelessWidget { - final TextEditingController _controller; final FocusNode _focusNode; + final TextEditingController _controller; + final TextfieldTagsController tagController; + final LinkedHashMap optionMap; + final double distanceToText; + + final Function(String) onNewTag; SelectOptionTextField({ + required this.optionMap, + required this.distanceToText, + required this.tagController, + required this.onNewTag, TextEditingController? controller, FocusNode? focusNode, Key? key, @@ -74,26 +86,45 @@ class SelectOptionTextField extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = context.watch(); + return TextFieldTags( textEditingController: _controller, - initialTags: ["abc", "bdf"], + textfieldTagsController: tagController, + initialTags: optionMap.keys.toList(), focusNode: _focusNode, textSeparators: const [' ', ','], inputfieldBuilder: (BuildContext context, editController, focusNode, error, onChanged, onSubmitted) { return ((context, sc, tags, onTagDelegate) { + tags.retainWhere((name) => optionMap.containsKey(name) == false); + if (tags.isNotEmpty) { + assert(tags.length == 1); + onNewTag(tags.first); + } + return TextField( controller: editController, focusNode: focusNode, onChanged: onChanged, onSubmitted: onSubmitted, - onEditingComplete: () => focusNode.unfocus(), maxLines: 1, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), decoration: InputDecoration( - contentPadding: EdgeInsets.zero, - border: InputBorder.none, + border: OutlineInputBorder( + borderSide: BorderSide(color: theme.shader3, width: 1.0), + borderRadius: Corners.s10Border, + ), isDense: true, - prefixIcon: _renderTags(tags, sc), + prefixIcon: _renderTags(sc), + hintText: LocaleKeys.grid_selectOption_searchOption.tr(), + prefixIconConstraints: BoxConstraints(maxWidth: distanceToText), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: theme.main1, + width: 1.0, + ), + borderRadius: Corners.s10Border, + ), ), ); }); @@ -101,41 +132,26 @@ class SelectOptionTextField extends StatelessWidget { ); } - Widget? _renderTags(List tags, ScrollController sc) { - if (tags.isEmpty) { + Widget? _renderTags(ScrollController sc) { + if (optionMap.isEmpty) { return null; } - return SingleChildScrollView( - controller: sc, - scrollDirection: Axis.horizontal, - child: Row(children: [ - Container( - decoration: BoxDecoration( - color: Color.fromARGB(255, 74, 137, 92), - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(6.0), - ), - child: FlowyText.medium("efc", fontSize: 12), - ), - Container( - decoration: BoxDecoration( - color: Color.fromARGB(255, 74, 137, 92), - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(6.0), - ), - child: FlowyText.medium("abc", fontSize: 12), - margin: const EdgeInsets.symmetric(horizontal: 5.0), - padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), - ) - ]), + final children = optionMap.values.map((option) => SelectOptionTag(option: option)).toList(); + return Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + controller: sc, + scrollDirection: Axis.horizontal, + child: Row(children: children), + ), ); } } -class SelectionBadge extends StatelessWidget { +class SelectOptionTag extends StatelessWidget { final SelectOption option; - const SelectionBadge({required this.option, Key? key}) : super(key: key); + const SelectOptionTag({required this.option, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -143,9 +159,11 @@ class SelectionBadge extends StatelessWidget { decoration: BoxDecoration( color: option.color.make(context), shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(6.0), + borderRadius: BorderRadius.circular(8.0), ), - child: FlowyText.medium(option.name, fontSize: 12), + child: Center(child: FlowyText.medium(option.name, fontSize: 12)), + margin: const EdgeInsets.symmetric(horizontal: 3.0), + padding: const EdgeInsets.symmetric(horizontal: 6.0), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 5584b7ded5..3fe1b19c14 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -6,9 +6,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'extension.dart'; +import 'selection_editor.dart'; class SingleSelectCell extends StatefulWidget { - final FutureCellData cellData; + final CellData cellData; const SingleSelectCell({ required this.cellData, @@ -20,30 +21,28 @@ class SingleSelectCell extends StatefulWidget { } class _SingleSelectCellState extends State { - late CellFocusNode _focusNode; late SelectionCellBloc _cellBloc; - late TextEditingController _controller; @override void initState() { - _cellBloc = getIt(param1: widget.cellData); - _controller = TextEditingController(); - _focusNode = CellFocusNode(); + _cellBloc = getIt(param1: widget.cellData)..add(const SelectionCellEvent.initial()); super.initState(); } @override Widget build(BuildContext context) { - _focusNode.addCallback(context, () { - Log.info(_focusNode.hasFocus); - }); return BlocProvider.value( value: _cellBloc, child: BlocBuilder( builder: (context, state) { - return SelectOptionTextField( - focusNode: _focusNode, - controller: _controller, + final children = state.selectedOptions.map((option) => SelectOptionTag(option: option)).toList(); + return SizedBox.expand( + child: InkWell( + onTap: () { + SelectionEditor.show(context, state.cellData, state.options, state.selectedOptions); + }, + child: Row(children: children), + ), ); }, ), @@ -53,14 +52,13 @@ class _SingleSelectCellState extends State { @override Future dispose() async { _cellBloc.close(); - _focusNode.dispose(); super.dispose(); } } //---------------------------------------------------------------- class MultiSelectCell extends StatefulWidget { - final FutureCellData cellData; + final CellData cellData; const MultiSelectCell({ required this.cellData, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 20e329c788..0c8d207a4b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -1,6 +1,9 @@ +import 'dart:collection'; + import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; @@ -12,42 +15,81 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:textfield_tags/textfield_tags.dart'; import 'extension.dart'; -class SelectionEditor extends StatelessWidget { - final GridCellData cellData; - const SelectionEditor({required this.cellData, Key? key}) : super(key: key); +const double _editorPannelWidth = 300; - void show(BuildContext context) { - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - child: this, - constraints: BoxConstraints.loose(const Size(240, 200)), - ), - identifier: toString(), - anchorContext: context, - anchorDirection: AnchorDirection.bottomWithLeftAligned, - ); +class SelectionEditor extends StatelessWidget { + final CellData cellData; + final List options; + final List selectedOptions; + + const SelectionEditor({ + required this.cellData, + required this.options, + required this.selectedOptions, + Key? key, + }) : super(key: key); + + static String identifier() { + return (SelectionEditor).toString(); } @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => SelectionEditorBloc(gridId: cellData.gridId, field: cellData.field), - child: BlocBuilder( + create: (context) => SelectOptionEditorBloc( + gridId: cellData.gridId, + field: cellData.field, + options: options, + selectedOptions: selectedOptions, + ), + child: BlocBuilder( builder: (context, state) { - return Column( - children: const [ - _Title(), - VSpace(10), - _OptionList(), + return CustomScrollView( + shrinkWrap: true, + slivers: [ + SliverToBoxAdapter(child: _TextField()), + const SliverToBoxAdapter(child: VSpace(10)), + const SliverToBoxAdapter(child: _Title()), + const SliverToBoxAdapter(child: _OptionList()), ], ); }, ), ); } + + static void show( + BuildContext context, + CellData cellData, + List options, + List selectedOptions, + ) { + SelectionEditor.hide(context); + final editor = SelectionEditor( + cellData: cellData, + options: options, + selectedOptions: selectedOptions, + ); + + // + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: SizedBox(width: _editorPannelWidth, child: editor), + constraints: BoxConstraints.loose(const Size(_editorPannelWidth, 300)), + ), + identifier: SelectionEditor.identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomWithCenterAligned, + ); + } + + static void hide(BuildContext context) { + FlowyOverlay.of(context).remove(identifier()); + } } class _OptionList extends StatelessWidget { @@ -55,9 +97,9 @@ class _OptionList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { - final cells = state.options.map((option) => _SelectionCell(option)).toList(); + final cells = state.options.map((option) => _SelectOptionCell(option)).toList(); final list = ListView.separated( shrinkWrap: true, controller: ScrollController(), @@ -76,40 +118,84 @@ class _OptionList extends StatelessWidget { } } +class _TextField extends StatelessWidget { + final TextfieldTagsController _tagController = TextfieldTagsController(); + + _TextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) {}, + buildWhen: (previous, current) => previous.field.id != current.field.id, + builder: (context, state) { + final optionMap = LinkedHashMap.fromIterable(state.selectedOptions, + key: (option) => option.name, value: (option) => option); + return SizedBox( + height: 42, + child: SelectOptionTextField( + optionMap: optionMap, + distanceToText: _editorPannelWidth * 0.7, + tagController: _tagController, + onNewTag: (newTagName) { + context.read().add(SelectOptionEditorEvent.newOption(newTagName)); + }, + ), + ); + }, + ); + } +} + class _Title extends StatelessWidget { const _Title({Key? key}) : super(key: key); @override Widget build(BuildContext context) { + final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, - child: FlowyText.medium(LocaleKeys.grid_selectOption_pannelTitle.tr(), fontSize: 12), - ); - } -} - -class _SelectionCell extends StatelessWidget { - final SelectOption option; - const _SelectionCell(this.option, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.watch(); - - // return FlowyButton( - // text: FlowyText.medium(fieldType.title(), fontSize: 12), - // hoverColor: theme.hover, - // onTap: () => onSelectField(fieldType), - // leftIcon: svgWidget(fieldType.iconName(), color: theme.iconColor), - // ); - - return InkWell( - onTap: () {}, - child: FlowyHover( - config: HoverDisplayConfig(hoverColor: theme.hover), - builder: (_, onHover) { - return SelectionBadge(option: option); - }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: FlowyText.medium( + LocaleKeys.grid_selectOption_pannelTitle.tr(), + fontSize: 12, + color: theme.shader3, + ), + ), + ); + } +} + +class _SelectOptionCell extends StatelessWidget { + final SelectOption option; + const _SelectOptionCell(this.option, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: InkWell( + onTap: () {}, + child: FlowyHover( + config: HoverDisplayConfig(hoverColor: theme.hover), + builder: (_, onHover) { + List children = [ + SelectOptionTag(option: option), + const Spacer(), + ]; + + if (onHover) { + children.add(svgWidget("editor/details", color: theme.iconColor)); + } + + return Padding( + padding: const EdgeInsets.all(3.0), + child: Row(children: children), + ); + }, + ), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index c4e272aeb4..c7b4219bab 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -6,7 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_container.dart'; class GridTextCell extends GridCell { - final FutureCellData cellData; + final CellData cellData; const GridTextCell({ required this.cellData, Key? key, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart new file mode 100644 index 0000000000..41b8cf6ee5 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart @@ -0,0 +1,44 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class NumberCell extends StatefulWidget { + final CellData cellData; + + const NumberCell({ + required this.cellData, + Key? key, + }) : super(key: key); + + @override + State createState() => _NumberCellState(); +} + +class _NumberCellState extends State { + late NumberCellBloc _cellBloc; + + @override + void initState() { + _cellBloc = getIt(param1: widget.cellData); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BlocProvider.value( + value: _cellBloc, + child: BlocBuilder( + builder: (context, state) { + return Container(); + }, + ), + ); + } + + @override + Future dispose() async { + _cellBloc.close(); + super.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index 06218f5776..5586328e32 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -10,7 +10,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; class GridRowWidget extends StatefulWidget { - final GridRowData data; + final RowData data; const GridRowWidget({required this.data, Key? key}) : super(key: key); @override diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart new file mode 100644 index 0000000000..41b8cf6ee5 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart @@ -0,0 +1,44 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class NumberCell extends StatefulWidget { + final CellData cellData; + + const NumberCell({ + required this.cellData, + Key? key, + }) : super(key: key); + + @override + State createState() => _NumberCellState(); +} + +class _NumberCellState extends State { + late NumberCellBloc _cellBloc; + + @override + void initState() { + _cellBloc = getIt(param1: widget.cellData); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BlocProvider.value( + value: _cellBloc, + child: BlocBuilder( + builder: (context, state) { + return Container(); + }, + ), + ); + } + + @override + Future dispose() async { + _cellBloc.close(); + super.dispose(); + } +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart index 7ddfdc1c13..55f29eba93 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart @@ -44,7 +44,7 @@ class FlowyText extends StatelessWidget { softWrap: false, textAlign: textAlign, style: TextStyle( - color: theme.textColor, + color: color ?? theme.textColor, fontWeight: fontWeight, fontSize: fontSize + 2, fontFamily: 'Mulish', diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index a543085a78..9be0faa99d 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; -pub const DEFAULT_ROW_HEIGHT: i32 = 36; +pub const DEFAULT_ROW_HEIGHT: i32 = 42; pub const DEFAULT_FIELD_WIDTH: i32 = 150; #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] From 99d827f07daa1c6e3ac8568aaf36c9145ee7eba6 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 5 Apr 2022 14:25:07 +0800 Subject: [PATCH 38/47] chore: update cell data --- .../grid/cell_bloc/selection_editor_bloc.dart | 39 +- .../dart_event/flowy-grid/dart_event.dart | 34 + .../flowy-error-code/code.pbenum.dart | 2 + .../flowy-error-code/code.pbjson.dart | 3 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 4 + .../protobuf/flowy-grid/event_map.pbjson.dart | 4 +- .../flowy-grid/selection_type_option.pb.dart | 164 +++++ .../selection_type_option.pbjson.dart | 28 + .../down.sql | 3 + .../up.sql | 7 + .../rust-lib/flowy-database/src/schema.rs | 8 + .../rust-lib/flowy-grid/src/event_handler.rs | 19 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 9 +- frontend/rust-lib/flowy-grid/src/manager.rs | 37 +- .../src/protobuf/model/event_map.rs | 13 +- .../protobuf/model/selection_type_option.rs | 596 +++++++++++++++++- .../src/protobuf/proto/event_map.proto | 2 + .../proto/selection_type_option.proto | 10 + .../src/services/block_meta_editor.rs | 94 ++- .../type_options/checkbox_type_option.rs | 6 +- .../field/type_options/date_type_option.rs | 6 +- .../field/type_options/number_type_option.rs | 6 +- .../type_options/selection_type_option.rs | 82 ++- .../field/type_options/text_type_option.rs | 6 +- .../flowy-grid/src/services/grid_editor.rs | 49 +- .../rust-lib/flowy-grid/src/services/mod.rs | 2 +- .../src/services/persistence/block_index.rs | 49 ++ .../{kv_persistence.rs => persistence/kv.rs} | 9 +- .../src/services/persistence/mod.rs | 16 + ...l_data_serde.rs => cell_data_operation.rs} | 5 +- .../flowy-grid/src/services/row/mod.rs | 4 +- .../src/services/row/row_builder.rs | 1 + .../flowy-grid/src/services/row/row_loader.rs | 32 +- .../flowy-grid/tests/grid/grid_test.rs | 2 +- .../flowy-sdk/src/deps_resolve/grid_deps.rs | 16 +- shared-lib/flowy-error-code/src/code.rs | 2 + .../src/protobuf/model/code.rs | 14 +- .../src/protobuf/proto/code.proto | 1 + .../src/entities/grid.rs | 6 + .../src/entities/meta.rs | 14 +- .../src/client_grid/grid_meta_pad.rs | 3 +- 41 files changed, 1235 insertions(+), 172 deletions(-) create mode 100644 frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/down.sql create mode 100644 frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/up.sql create mode 100644 frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs rename frontend/rust-lib/flowy-grid/src/services/{kv_persistence.rs => persistence/kv.rs} (95%) create mode 100644 frontend/rust-lib/flowy-grid/src/services/persistence/mod.rs rename frontend/rust-lib/flowy-grid/src/services/row/{cell_data_serde.rs => cell_data_operation.rs} (97%) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index e2109a4c57..5ce68105ea 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -1,5 +1,7 @@ import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; @@ -12,16 +14,18 @@ import 'cell_service.dart'; part 'selection_editor_bloc.freezed.dart'; class SelectOptionEditorBloc extends Bloc { - final CellService service = CellService(); + final TypeOptionService _typeOptionService; + final CellService _cellService; final FieldListener _listener; SelectOptionEditorBloc({ - required String gridId, - required Field field, + required CellData cellData, required List options, required List selectedOptions, - }) : _listener = FieldListener(fieldId: field.id), - super(SelectOptionEditorState.initial(gridId, field, options, selectedOptions)) { + }) : _cellService = CellService(), + _typeOptionService = TypeOptionService(fieldId: cellData.field.id), + _listener = FieldListener(fieldId: cellData.field.id), + super(SelectOptionEditorState.initial(cellData, options, selectedOptions)) { on( (event, emit) async { await event.map( @@ -36,7 +40,18 @@ class SelectOptionEditorBloc extends Bloc null, (err) => Log.error(err)); + }, + selectOption: (_SelectOption value) { + _cellService.updateCell( + gridId: state.gridId, + fieldId: state.fieldId, + rowId: state.rowId, + data: data, + ); + }, ); }, ); @@ -85,7 +100,8 @@ class SelectOptionEditorEvent with _$SelectOptionEditorEvent { const factory SelectOptionEditorEvent.initial() = _Initial; const factory SelectOptionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; const factory SelectOptionEditorEvent.didReceiveOptions(List options) = _DidReceiveOptions; - const factory SelectOptionEditorEvent.newOption(String optionName) = _newOption; + const factory SelectOptionEditorEvent.newOption(String optionName) = _NewOption; + const factory SelectOptionEditorEvent.selectOption(String optionId) = _SelectOption; } @freezed @@ -93,19 +109,20 @@ class SelectOptionEditorState with _$SelectOptionEditorState { const factory SelectOptionEditorState({ required String gridId, required Field field, + required String rowId, required List options, required List selectedOptions, }) = _SelectOptionEditorState; factory SelectOptionEditorState.initial( - String gridId, - Field field, + CellData cellData, List options, List selectedOptions, ) { return SelectOptionEditorState( - gridId: gridId, - field: field, + gridId: cellData.gridId, + field: cellData.field, + rowId: cellData.rowId, options: options, selectedOptions: selectedOptions, ); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 45b33f1004..a709d06fe8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -171,6 +171,23 @@ class GridEventCreateSelectOption { } } +class GridEventGetSelectOptions { + FieldIdentifierPayload request; + GridEventGetSelectOptions(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.GetSelectOptions.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(SelectOptionContext.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateRow { CreateRowPayload request; GridEventCreateRow(this.request); @@ -222,3 +239,20 @@ class GridEventUpdateCell { } } +class GridEventInsertSelectOption { + InsertSelectOptionPayload request; + GridEventInsertSelectOption(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.InsertSelectOption.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart index 9c4e31eeea..a638e65405 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -45,6 +45,7 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode GridIdIsEmpty = ErrorCode._(410, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridIdIsEmpty'); static const ErrorCode BlockIdIsEmpty = ErrorCode._(420, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockIdIsEmpty'); static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty'); + static const ErrorCode OptionIdIsEmpty = ErrorCode._(431, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'OptionIdIsEmpty'); static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty'); static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist'); static const ErrorCode SelectOptionNameIsEmpty = ErrorCode._(442, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SelectOptionNameIsEmpty'); @@ -87,6 +88,7 @@ class ErrorCode extends $pb.ProtobufEnum { GridIdIsEmpty, BlockIdIsEmpty, RowIdIsEmpty, + OptionIdIsEmpty, FieldIdIsEmpty, FieldDoesNotExist, SelectOptionNameIsEmpty, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart index b3efa2c0ad..625e2d9572 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -47,6 +47,7 @@ const ErrorCode$json = const { const {'1': 'GridIdIsEmpty', '2': 410}, const {'1': 'BlockIdIsEmpty', '2': 420}, const {'1': 'RowIdIsEmpty', '2': 430}, + const {'1': 'OptionIdIsEmpty', '2': 431}, const {'1': 'FieldIdIsEmpty', '2': 440}, const {'1': 'FieldDoesNotExist', '2': 441}, const {'1': 'SelectOptionNameIsEmpty', '2': 442}, @@ -56,4 +57,4 @@ const ErrorCode$json = const { }; /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIcChdTZWxlY3RPcHRpb25OYW1lSXNFbXB0eRC6AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM='); +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxIUCg9PcHRpb25JZElzRW1wdHkQrwMSEwoORmllbGRJZElzRW1wdHkQuAMSFgoRRmllbGREb2VzTm90RXhpc3QQuQMSHAoXU2VsZWN0T3B0aW9uTmFtZUlzRW1wdHkQugMSGgoVVHlwZU9wdGlvbkRhdGFJc0VtcHR5EMIDEhAKC0ludmFsaWREYXRhEPQD'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 7d69a59524..2de16d922c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -20,9 +20,11 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); static const GridEvent GetEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetEditFieldContext'); static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption'); + static const GridEvent GetSelectOptions = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptions'); static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); + static const GridEvent InsertSelectOption = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InsertSelectOption'); static const $core.List values = [ GetGridData, @@ -35,9 +37,11 @@ class GridEvent extends $pb.ProtobufEnum { DuplicateField, GetEditFieldContext, CreateSelectOption, + GetSelectOptions, CreateRow, GetRow, UpdateCell, + InsertSelectOption, ]; static final $core.Map<$core.int, GridEvent> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index dc5ca350b6..56b593c688 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -22,11 +22,13 @@ const GridEvent$json = const { const {'1': 'DuplicateField', '2': 15}, const {'1': 'GetEditFieldContext', '2': 16}, const {'1': 'CreateSelectOption', '2': 30}, + const {'1': 'GetSelectOptions', '2': 31}, const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, const {'1': 'UpdateCell', '2': 70}, + const {'1': 'InsertSelectOption', '2': 71}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg4KClVwZGF0ZUNlbGwQRg=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEhQKEEdldFNlbGVjdE9wdGlvbnMQHxINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxIOCgpVcGRhdGVDZWxsEEYSFgoSSW5zZXJ0U2VsZWN0T3B0aW9uEEc='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart index 2e1ac9610e..2b9fc8a5ce 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart @@ -198,3 +198,167 @@ class SelectOption extends $pb.GeneratedMessage { void clearColor() => clearField(3); } +enum SelectOptionChangesetPayload_OneOfInsertOptionId { + insertOptionId, + notSet +} + +enum SelectOptionChangesetPayload_OneOfDeleteOptionId { + deleteOptionId, + notSet +} + +class SelectOptionChangesetPayload extends $pb.GeneratedMessage { + static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfInsertOptionId> _SelectOptionChangesetPayload_OneOfInsertOptionIdByTag = { + 3 : SelectOptionChangesetPayload_OneOfInsertOptionId.insertOptionId, + 0 : SelectOptionChangesetPayload_OneOfInsertOptionId.notSet + }; + static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfDeleteOptionId> _SelectOptionChangesetPayload_OneOfDeleteOptionIdByTag = { + 4 : SelectOptionChangesetPayload_OneOfDeleteOptionId.deleteOptionId, + 0 : SelectOptionChangesetPayload_OneOfDeleteOptionId.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionChangesetPayload', createEmptyInstance: create) + ..oo(0, [3]) + ..oo(1, [4]) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOptionId') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOptionId') + ..hasRequiredFields = false + ; + + SelectOptionChangesetPayload._() : super(); + factory SelectOptionChangesetPayload({ + $core.String? gridId, + $core.String? rowId, + $core.String? insertOptionId, + $core.String? deleteOptionId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (rowId != null) { + _result.rowId = rowId; + } + if (insertOptionId != null) { + _result.insertOptionId = insertOptionId; + } + if (deleteOptionId != null) { + _result.deleteOptionId = deleteOptionId; + } + return _result; + } + factory SelectOptionChangesetPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectOptionChangesetPayload.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') + SelectOptionChangesetPayload clone() => SelectOptionChangesetPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectOptionChangesetPayload copyWith(void Function(SelectOptionChangesetPayload) updates) => super.copyWith((message) => updates(message as SelectOptionChangesetPayload)) as SelectOptionChangesetPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SelectOptionChangesetPayload create() => SelectOptionChangesetPayload._(); + SelectOptionChangesetPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectOptionChangesetPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectOptionChangesetPayload? _defaultInstance; + + SelectOptionChangesetPayload_OneOfInsertOptionId whichOneOfInsertOptionId() => _SelectOptionChangesetPayload_OneOfInsertOptionIdByTag[$_whichOneof(0)]!; + void clearOneOfInsertOptionId() => clearField($_whichOneof(0)); + + SelectOptionChangesetPayload_OneOfDeleteOptionId whichOneOfDeleteOptionId() => _SelectOptionChangesetPayload_OneOfDeleteOptionIdByTag[$_whichOneof(1)]!; + void clearOneOfDeleteOptionId() => clearField($_whichOneof(1)); + + @$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.String get insertOptionId => $_getSZ(2); + @$pb.TagNumber(3) + set insertOptionId($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasInsertOptionId() => $_has(2); + @$pb.TagNumber(3) + void clearInsertOptionId() => clearField(3); + + @$pb.TagNumber(4) + $core.String get deleteOptionId => $_getSZ(3); + @$pb.TagNumber(4) + set deleteOptionId($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasDeleteOptionId() => $_has(3); + @$pb.TagNumber(4) + void clearDeleteOptionId() => clearField(4); +} + +class SelectOptionContext extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionContext', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selectOptions', $pb.PbFieldType.PM, subBuilder: SelectOption.create) + ..hasRequiredFields = false + ; + + SelectOptionContext._() : super(); + factory SelectOptionContext({ + $core.Iterable? options, + $core.Iterable? selectOptions, + }) { + final _result = create(); + if (options != null) { + _result.options.addAll(options); + } + if (selectOptions != null) { + _result.selectOptions.addAll(selectOptions); + } + return _result; + } + factory SelectOptionContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectOptionContext.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') + SelectOptionContext clone() => SelectOptionContext()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectOptionContext copyWith(void Function(SelectOptionContext) updates) => super.copyWith((message) => updates(message as SelectOptionContext)) as SelectOptionContext; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SelectOptionContext create() => SelectOptionContext._(); + SelectOptionContext createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectOptionContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectOptionContext? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get options => $_getList(0); + + @$pb.TagNumber(2) + $core.List get selectOptions => $_getList(1); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart index 7499864079..4002db9a33 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart @@ -60,3 +60,31 @@ const SelectOption$json = const { /// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSKAoFY29sb3IYAyABKA4yEi5TZWxlY3RPcHRpb25Db2xvclIFY29sb3I='); +@$core.Deprecated('Use selectOptionChangesetPayloadDescriptor instead') +const SelectOptionChangesetPayload$json = const { + '1': 'SelectOptionChangesetPayload', + '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': 'insert_option_id', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'insertOptionId'}, + const {'1': 'delete_option_id', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'deleteOptionId'}, + ], + '8': const [ + const {'1': 'one_of_insert_option_id'}, + const {'1': 'one_of_delete_option_id'}, + ], +}; + +/// Descriptor for `SelectOptionChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionChangesetPayloadDescriptor = $convert.base64Decode('ChxTZWxlY3RPcHRpb25DaGFuZ2VzZXRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEioKEGluc2VydF9vcHRpb25faWQYAyABKAlIAFIOaW5zZXJ0T3B0aW9uSWQSKgoQZGVsZXRlX29wdGlvbl9pZBgEIAEoCUgBUg5kZWxldGVPcHRpb25JZEIZChdvbmVfb2ZfaW5zZXJ0X29wdGlvbl9pZEIZChdvbmVfb2ZfZGVsZXRlX29wdGlvbl9pZA=='); +@$core.Deprecated('Use selectOptionContextDescriptor instead') +const SelectOptionContext$json = const { + '1': 'SelectOptionContext', + '2': const [ + const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'}, + const {'1': 'select_options', '3': 2, '4': 3, '5': 11, '6': '.SelectOption', '10': 'selectOptions'}, + ], +}; + +/// Descriptor for `SelectOptionContext`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionContextDescriptor = $convert.base64Decode('ChNTZWxlY3RPcHRpb25Db250ZXh0EicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSNAoOc2VsZWN0X29wdGlvbnMYAiADKAsyDS5TZWxlY3RPcHRpb25SDXNlbGVjdE9wdGlvbnM='); diff --git a/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/down.sql b/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/down.sql new file mode 100644 index 0000000000..06daaca7de --- /dev/null +++ b/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +DROP TABLE grid_block_index_table; +-- DROP TABLE grid_block_fts_table; \ No newline at end of file diff --git a/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/up.sql b/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/up.sql new file mode 100644 index 0000000000..f55bc82f64 --- /dev/null +++ b/frontend/rust-lib/flowy-database/migrations/2022-04-05-015536_flowy-grid-block-index/up.sql @@ -0,0 +1,7 @@ +-- Your SQL goes here +CREATE TABLE grid_block_index_table ( + row_id TEXT NOT NULL PRIMARY KEY, + block_id TEXT NOT NULL +); + +-- CREATE VIRTUAL TABLE grid_block_fts_table USING FTS5(content, grid_id, block_id, row_id); \ No newline at end of file diff --git a/frontend/rust-lib/flowy-database/src/schema.rs b/frontend/rust-lib/flowy-database/src/schema.rs index 6be116e806..8fddd037e0 100644 --- a/frontend/rust-lib/flowy-database/src/schema.rs +++ b/frontend/rust-lib/flowy-database/src/schema.rs @@ -21,6 +21,13 @@ table! { } } +table! { + grid_block_index_table (row_id) { + row_id -> Text, + block_id -> Text, + } +} + table! { grid_meta_rev_table (id) { id -> Integer, @@ -113,6 +120,7 @@ table! { allow_tables_to_appear_in_same_query!( app_table, doc_table, + grid_block_index_table, grid_meta_rev_table, grid_rev_table, kv_table, diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index e90998b986..dd7675e803 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,8 @@ use crate::manager::GridManager; -use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str, SelectOption}; +use crate::services::field::{ + default_type_option_builder_from_type, type_option_builder_from_json_str, SelectOption, + SelectOptionChangesetParams, SelectOptionChangesetPayload, +}; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; @@ -40,7 +43,8 @@ pub(crate) async fn get_fields_handler( ) -> DataResult { let params: QueryFieldParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let field_metas = editor.get_field_metas(Some(params.field_orders)).await?; + let field_orders = params.field_orders.items; + let field_metas = editor.get_field_metas(Some(field_orders)).await?; let repeated_field: RepeatedField = field_metas.into_iter().map(Field::from).collect::>().into(); data_result(repeated_field) } @@ -203,3 +207,14 @@ pub(crate) async fn update_cell_handler( let _ = editor.update_cell(changeset).await?; Ok(()) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn insert_select_option_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let params: SelectOptionChangesetParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let _ = editor.insert_select_option(params).await?; + Ok(()) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 5183b8afb7..64c7c70e56 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -20,7 +20,8 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::CreateSelectOption, create_select_option_handler) .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) - .event(GridEvent::UpdateCell, update_cell_handler); + .event(GridEvent::UpdateCell, update_cell_handler) + .event(GridEvent::InsertSelectOption, insert_select_option_handler); module } @@ -58,6 +59,9 @@ pub enum GridEvent { #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] CreateSelectOption = 30, + #[event(input = "FieldIdentifierPayload", output = "SelectOptionContext")] + GetSelectOptions = 31, + #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 50, @@ -66,4 +70,7 @@ pub enum GridEvent { #[event(input = "CellMetaChangeset")] UpdateCell = 70, + + #[event(input = "InsertSelectOptionPayload")] + InsertSelectOption = 71, } diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index e4f24a8547..686f539b74 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -1,5 +1,7 @@ use crate::services::grid_editor::ClientGridEditor; -use crate::services::kv_persistence::GridKVPersistence; +use crate::services::persistence::block_index::BlockIndexPersistence; +use crate::services::persistence::kv::GridKVPersistence; +use crate::services::persistence::GridDatabase; use bytes::Bytes; use dashmap::DashMap; use flowy_database::ConnectionPool; @@ -21,20 +23,24 @@ pub trait GridUser: Send + Sync { pub struct GridManager { editor_map: Arc, grid_user: Arc, - kv_persistence: Arc>>>, + block_index_persistence: Arc, + kv_persistence: Arc, } impl GridManager { - pub fn new(grid_user: Arc, _rev_web_socket: Arc) -> Self { + pub fn new( + grid_user: Arc, + _rev_web_socket: Arc, + database: Arc, + ) -> Self { let grid_editors = Arc::new(GridEditorMap::new()); - - // kv_persistence will be initialized after first access. - // See get_kv_persistence function below - let kv_persistence = Arc::new(RwLock::new(None)); + let kv_persistence = Arc::new(GridKVPersistence::new(database.clone())); + let block_index_persistence = Arc::new(BlockIndexPersistence::new(database)); Self { editor_map: grid_editors, grid_user, kv_persistence, + block_index_persistence, } } @@ -111,7 +117,8 @@ impl GridManager { ) -> Result, FlowyError> { let user = self.grid_user.clone(); let rev_manager = self.make_grid_rev_manager(grid_id, pool.clone())?; - let grid_editor = ClientGridEditor::new(grid_id, user, rev_manager).await?; + let grid_editor = + ClientGridEditor::new(grid_id, user, rev_manager, self.block_index_persistence.clone()).await?; Ok(grid_editor) } @@ -135,20 +142,6 @@ impl GridManager { let rev_manager = RevisionManager::new(&user_id, block_d, rev_persistence); Ok(rev_manager) } - - #[allow(dead_code)] - async fn get_kv_persistence(&self) -> FlowyResult> { - let read_guard = self.kv_persistence.read().await; - if read_guard.is_some() { - return Ok(read_guard.clone().unwrap()); - } - drop(read_guard); - - let pool = self.grid_user.db_pool()?; - let kv_persistence = Arc::new(GridKVPersistence::new(pool)); - *self.kv_persistence.write().await = Some(kv_persistence.clone()); - Ok(kv_persistence) - } } pub struct GridEditorMap { diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 368c4df718..ae1dfe161d 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -35,9 +35,11 @@ pub enum GridEvent { DuplicateField = 15, GetEditFieldContext = 16, CreateSelectOption = 30, + GetSelectOptions = 31, CreateRow = 50, GetRow = 51, UpdateCell = 70, + InsertSelectOption = 71, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -57,9 +59,11 @@ impl ::protobuf::ProtobufEnum for GridEvent { 15 => ::std::option::Option::Some(GridEvent::DuplicateField), 16 => ::std::option::Option::Some(GridEvent::GetEditFieldContext), 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption), + 31 => ::std::option::Option::Some(GridEvent::GetSelectOptions), 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), 70 => ::std::option::Option::Some(GridEvent::UpdateCell), + 71 => ::std::option::Option::Some(GridEvent::InsertSelectOption), _ => ::std::option::Option::None } } @@ -76,9 +80,11 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::DuplicateField, GridEvent::GetEditFieldContext, GridEvent::CreateSelectOption, + GridEvent::GetSelectOptions, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, + GridEvent::InsertSelectOption, ]; values } @@ -107,13 +113,14 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xf4\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xa2\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x16\n\x12Creat\ - eSelectOption\x10\x1e\x12\r\n\tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\ - \x0e\n\nUpdateCell\x10Fb\x06proto3\ + eSelectOption\x10\x1e\x12\x14\n\x10GetSelectOptions\x10\x1f\x12\r\n\tCre\ + ateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\x16\n\ + \x12InsertSelectOption\x10Gb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs index ae57224d2e..ba0e1bebe9 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs @@ -657,6 +657,585 @@ impl ::protobuf::reflect::ProtobufValue for SelectOption { } } +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionChangesetPayload { + // message fields + pub grid_id: ::std::string::String, + pub row_id: ::std::string::String, + // message oneof groups + pub one_of_insert_option_id: ::std::option::Option, + pub one_of_delete_option_id: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOptionChangesetPayload { + fn default() -> &'a SelectOptionChangesetPayload { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionChangesetPayload_oneof_one_of_insert_option_id { + insert_option_id(::std::string::String), +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionChangesetPayload_oneof_one_of_delete_option_id { + delete_option_id(::std::string::String), +} + +impl SelectOptionChangesetPayload { + pub fn new() -> SelectOptionChangesetPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string row_id = 2; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } + + // string insert_option_id = 3; + + + pub fn get_insert_option_id(&self) -> &str { + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v)) => v, + _ => "", + } + } + pub fn clear_insert_option_id(&mut self) { + self.one_of_insert_option_id = ::std::option::Option::None; + } + + pub fn has_insert_option_id(&self) -> bool { + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_insert_option_id(&mut self, v: ::std::string::String) { + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_insert_option_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(_)) = self.one_of_insert_option_id { + } else { + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(::std::string::String::new())); + } + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_insert_option_id(&mut self) -> ::std::string::String { + if self.has_insert_option_id() { + match self.one_of_insert_option_id.take() { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } + + // string delete_option_id = 4; + + + pub fn get_delete_option_id(&self) -> &str { + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v)) => v, + _ => "", + } + } + pub fn clear_delete_option_id(&mut self) { + self.one_of_delete_option_id = ::std::option::Option::None; + } + + pub fn has_delete_option_id(&self) -> bool { + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_delete_option_id(&mut self, v: ::std::string::String) { + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_delete_option_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(_)) = self.one_of_delete_option_id { + } else { + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(::std::string::String::new())); + } + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_delete_option_id(&mut self) -> ::std::string::String { + if self.has_delete_option_id() { + match self.one_of_delete_option_id.take() { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } +} + +impl ::protobuf::Message for SelectOptionChangesetPayload { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + 3 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); + }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(is.read_string()?)); + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.row_id); + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { + match v { + &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + my_size += ::protobuf::rt::string_size(3, &v); + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { + match v { + &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + my_size += ::protobuf::rt::string_size(4, &v); + }, + }; + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.row_id.is_empty() { + os.write_string(2, &self.row_id)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { + match v { + &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + os.write_string(3, v)?; + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { + match v { + &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + os.write_string(4, v)?; + }, + }; + } + 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() -> SelectOptionChangesetPayload { + SelectOptionChangesetPayload::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>( + "grid_id", + |m: &SelectOptionChangesetPayload| { &m.grid_id }, + |m: &mut SelectOptionChangesetPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &SelectOptionChangesetPayload| { &m.row_id }, + |m: &mut SelectOptionChangesetPayload| { &mut m.row_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "insert_option_id", + SelectOptionChangesetPayload::has_insert_option_id, + SelectOptionChangesetPayload::get_insert_option_id, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "delete_option_id", + SelectOptionChangesetPayload::has_delete_option_id, + SelectOptionChangesetPayload::get_delete_option_id, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionChangesetPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionChangesetPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionChangesetPayload::new) + } +} + +impl ::protobuf::Clear for SelectOptionChangesetPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.row_id.clear(); + self.one_of_insert_option_id = ::std::option::Option::None; + self.one_of_delete_option_id = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionChangesetPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionChangesetPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionContext { + // message fields + pub options: ::protobuf::RepeatedField, + pub select_options: ::protobuf::RepeatedField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOptionContext { + fn default() -> &'a SelectOptionContext { + ::default_instance() + } +} + +impl SelectOptionContext { + pub fn new() -> SelectOptionContext { + ::std::default::Default::default() + } + + // repeated .SelectOption options = 1; + + + pub fn get_options(&self) -> &[SelectOption] { + &self.options + } + pub fn clear_options(&mut self) { + self.options.clear(); + } + + // Param is passed by value, moved + pub fn set_options(&mut self, v: ::protobuf::RepeatedField) { + self.options = v; + } + + // Mutable pointer to the field. + pub fn mut_options(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.options + } + + // Take field + pub fn take_options(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.options, ::protobuf::RepeatedField::new()) + } + + // repeated .SelectOption select_options = 2; + + + pub fn get_select_options(&self) -> &[SelectOption] { + &self.select_options + } + pub fn clear_select_options(&mut self) { + self.select_options.clear(); + } + + // Param is passed by value, moved + pub fn set_select_options(&mut self, v: ::protobuf::RepeatedField) { + self.select_options = v; + } + + // Mutable pointer to the field. + pub fn mut_select_options(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.select_options + } + + // Take field + pub fn take_select_options(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.select_options, ::protobuf::RepeatedField::new()) + } +} + +impl ::protobuf::Message for SelectOptionContext { + fn is_initialized(&self) -> bool { + for v in &self.options { + if !v.is_initialized() { + return false; + } + }; + for v in &self.select_options { + 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.options)?; + }, + 2 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.select_options)?; + }, + _ => { + ::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.options { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + for value in &self.select_options { + 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.options { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + for v in &self.select_options { + os.write_tag(2, ::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() -> SelectOptionContext { + SelectOptionContext::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>( + "options", + |m: &SelectOptionContext| { &m.options }, + |m: &mut SelectOptionContext| { &mut m.options }, + )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "select_options", + |m: &SelectOptionContext| { &m.select_options }, + |m: &mut SelectOptionContext| { &mut m.select_options }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionContext", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionContext { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionContext::new) + } +} + +impl ::protobuf::Clear for SelectOptionContext { + fn clear(&mut self) { + self.options.clear(); + self.select_options.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionContext { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionContext { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum SelectOptionColor { Purple = 0, @@ -736,11 +1315,18 @@ static file_descriptor_proto_data: &'static [u8] = b"\ s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"\\\n\x0cS\ electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ \x18\x02\x20\x01(\tR\x04name\x12(\n\x05color\x18\x03\x20\x01(\x0e2\x12.S\ - electOptionColorR\x05color*y\n\x11SelectOptionColor\x12\n\n\x06Purple\ - \x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\x10\x02\x12\n\n\x06O\ - range\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\n\x04Lime\x10\x05\x12\t\ - \n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\x12\x08\n\x04Blue\x10\x08b\ - \x06proto3\ + electOptionColorR\x05color\"\xdc\x01\n\x1cSelectOptionChangesetPayload\ + \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\ + \x18\x02\x20\x01(\tR\x05rowId\x12*\n\x10insert_option_id\x18\x03\x20\x01\ + (\tH\0R\x0einsertOptionId\x12*\n\x10delete_option_id\x18\x04\x20\x01(\tH\ + \x01R\x0edeleteOptionIdB\x19\n\x17one_of_insert_option_idB\x19\n\x17one_\ + of_delete_option_id\"t\n\x13SelectOptionContext\x12'\n\x07options\x18\ + \x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x124\n\x0eselect_options\ + \x18\x02\x20\x03(\x0b2\r.SelectOptionR\rselectOptions*y\n\x11SelectOptio\ + nColor\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightP\ + ink\x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\ + \n\x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\ + \x12\x08\n\x04Blue\x10\x08b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 9d2ea5961f..4703711cb3 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -11,7 +11,9 @@ enum GridEvent { DuplicateField = 15; GetEditFieldContext = 16; CreateSelectOption = 30; + GetSelectOptions = 31; CreateRow = 50; GetRow = 51; UpdateCell = 70; + InsertSelectOption = 71; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto index f07e2273bb..37dc0a36c1 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto @@ -13,6 +13,16 @@ message SelectOption { string name = 2; SelectOptionColor color = 3; } +message SelectOptionChangesetPayload { + string grid_id = 1; + string row_id = 2; + oneof one_of_insert_option_id { string insert_option_id = 3; }; + oneof one_of_delete_option_id { string delete_option_id = 4; }; +} +message SelectOptionContext { + repeated SelectOption options = 1; + repeated SelectOption select_options = 2; +} enum SelectOptionColor { Purple = 0; Pink = 1; 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 353185f498..c5082a1c2e 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,6 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; -use crate::services::row::{make_cell, make_row_ids_per_block, GridBlockSnapshot}; +use crate::services::persistence::block_index::BlockIndexPersistence; +use crate::services::row::{make_block_row_ids, make_cell_by_field_id, GridBlockSnapshot}; use bytes::Bytes; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; @@ -28,20 +29,24 @@ pub(crate) struct GridBlockMetaEditorManager { grid_id: String, user: Arc, editor_map: DashMap>, - block_id_by_row_id: DashMap, + persistence: Arc, } impl GridBlockMetaEditorManager { - pub(crate) async fn new(grid_id: &str, user: &Arc, blocks: Vec) -> FlowyResult { + pub(crate) async fn new( + grid_id: &str, + user: &Arc, + blocks: Vec, + persistence: Arc, + ) -> 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, + persistence, }; Ok(manager) } @@ -60,14 +65,18 @@ impl GridBlockMetaEditorManager { } } + async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { + let block_id = self.persistence.get_block_id(row_id)?; + Ok(self.get_editor(&block_id).await?) + } + pub(crate) async fn create_row( &self, block_id: &str, row_meta: RowMeta, start_row_id: Option, ) -> FlowyResult { - self.block_id_by_row_id - .insert(row_meta.id.clone(), row_meta.block_id.clone()); + let _ = self.persistence.insert_or_update(&row_meta.block_id, &row_meta.id)?; let editor = self.get_editor(&row_meta.block_id).await?; let row_count = editor.create_row(row_meta, start_row_id).await?; self.notify_block_did_update_row(block_id).await?; @@ -83,7 +92,7 @@ impl GridBlockMetaEditorManager { let editor = self.get_editor(&block_id).await?; let mut row_count = 0; for row in &row_metas { - self.block_id_by_row_id.insert(row.id.clone(), row.block_id.clone()); + let _ = self.persistence.insert_or_update(&row.block_id, &row.id)?; row_count = editor.create_row(row.clone(), None).await?; } changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); @@ -95,12 +104,11 @@ impl GridBlockMetaEditorManager { pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { let mut changesets = vec![]; - let row_ids_per_blocks = make_row_ids_per_block(&row_orders); - for row_ids_per_block in row_ids_per_blocks { - let editor = self.get_editor(&row_ids_per_block.block_id).await?; - let row_count = editor.delete_rows(row_ids_per_block.row_ids).await?; + for block_row_ids in make_block_row_ids(&row_orders) { + let editor = self.get_editor(&block_row_ids.block_id).await?; + let row_count = editor.delete_rows(block_row_ids.row_ids).await?; - let changeset = GridBlockMetaChangeset::from_row_count(&row_ids_per_block.block_id, row_count); + let changeset = GridBlockMetaChangeset::from_row_count(&block_row_ids.block_id, row_count); changesets.push(changeset); } @@ -114,10 +122,17 @@ impl GridBlockMetaEditorManager { Ok(()) } - pub async fn get_row(&self, block_id: &str, row_id: &str) -> FlowyResult>> { - let editor = self.get_editor(block_id).await?; + pub async fn update_row_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 async fn get_row_meta(&self, row_id: &str) -> FlowyResult>> { + let editor = self.get_editor_from_row_id(row_id).await?; let row_ids = vec![row_id.to_owned()]; - let mut row_metas = editor.get_row_metas(&Some(row_ids)).await?; + let mut row_metas = editor.get_row_metas(Some(row_ids)).await?; if row_metas.is_empty() { Ok(None) } else { @@ -125,23 +140,11 @@ impl GridBlockMetaEditorManager { } } - 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 make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { let mut snapshots = vec![]; for block_id in block_ids { let editor = self.get_editor(&block_id).await?; - let row_metas = editor.get_row_metas(&None).await?; - row_metas.iter().for_each(|row_meta| { - self.block_id_by_row_id - .insert(row_meta.id.clone(), row_meta.block_id.clone()); - }); - + let row_metas = editor.get_row_metas(None).await?; snapshots.push(GridBlockSnapshot { block_id, row_metas }); } Ok(snapshots) @@ -164,19 +167,6 @@ impl GridBlockMetaEditorManager { Ok(block_cell_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) => Ok(self.get_editor(&block_id).await?), - } - } - async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { let block_order: GridBlockOrder = block_id.into(); send_dart_notification(&self.grid_id, GridNotification::DidUpdateRow) @@ -196,7 +186,7 @@ impl GridBlockMetaEditorManager { .cell_by_field_id .into_iter() .for_each( - |(field_id, cell_meta)| match make_cell(&field_meta_map, field_id, cell_meta) { + |(field_id, cell_meta)| match make_cell_by_field_id(&field_meta_map, field_id, cell_meta) { None => {} Some((_, cell)) => cells.push(cell), }, @@ -290,23 +280,13 @@ impl ClientGridBlockMetaEditor { Ok(row_count) } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult { - let row_id = changeset.row_id.clone(); + pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?; - let row_ids = vec![row_id.clone()]; - let mut row_metas = self.get_row_metas(&Some(row_ids)).await?; - debug_assert_eq!(row_metas.len(), 1); - - if row_metas.is_empty() { - return Err(FlowyError::record_not_found().context(format!("Can't find the row with id: {}", &row_id))); - } else { - let a = (**row_metas.pop().as_ref().unwrap()).clone(); - Ok(a) - } + Ok(()) } - pub async fn get_row_metas(&self, row_ids: &Option>) -> FlowyResult>> { - let row_metas = self.pad.read().await.get_row_metas(row_ids)?; + pub async fn get_row_metas(&self, row_ids: Option>) -> FlowyResult>> { + let row_metas = self.pad.read().await.get_row_metas(&row_ids)?; Ok(row_metas) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 84d693edd0..b91409c904 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,6 +1,6 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{CellDataSerde, TypeOptionCellData}; +use crate::services::row::{CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; @@ -40,7 +40,7 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox); const YES: &str = "Yes"; const NO: &str = "No"; -impl CellDataSerde for CheckboxTypeOption { +impl CellDataOperation for CheckboxTypeOption { fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_text() || !type_option_cell_data.is_checkbox() { @@ -81,7 +81,7 @@ fn string_to_bool(bool_str: &str) -> bool { mod tests { use crate::services::field::CheckboxTypeOption; use crate::services::field::FieldBuilder; - use crate::services::row::CellDataSerde; + use crate::services::row::CellDataOperation; use flowy_grid_data_model::entities::FieldType; #[test] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 5dd88a4a67..2c67c69fe5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,5 +1,5 @@ use crate::impl_type_option; -use crate::services::row::{CellDataSerde, TypeOptionCellData}; +use crate::services::row::{CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; @@ -42,7 +42,7 @@ impl DateTypeOption { } } -impl CellDataSerde for DateTypeOption { +impl CellDataOperation for DateTypeOption { fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_date() { @@ -185,7 +185,7 @@ impl std::default::Default for TimeFormat { mod tests { use crate::services::field::FieldBuilder; use crate::services::field::{DateFormat, DateTypeOption, TimeFormat}; - use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use crate::services::row::{CellDataOperation, TypeOptionCellData}; use flowy_grid_data_model::entities::FieldType; use strum::IntoEnumIterator; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 7cee8a3b39..55ce729a7f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -1,5 +1,5 @@ use crate::impl_type_option; -use crate::services::row::{CellDataSerde, TypeOptionCellData}; +use crate::services::row::{CellDataOperation, TypeOptionCellData}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; @@ -76,7 +76,7 @@ pub struct NumberTypeOption { } impl_type_option!(NumberTypeOption, FieldType::Number); -impl CellDataSerde for NumberTypeOption { +impl CellDataOperation for NumberTypeOption { fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if type_option_cell_data.is_date() { @@ -205,7 +205,7 @@ fn make_strip_symbol() -> Vec { mod tests { use crate::services::field::FieldBuilder; use crate::services::field::{NumberFormat, NumberTypeOption}; - use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use crate::services::row::{CellDataOperation, TypeOptionCellData}; use flowy_grid_data_model::entities::FieldType; use strum::IntoEnumIterator; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 5768a92f70..1774b12ce3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,11 +1,12 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{CellDataSerde, TypeOptionCellData}; +use crate::services::row::{CellDataOperation, TypeOptionCellData}; use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_error::{FlowyError, FlowyResult}; +use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -24,7 +25,7 @@ pub struct SingleSelectTypeOption { } impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); -impl CellDataSerde for SingleSelectTypeOption { +impl CellDataOperation for SingleSelectTypeOption { fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { @@ -80,7 +81,7 @@ pub struct MultiSelectTypeOption { } impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); -impl CellDataSerde for MultiSelectTypeOption { +impl CellDataOperation for MultiSelectTypeOption { fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { @@ -190,6 +191,77 @@ impl SelectOption { } } +#[derive(Clone, Debug, Default, ProtoBuf)] +pub struct SelectOptionChangesetPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub row_id: String, + + #[pb(index = 3)] + pub field_id: String, + + #[pb(index = 4, one_of)] + pub insert_option_id: Option, + + #[pb(index = 5, one_of)] + pub delete_option_id: Option, +} + +#[derive(Clone)] +pub struct SelectOptionChangesetParams { + pub grid_id: String, + pub field_id: String, + pub row_id: String, + pub insert_option_id: Option, + pub delete_option_id: Option, +} + +impl TryInto for SelectOptionChangesetPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + let insert_option_id = match self.insert_option_id { + None => None, + Some(insert_option_id) => Some( + NotEmptyStr::parse(insert_option_id) + .map_err(|_| ErrorCode::OptionIdIsEmpty)? + .0, + ), + }; + + let delete_option_id = match self.delete_option_id { + None => None, + Some(delete_option_id) => Some( + NotEmptyStr::parse(delete_option_id) + .map_err(|_| ErrorCode::OptionIdIsEmpty)? + .0, + ), + }; + + Ok(SelectOptionChangesetParams { + grid_id: grid_id.0, + row_id: row_id.0, + field_id: field_id.0, + insert_option_id, + delete_option_id, + }) + } +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] +pub struct SelectOptionContext { + #[pb(index = 1)] + pub options: Vec, + + #[pb(index = 2)] + pub select_options: Vec, +} + #[derive(ProtoBuf_Enum, Serialize, Deserialize, Debug, Clone)] #[repr(u8)] pub enum SelectOptionColor { @@ -213,7 +285,7 @@ impl std::default::Default for SelectOptionColor { #[cfg(test)] mod tests { use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; - use crate::services::row::CellDataSerde; + use crate::services::row::CellDataOperation; #[test] #[should_panic] diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 87434a3cdb..4b7195a305 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,6 +1,6 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{deserialize_cell_data, CellDataSerde, TypeOptionCellData}; +use crate::services::row::{deserialize_cell_data, CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; @@ -30,7 +30,7 @@ pub struct RichTextTypeOption { } impl_type_option!(RichTextTypeOption, FieldType::RichText); -impl CellDataSerde for RichTextTypeOption { +impl CellDataOperation for RichTextTypeOption { fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if type_option_cell_data.is_date() @@ -61,7 +61,7 @@ impl CellDataSerde for RichTextTypeOption { mod tests { use crate::services::field::FieldBuilder; use crate::services::field::*; - use crate::services::row::{CellDataSerde, TypeOptionCellData}; + use crate::services::row::{CellDataOperation, TypeOptionCellData}; use flowy_grid_data_model::entities::FieldType; #[test] 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 59840d1e4f..708e07fd74 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,10 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; +use crate::services::field::{ + default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder, SelectOptionChangesetParams, +}; +use crate::services::persistence::block_index::BlockIndexPersistence; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; @@ -30,17 +33,16 @@ impl ClientGridEditor { grid_id: &str, user: Arc, mut rev_manager: RevisionManager, + persistence: Arc, ) -> FlowyResult> { let token = user.token()?; let cloud = Arc::new(GridRevisionCloudService { token }); let grid_pad = rev_manager.load::(Some(cloud)).await?; let rev_manager = Arc::new(rev_manager); let pad = Arc::new(RwLock::new(grid_pad)); + let blocks = pad.read().await.get_block_metas().clone(); - let block_meta_manager = Arc::new( - GridBlockMetaEditorManager::new(grid_id, &user, pad.read().await.get_block_metas().clone()).await?, - ); - + let block_meta_manager = Arc::new(GridBlockMetaEditorManager::new(grid_id, &user, blocks, persistence).await?); Ok(Arc::new(Self { grid_id: grid_id.to_owned(), user, @@ -223,12 +225,12 @@ impl ClientGridEditor { } } - pub async fn get_row(&self, block_id: &str, row_id: &str) -> FlowyResult> { - match self.block_meta_manager.get_row(block_id, row_id).await? { + pub async fn get_row(&self, row_id: &str) -> FlowyResult> { + match self.block_meta_manager.get_row_meta(row_id).await? { None => Ok(None), - Some(row) => { + Some(row_meta) => { let field_metas = self.get_field_metas(None).await?; - let row_metas = vec![row]; + let row_metas = vec![row_meta]; let mut rows = make_rows_from_row_metas(&field_metas, &row_metas); debug_assert!(rows.len() == 1); Ok(rows.pop()) @@ -236,12 +238,28 @@ impl ClientGridEditor { } } + pub async fn get_cell_meta(&self, row_id: &str, field_id: &str) -> FlowyResult> { + let row_meta = self.block_meta_manager.get_row_meta(row_id).await?; + match row_meta { + None => Ok(None), + Some(row_meta) => { + let cell_meta = row_meta.cell_by_field_id.get(field_id).cloned(); + Ok(cell_meta) + } + } + } + + pub async fn apply_select_option(&self, params: SelectOptionChangesetParams) -> FlowyResult<()> { + let cell_meta = self.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?; + todo!() + } + pub async fn update_cell(&self, mut changeset: CellMetaChangeset) -> FlowyResult<()> { if let Some(cell_data) = changeset.data.as_ref() { match self.pad.read().await.get_field(&changeset.field_id) { None => { - return Err(FlowyError::internal() - .context(format!("Can not find the field with id: {}", &changeset.field_id))); + let msg = format!("Can not find the field with id: {}", &changeset.field_id); + return Err(FlowyError::internal().context(msg)); } Some(field_meta) => { let cell_data = serialize_cell_data(cell_data, field_meta)?; @@ -254,7 +272,7 @@ impl ClientGridEditor { let row_changeset: RowMetaChangeset = changeset.into(); let _ = self .block_meta_manager - .update_cells(&field_metas, row_changeset) + .update_row_cells(&field_metas, row_changeset) .await?; Ok(()) } @@ -296,7 +314,7 @@ impl ClientGridEditor { }) } - pub async fn get_field_metas(&self, field_orders: Option) -> FlowyResult> { + pub async fn get_field_metas(&self, field_orders: Option>) -> FlowyResult> { let expected_len = match field_orders.as_ref() { None => 0, Some(field_orders) => field_orders.len(), @@ -310,7 +328,6 @@ impl ClientGridEditor { ); debug_assert!(field_metas.len() == expected_len); } - // field_metas.retain(|field_meta| field_meta.visibility); Ok(field_metas) } @@ -385,8 +402,8 @@ impl ClientGridEditor { } async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> { - let field_orders: RepeatedFieldOrder = vec![FieldOrder::from(field_id)].into(); - let mut field_metas = self.get_field_metas(Some(field_orders)).await?; + let field_order = FieldOrder::from(field_id); + let mut field_metas = self.get_field_metas(Some(field_order.into())).await?; debug_assert!(field_metas.len() == 1); if let Some(field_meta) = field_metas.pop() { diff --git a/frontend/rust-lib/flowy-grid/src/services/mod.rs b/frontend/rust-lib/flowy-grid/src/services/mod.rs index d3eb2d2857..6ae3be1dca 100644 --- a/frontend/rust-lib/flowy-grid/src/services/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/mod.rs @@ -3,5 +3,5 @@ mod util; pub mod block_meta_editor; pub mod field; pub mod grid_editor; -pub mod kv_persistence; +pub mod persistence; pub mod row; diff --git a/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs b/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs new file mode 100644 index 0000000000..a639776394 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs @@ -0,0 +1,49 @@ +use crate::services::persistence::GridDatabase; +use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; +use flowy_database::{ + prelude::*, + schema::{grid_block_index_table, grid_block_index_table::dsl}, + ConnectionPool, +}; +use flowy_error::FlowyResult; +use std::sync::Arc; + +pub struct BlockIndexPersistence { + database: Arc, +} + +impl BlockIndexPersistence { + pub fn new(database: Arc) -> Self { + Self { database } + } + + pub fn get_block_id(&self, row_id: &str) -> FlowyResult { + let conn = self.database.db_connection()?; + let block_id = dsl::grid_block_index_table + .filter(grid_block_index_table::row_id.eq(row_id)) + .select(grid_block_index_table::block_id) + .first::(&*conn)?; + + Ok(block_id) + } + + pub fn insert_or_update(&self, block_id: &str, row_id: &str) -> FlowyResult<()> { + let conn = self.database.db_connection()?; + let item = IndexItem { + row_id: row_id.to_string(), + block_id: block_id.to_string(), + }; + let _ = diesel::replace_into(grid_block_index_table::table) + .values(item) + .execute(&*conn)?; + Ok(()) + } +} + +#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] +#[table_name = "grid_block_index_table"] +#[primary_key(row_id)] +struct IndexItem { + row_id: String, + block_id: String, +} diff --git a/frontend/rust-lib/flowy-grid/src/services/kv_persistence.rs b/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs similarity index 95% rename from frontend/rust-lib/flowy-grid/src/services/kv_persistence.rs rename to frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs index 89961ace48..cf66211fab 100644 --- a/frontend/rust-lib/flowy-grid/src/services/kv_persistence.rs +++ b/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs @@ -1,3 +1,4 @@ +use crate::services::persistence::GridDatabase; use ::diesel::{query_dsl::*, ExpressionMethods}; use bytes::Bytes; use diesel::SqliteConnection; @@ -29,19 +30,19 @@ pub trait KVTransaction { } pub struct GridKVPersistence { - pool: Arc, + database: Arc, } impl GridKVPersistence { - pub fn new(pool: Arc) -> Self { - Self { pool } + pub fn new(database: Arc) -> Self { + Self { database } } pub fn begin_transaction(&self, f: F) -> FlowyResult where F: for<'a> FnOnce(SqliteTransaction<'a>) -> FlowyResult, { - let conn = self.pool.get()?; + let conn = self.database.db_connection()?; conn.immediate_transaction::<_, FlowyError, _>(|| { let sql_transaction = SqliteTransaction { conn: &conn }; f(sql_transaction) diff --git a/frontend/rust-lib/flowy-grid/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-grid/src/services/persistence/mod.rs new file mode 100644 index 0000000000..d6167cf8e6 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/persistence/mod.rs @@ -0,0 +1,16 @@ +use flowy_database::{ConnectionPool, DBConnection}; +use flowy_error::FlowyError; +use std::sync::Arc; + +pub mod block_index; +pub mod kv; + +pub trait GridDatabase: Send + Sync { + fn db_pool(&self) -> Result, FlowyError>; + + fn db_connection(&self) -> Result { + let pool = self.db_pool()?; + let conn = pool.get().map_err(|e| FlowyError::internal().context(e))?; + Ok(conn) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs similarity index 97% rename from frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs rename to frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs index 259e052ab7..ad0dcb1646 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs @@ -1,11 +1,13 @@ use crate::services::field::*; +use bytes::Bytes; use flowy_error::FlowyError; use flowy_grid_data_model::entities::{FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; -pub trait CellDataSerde { +pub trait CellDataOperation { fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String; fn serialize_cell_data(&self, data: &str) -> Result; + // fn apply_changeset() } #[derive(Serialize, Deserialize)] @@ -60,7 +62,6 @@ impl TypeOptionCellData { } } -#[allow(dead_code)] pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result { match field_meta.field_type { FieldType::RichText => RichTextTypeOption::from(field_meta).serialize_cell_data(data), diff --git a/frontend/rust-lib/flowy-grid/src/services/row/mod.rs b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs index fec4ea8d8c..e2727cdf34 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs @@ -1,7 +1,7 @@ -mod cell_data_serde; +mod cell_data_operation; mod row_builder; mod row_loader; -pub use cell_data_serde::*; +pub use cell_data_operation::*; pub use row_builder::*; pub(crate) use row_loader::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index cbaae78fed..698d4ac4ec 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -1,4 +1,5 @@ use crate::services::row::serialize_cell_data; +use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{CellMeta, FieldMeta, RowMeta, DEFAULT_ROW_HEIGHT}; use std::collections::HashMap; 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 55ee0ec8c8..c497d7e12d 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 @@ -8,14 +8,14 @@ use std::collections::HashMap; use std::sync::Arc; -pub(crate) struct RowIdsPerBlock { +pub(crate) struct BlockRowIds { pub(crate) block_id: String, pub(crate) row_ids: Vec, } -impl RowIdsPerBlock { +impl BlockRowIds { pub fn new(block_id: &str) -> Self { - RowIdsPerBlock { + BlockRowIds { block_id: block_id.to_owned(), row_ids: vec![], } @@ -27,13 +27,13 @@ pub struct GridBlockSnapshot { pub row_metas: Vec>, } -pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec { - let mut map: HashMap<&String, RowIdsPerBlock> = HashMap::new(); +pub(crate) fn make_block_row_ids(row_orders: &[RowOrder]) -> Vec { + let mut map: HashMap<&String, BlockRowIds> = HashMap::new(); row_orders.iter().for_each(|row_order| { let block_id = &row_order.block_id; let row_id = row_order.row_id.clone(); map.entry(block_id) - .or_insert_with(|| RowIdsPerBlock::new(block_id)) + .or_insert_with(|| BlockRowIds::new(block_id)) .row_ids .push(row_id); }); @@ -41,13 +41,13 @@ pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec, field_id: String, - raw_cell: CellMeta, + cell_meta: CellMeta, ) -> Option<(String, Cell)> { let field_meta = field_map.get(&field_id)?; - match deserialize_cell_data(raw_cell.data, field_meta) { + match deserialize_cell_data(cell_meta.data, field_meta) { Ok(content) => { let cell = Cell::new(&field_id, content); Some((field_id, cell)) @@ -59,6 +59,18 @@ pub fn make_cell( } } +#[allow(dead_code)] +pub fn make_cell(field_id: &str, field_meta: &FieldMeta, row_meta: &RowMeta) -> Option { + let cell_meta = row_meta.cell_by_field_id.get(field_id)?.clone(); + match deserialize_cell_data(cell_meta.data, field_meta) { + Ok(content) => Some(Cell::new(&field_id, content)), + Err(e) => { + tracing::error!("{}", e); + None + } + } +} + pub(crate) fn make_row_orders_from_row_metas(row_metas: &[Arc]) -> Vec { row_metas.iter().map(RowOrder::from).collect::>() } @@ -74,7 +86,7 @@ pub(crate) fn make_rows_from_row_metas(fields: &[FieldMeta], row_metas: &[Arc>(); Row { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 138ccf4bba..26dd3896dc 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -4,7 +4,7 @@ use chrono::NaiveDateTime; use flowy_grid::services::field::{ MultiSelectTypeOption, SelectOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, }; -use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataSerde, CreateRowMetaBuilder}; +use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataOperation, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ CellMetaChangeset, FieldChangesetParams, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, TypeOptionDataEntry, diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/grid_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/grid_deps.rs index 514c320511..88073a3107 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/grid_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/grid_deps.rs @@ -2,6 +2,7 @@ use crate::FlowyError; use bytes::Bytes; use flowy_database::ConnectionPool; use flowy_grid::manager::{GridManager, GridUser}; +use flowy_grid::services::persistence::GridDatabase; use flowy_net::ws::connection::FlowyWebSocketConnect; use flowy_revision::{RevisionWebSocket, WSStateReceiver}; use flowy_sync::entities::ws_data::ClientRevisionWSData; @@ -16,9 +17,20 @@ pub struct GridDepsResolver(); impl GridDepsResolver { pub fn resolve(ws_conn: Arc, user_session: Arc) -> Arc { - let user = Arc::new(GridUserImpl(user_session)); + let user = Arc::new(GridUserImpl(user_session.clone())); let rev_web_socket = Arc::new(GridWebSocket(ws_conn)); - Arc::new(GridManager::new(user, rev_web_socket)) + Arc::new(GridManager::new( + user, + rev_web_socket, + Arc::new(GridDatabaseImpl(user_session)), + )) + } +} + +struct GridDatabaseImpl(Arc); +impl GridDatabase for GridDatabaseImpl { + fn db_pool(&self) -> Result, FlowyError> { + self.0.db_pool().map_err(|e| FlowyError::internal().context(e)) } } diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 3b0cf331ee..30af0f9885 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -95,6 +95,8 @@ pub enum ErrorCode { BlockIdIsEmpty = 420, #[display(fmt = "Row id is empty")] RowIdIsEmpty = 430, + #[display(fmt = "Select option id is empty")] + OptionIdIsEmpty = 431, #[display(fmt = "Field id is empty")] FieldIdIsEmpty = 440, #[display(fmt = "Field doesn't exist")] diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs index 6e6db9139b..f3d669a681 100644 --- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -60,6 +60,7 @@ pub enum ErrorCode { GridIdIsEmpty = 410, BlockIdIsEmpty = 420, RowIdIsEmpty = 430, + OptionIdIsEmpty = 431, FieldIdIsEmpty = 440, FieldDoesNotExist = 441, SelectOptionNameIsEmpty = 442, @@ -109,6 +110,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode { 410 => ::std::option::Option::Some(ErrorCode::GridIdIsEmpty), 420 => ::std::option::Option::Some(ErrorCode::BlockIdIsEmpty), 430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty), + 431 => ::std::option::Option::Some(ErrorCode::OptionIdIsEmpty), 440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty), 441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist), 442 => ::std::option::Option::Some(ErrorCode::SelectOptionNameIsEmpty), @@ -155,6 +157,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode { ErrorCode::GridIdIsEmpty, ErrorCode::BlockIdIsEmpty, ErrorCode::RowIdIsEmpty, + ErrorCode::OptionIdIsEmpty, ErrorCode::FieldIdIsEmpty, ErrorCode::FieldDoesNotExist, ErrorCode::SelectOptionNameIsEmpty, @@ -188,7 +191,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ncode.proto*\x9e\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\ncode.proto*\xb4\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\ \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\ @@ -207,10 +210,11 @@ static file_descriptor_proto_data: &'static [u8] = b"\ IsEmpty\x10\xb6\x02\x12\x12\n\rUserIdInvalid\x10\xb7\x02\x12\x11\n\x0cUs\ erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\ ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\ - \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\ - \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1c\n\x17SelectOptionNam\ - eIsEmpty\x10\xba\x03\x12\x1a\n\x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\ - \x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\ + \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x14\n\x0fOptionIdIsEmpty\x10\xaf\x03\ + \x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\x12\x16\n\x11FieldDoesNotExist\ + \x10\xb9\x03\x12\x1c\n\x17SelectOptionNameIsEmpty\x10\xba\x03\x12\x1a\n\ + \x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\ + \x03b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto index d435d558dc..8ea2941815 100644 --- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto +++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto @@ -36,6 +36,7 @@ enum ErrorCode { GridIdIsEmpty = 410; BlockIdIsEmpty = 420; RowIdIsEmpty = 430; + OptionIdIsEmpty = 431; FieldIdIsEmpty = 440; FieldDoesNotExist = 441; SelectOptionNameIsEmpty = 442; 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 1dd2220f13..c92a3b23a4 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -92,6 +92,12 @@ pub struct FieldOrder { pub field_id: String, } +impl std::convert::Into> for FieldOrder { + fn into(self) -> Vec { + vec![self] + } +} + impl std::convert::From<&FieldMeta> for FieldOrder { fn from(field_meta: &FieldMeta) -> Self { Self { diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 9be0faa99d..de8ac320f3 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -393,14 +393,12 @@ pub struct CellMetaChangeset { impl std::convert::From for RowMetaChangeset { fn from(changeset: CellMetaChangeset) -> Self { let mut cell_by_field_id = HashMap::with_capacity(1); - if let Some(data) = changeset.data { - let field_id = changeset.field_id; - let cell_meta = CellMeta { - field_id: field_id.clone(), - data, - }; - cell_by_field_id.insert(field_id, cell_meta); - } + let field_id = changeset.field_id; + let cell_meta = CellMeta { + field_id: field_id.clone(), + data: changeset.data.unwrap_or("".to_owned()), + }; + cell_by_field_id.insert(field_id, cell_meta); RowMetaChangeset { row_id: changeset.row_id, diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 513a1ea9ec..f022488f0a 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -42,6 +42,7 @@ impl GridMetaPad { Self::from_delta(grid_delta) } + #[tracing::instrument(level = "debug", skip_all, err)] pub fn create_field( &mut self, new_field_meta: FieldMeta, @@ -186,7 +187,7 @@ impl GridMetaPad { self.grid_meta.fields.iter().map(FieldOrder::from).collect() } - pub fn get_field_metas(&self, field_orders: Option) -> CollaborateResult> { + pub fn get_field_metas(&self, field_orders: Option>) -> CollaborateResult> { match field_orders { None => Ok(self.grid_meta.fields.clone()), Some(field_orders) => { From 2607822412de6aeadb8ac5ce0aae6971b25df948 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 5 Apr 2022 21:25:59 +0800 Subject: [PATCH 39/47] chore: show selection --- .../grid/cell_bloc/cell_service.dart | 43 ++ .../grid/cell_bloc/selection_cell_bloc.dart | 36 +- .../grid/cell_bloc/selection_editor_bloc.dart | 8 +- .../type_option/type_option_service.dart | 6 +- .../application/grid/row/row_service.dart | 1 - .../cell/selection_cell/selection_cell.dart | 2 +- .../cell/selection_cell/selection_editor.dart | 19 +- .../dart_event/flowy-grid/dart_event.dart | 10 +- .../flowy-grid-data-model/grid.pb.dart | 170 ++--- .../flowy-grid-data-model/grid.pbjson.dart | 29 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 4 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 4 +- .../flowy-grid/selection_type_option.pb.dart | 42 +- .../selection_type_option.pbjson.dart | 7 +- .../rust-lib/flowy-grid/src/event_handler.rs | 66 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 20 +- frontend/rust-lib/flowy-grid/src/manager.rs | 1 - .../src/protobuf/model/event_map.rs | 12 +- .../protobuf/model/selection_type_option.rs | 79 ++- .../src/protobuf/proto/event_map.proto | 2 +- .../proto/selection_type_option.proto | 5 +- .../src/services/block_meta_editor.rs | 8 +- .../type_options/checkbox_type_option.rs | 29 +- .../field/type_options/date_type_option.rs | 39 +- .../field/type_options/number_type_option.rs | 57 +- .../type_options/selection_type_option.rs | 194 ++++-- .../field/type_options/text_type_option.rs | 24 +- .../flowy-grid/src/services/grid_editor.rs | 102 ++- .../src/services/persistence/block_index.rs | 1 - .../flowy-grid/src/services/persistence/kv.rs | 1 - .../src/services/row/cell_data_operation.rs | 81 ++- .../src/services/row/row_builder.rs | 6 +- .../flowy-grid/src/services/row/row_loader.rs | 8 +- .../flowy-grid/tests/grid/grid_test.rs | 16 +- .../src/entities/grid.rs | 72 +- .../src/protobuf/model/grid.rs | 619 +++++++++--------- .../src/protobuf/proto/grid.proto | 11 +- .../src/client_grid/grid_meta_pad.rs | 1 - 38 files changed, 1080 insertions(+), 755 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index e1af022d95..f7a0247a98 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -1,11 +1,54 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; class CellService { CellService(); + Future> addSelectOpiton({ + required String gridId, + required String fieldId, + required String rowId, + required String optionId, + }) { + final payload = SelectOptionChangesetPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId + ..insertOptionId = optionId; + return GridEventApplySelectOptionChangeset(payload).send(); + } + + Future> getSelectOpitonContext({ + required String gridId, + required String fieldId, + required String rowId, + }) { + final payload = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + + return GridEventGetSelectOptions(payload).send(); + } + + Future> removeSelectOpiton({ + required String gridId, + required String fieldId, + required String rowId, + required String optionId, + }) { + final payload = SelectOptionChangesetPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId + ..deleteOptionId = optionId; + return GridEventApplySelectOptionChangeset(payload).send(); + } + Future> updateCell({ required String gridId, required String fieldId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 2cde7c6a96..1b38376e86 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -11,12 +11,13 @@ import 'cell_service.dart'; part 'selection_cell_bloc.freezed.dart'; class SelectionCellBloc extends Bloc { - final CellService service; + final CellService _service; SelectionCellBloc({ - required this.service, + required CellService service, required CellData cellData, - }) : super(SelectionCellState.initial(cellData)) { + }) : _service = service, + super(SelectionCellState.initial(cellData)) { on( (event, emit) async { await event.map( @@ -37,30 +38,17 @@ class SelectionCellBloc extends Bloc { } void _loadOptions() async { - final result = await FieldContextLoaderAdaptor( + final result = await _service.getSelectOpitonContext( gridId: state.cellData.gridId, - field: state.cellData.field, - ).load(); + fieldId: state.cellData.field.id, + rowId: state.cellData.rowId, + ); result.fold( - (context) { - List options = []; - switch (state.cellData.field.fieldType) { - case FieldType.MultiSelect: - options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options); - break; - case FieldType.SingleSelect: - options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options); - break; - default: - Log.error("Invalid field type, expect single select or multiple select"); - break; - } - - final ids = state.cellData.cell?.content.split(','); - final selectedOptions = ids?.map((id) => options.firstWhere((option) => option.id == id)).toList() ?? []; - add(SelectionCellEvent.didReceiveOptions(options, selectedOptions)); - }, + (selectOptionContext) => add(SelectionCellEvent.didReceiveOptions( + selectOptionContext.options, + selectOptionContext.selectOptions, + )), (err) => Log.error(err), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index 5ce68105ea..671dc7ae8a 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -41,15 +41,15 @@ class SelectOptionEditorBloc extends Bloc null, (err) => Log.error(err)); }, selectOption: (_SelectOption value) { - _cellService.updateCell( + _cellService.addSelectOpiton( gridId: state.gridId, - fieldId: state.fieldId, + fieldId: state.field.id, rowId: state.rowId, - data: data, + optionId: value.optionId, ); }, ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart index 8ab3460b82..9121ded71b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart @@ -10,8 +10,10 @@ class TypeOptionService { required this.fieldId, }); - Future> createOption(String name) { - final payload = CreateSelectOptionPayload.create()..optionName = name; + Future> createOption(String name, {bool selected = false}) { + final payload = CreateSelectOptionPayload.create() + ..optionName = name + ..selected = selected; return GridEventCreateSelectOption(payload).send(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index a65cb81b29..1b3f9e87ec 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -22,7 +22,6 @@ class RowService { Future> getRow() { QueryRowPayload payload = QueryRowPayload.create() ..gridId = gridId - ..blockId = blockId ..rowId = rowId; return GridEventGetRow(payload).send(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 3fe1b19c14..33a935d37e 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -39,7 +39,7 @@ class _SingleSelectCellState extends State { return SizedBox.expand( child: InkWell( onTap: () { - SelectionEditor.show(context, state.cellData, state.options, state.selectedOptions); + SelectOptionEditor.show(context, state.cellData, state.options, state.selectedOptions); }, child: Row(children: children), ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 0c8d207a4b..d10a5a8cf8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -21,12 +21,12 @@ import 'extension.dart'; const double _editorPannelWidth = 300; -class SelectionEditor extends StatelessWidget { +class SelectOptionEditor extends StatelessWidget { final CellData cellData; final List options; final List selectedOptions; - const SelectionEditor({ + const SelectOptionEditor({ required this.cellData, required this.options, required this.selectedOptions, @@ -34,15 +34,14 @@ class SelectionEditor extends StatelessWidget { }) : super(key: key); static String identifier() { - return (SelectionEditor).toString(); + return (SelectOptionEditor).toString(); } @override Widget build(BuildContext context) { return BlocProvider( create: (context) => SelectOptionEditorBloc( - gridId: cellData.gridId, - field: cellData.field, + cellData: cellData, options: options, selectedOptions: selectedOptions, ), @@ -68,8 +67,8 @@ class SelectionEditor extends StatelessWidget { List options, List selectedOptions, ) { - SelectionEditor.hide(context); - final editor = SelectionEditor( + SelectOptionEditor.hide(context); + final editor = SelectOptionEditor( cellData: cellData, options: options, selectedOptions: selectedOptions, @@ -81,7 +80,7 @@ class SelectionEditor extends StatelessWidget { child: SizedBox(width: _editorPannelWidth, child: editor), constraints: BoxConstraints.loose(const Size(_editorPannelWidth, 300)), ), - identifier: SelectionEditor.identifier(), + identifier: SelectOptionEditor.identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomWithCenterAligned, ); @@ -177,7 +176,9 @@ class _SelectOptionCell extends StatelessWidget { return SizedBox( height: GridSize.typeOptionItemHeight, child: InkWell( - onTap: () {}, + onTap: () { + context.read().add(SelectOptionEditorEvent.selectOption(option.id)); + }, child: FlowyHover( config: HoverDisplayConfig(hoverColor: theme.hover), builder: (_, onHover) { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index a709d06fe8..2a23cfad4a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -172,7 +172,7 @@ class GridEventCreateSelectOption { } class GridEventGetSelectOptions { - FieldIdentifierPayload request; + CellIdentifierPayload request; GridEventGetSelectOptions(this.request); Future> send() { @@ -239,13 +239,13 @@ class GridEventUpdateCell { } } -class GridEventInsertSelectOption { - InsertSelectOptionPayload request; - GridEventInsertSelectOption(this.request); +class GridEventApplySelectOptionChangeset { + SelectOptionChangesetPayload request; + GridEventApplySelectOptionChangeset(this.request); Future> send() { final request = FFIRequest.create() - ..event = GridEvent.InsertSelectOption.toString() + ..event = GridEvent.ApplySelectOptionChangeset.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) 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 7fcee422d7..ab195308c6 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 @@ -266,67 +266,6 @@ class FieldIdentifierPayload extends $pb.GeneratedMessage { void clearGridId() => clearField(2); } -class FieldIdentifierParams extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierParams', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..hasRequiredFields = false - ; - - FieldIdentifierParams._() : super(); - factory FieldIdentifierParams({ - $core.String? fieldId, - $core.String? gridId, - }) { - final _result = create(); - if (fieldId != null) { - _result.fieldId = fieldId; - } - if (gridId != null) { - _result.gridId = gridId; - } - return _result; - } - factory FieldIdentifierParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory FieldIdentifierParams.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') - FieldIdentifierParams clone() => FieldIdentifierParams()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - FieldIdentifierParams copyWith(void Function(FieldIdentifierParams) updates) => super.copyWith((message) => updates(message as FieldIdentifierParams)) as FieldIdentifierParams; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static FieldIdentifierParams create() => FieldIdentifierParams._(); - FieldIdentifierParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static FieldIdentifierParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static FieldIdentifierParams? _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.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); -} - 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') @@ -1085,6 +1024,81 @@ class Cell extends $pb.GeneratedMessage { void clearContent() => clearField(2); } +class CellIdentifierPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellIdentifierPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..hasRequiredFields = false + ; + + CellIdentifierPayload._() : super(); + factory CellIdentifierPayload({ + $core.String? gridId, + $core.String? fieldId, + $core.String? rowId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (rowId != null) { + _result.rowId = rowId; + } + return _result; + } + factory CellIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CellIdentifierPayload.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') + CellIdentifierPayload clone() => CellIdentifierPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CellIdentifierPayload copyWith(void Function(CellIdentifierPayload) updates) => super.copyWith((message) => updates(message as CellIdentifierPayload)) as CellIdentifierPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CellIdentifierPayload create() => CellIdentifierPayload._(); + CellIdentifierPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CellIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CellIdentifierPayload? _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 fieldId => $_getSZ(1); + @$pb.TagNumber(2) + set fieldId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasFieldId() => $_has(1); + @$pb.TagNumber(2) + void clearFieldId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get rowId => $_getSZ(2); + @$pb.TagNumber(3) + set rowId($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasRowId() => $_has(2); + @$pb.TagNumber(3) + void clearRowId() => clearField(3); +} + 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) @@ -1566,7 +1580,6 @@ class QueryGridBlocksPayload extends $pb.GeneratedMessage { class QueryRowPayload extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryRowPayload', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') ..hasRequiredFields = false ; @@ -1574,16 +1587,12 @@ class QueryRowPayload extends $pb.GeneratedMessage { QueryRowPayload._() : super(); factory QueryRowPayload({ $core.String? gridId, - $core.String? blockId, $core.String? rowId, }) { final _result = create(); if (gridId != null) { _result.gridId = gridId; } - if (blockId != null) { - _result.blockId = blockId; - } if (rowId != null) { _result.rowId = rowId; } @@ -1619,21 +1628,12 @@ class QueryRowPayload extends $pb.GeneratedMessage { @$pb.TagNumber(1) void clearGridId() => clearField(1); - @$pb.TagNumber(2) - $core.String get blockId => $_getSZ(1); - @$pb.TagNumber(2) - set blockId($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasBlockId() => $_has(1); - @$pb.TagNumber(2) - void clearBlockId() => clearField(2); - @$pb.TagNumber(3) - $core.String get rowId => $_getSZ(2); + $core.String get rowId => $_getSZ(1); @$pb.TagNumber(3) - set rowId($core.String v) { $_setString(2, v); } + set rowId($core.String v) { $_setString(1, v); } @$pb.TagNumber(3) - $core.bool hasRowId() => $_has(2); + $core.bool hasRowId() => $_has(1); @$pb.TagNumber(3) void clearRowId() => clearField(3); } @@ -1641,17 +1641,22 @@ class QueryRowPayload extends $pb.GeneratedMessage { class CreateSelectOptionPayload extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateSelectOptionPayload', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'optionName') + ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selected') ..hasRequiredFields = false ; CreateSelectOptionPayload._() : super(); factory CreateSelectOptionPayload({ $core.String? optionName, + $core.bool? selected, }) { final _result = create(); if (optionName != null) { _result.optionName = optionName; } + if (selected != null) { + _result.selected = selected; + } return _result; } factory CreateSelectOptionPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -1683,5 +1688,14 @@ class CreateSelectOptionPayload extends $pb.GeneratedMessage { $core.bool hasOptionName() => $_has(0); @$pb.TagNumber(1) void clearOptionName() => clearField(1); + + @$pb.TagNumber(2) + $core.bool get selected => $_getBF(1); + @$pb.TagNumber(2) + set selected($core.bool v) { $_setBool(1, v); } + @$pb.TagNumber(2) + $core.bool hasSelected() => $_has(1); + @$pb.TagNumber(2) + void clearSelected() => clearField(2); } 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 596c7f6fc1..c51a224a9e 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 @@ -47,17 +47,6 @@ const FieldIdentifierPayload$json = const { /// Descriptor for `FieldIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldIdentifierPayloadDescriptor = $convert.base64Decode('ChZGaWVsZElkZW50aWZpZXJQYXlsb2FkEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZA=='); -@$core.Deprecated('Use fieldIdentifierParamsDescriptor instead') -const FieldIdentifierParams$json = const { - '1': 'FieldIdentifierParams', - '2': const [ - const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, - ], -}; - -/// Descriptor for `FieldIdentifierParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldIdentifierParamsDescriptor = $convert.base64Decode('ChVGaWVsZElkZW50aWZpZXJQYXJhbXMSGQoIZmllbGRfaWQYASABKAlSB2ZpZWxkSWQSFwoHZ3JpZF9pZBgCIAEoCVIGZ3JpZElk'); @$core.Deprecated('Use fieldOrderDescriptor instead') const FieldOrder$json = const { '1': 'FieldOrder', @@ -214,6 +203,18 @@ const Cell$json = const { /// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhgKB2NvbnRlbnQYAiABKAlSB2NvbnRlbnQ='); +@$core.Deprecated('Use cellIdentifierPayloadDescriptor instead') +const CellIdentifierPayload$json = const { + '1': 'CellIdentifierPayload', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, + ], +}; + +/// Descriptor for `CellIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List cellIdentifierPayloadDescriptor = $convert.base64Decode('ChVDZWxsSWRlbnRpZmllclBheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); @$core.Deprecated('Use repeatedCellDescriptor instead') const RepeatedCell$json = const { '1': 'RepeatedCell', @@ -311,20 +312,20 @@ const QueryRowPayload$json = const { '1': 'QueryRowPayload', '2': const [ const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, - const {'1': 'block_id', '3': 2, '4': 1, '5': 9, '10': 'blockId'}, const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, ], }; /// Descriptor for `QueryRowPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List queryRowPayloadDescriptor = $convert.base64Decode('Cg9RdWVyeVJvd1BheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGJsb2NrX2lkGAIgASgJUgdibG9ja0lkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); +final $typed_data.Uint8List queryRowPayloadDescriptor = $convert.base64Decode('Cg9RdWVyeVJvd1BheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); @$core.Deprecated('Use createSelectOptionPayloadDescriptor instead') const CreateSelectOptionPayload$json = const { '1': 'CreateSelectOptionPayload', '2': const [ const {'1': 'option_name', '3': 1, '4': 1, '5': 9, '10': 'optionName'}, + const {'1': 'selected', '3': 2, '4': 1, '5': 8, '10': 'selected'}, ], }; /// Descriptor for `CreateSelectOptionPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEh8KC29wdGlvbl9uYW1lGAEgASgJUgpvcHRpb25OYW1l'); +final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEh8KC29wdGlvbl9uYW1lGAEgASgJUgpvcHRpb25OYW1lEhoKCHNlbGVjdGVkGAIgASgIUghzZWxlY3RlZA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 2de16d922c..4c8cff633b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -24,7 +24,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); - static const GridEvent InsertSelectOption = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InsertSelectOption'); + static const GridEvent ApplySelectOptionChangeset = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset'); static const $core.List values = [ GetGridData, @@ -41,7 +41,7 @@ class GridEvent extends $pb.ProtobufEnum { CreateRow, GetRow, UpdateCell, - InsertSelectOption, + ApplySelectOptionChangeset, ]; static final $core.Map<$core.int, GridEvent> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 56b593c688..017dc4b1aa 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -26,9 +26,9 @@ const GridEvent$json = const { const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, const {'1': 'UpdateCell', '2': 70}, - const {'1': 'InsertSelectOption', '2': 71}, + const {'1': 'ApplySelectOptionChangeset', '2': 71}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEhQKEEdldFNlbGVjdE9wdGlvbnMQHxINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxIOCgpVcGRhdGVDZWxsEEYSFgoSSW5zZXJ0U2VsZWN0T3B0aW9uEEc='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEhQKEEdldFNlbGVjdE9wdGlvbnMQHxINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxIOCgpVcGRhdGVDZWxsEEYSHgoaQXBwbHlTZWxlY3RPcHRpb25DaGFuZ2VzZXQQRw=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart index 2b9fc8a5ce..350806f275 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart @@ -210,20 +210,21 @@ enum SelectOptionChangesetPayload_OneOfDeleteOptionId { class SelectOptionChangesetPayload extends $pb.GeneratedMessage { static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfInsertOptionId> _SelectOptionChangesetPayload_OneOfInsertOptionIdByTag = { - 3 : SelectOptionChangesetPayload_OneOfInsertOptionId.insertOptionId, + 4 : SelectOptionChangesetPayload_OneOfInsertOptionId.insertOptionId, 0 : SelectOptionChangesetPayload_OneOfInsertOptionId.notSet }; static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfDeleteOptionId> _SelectOptionChangesetPayload_OneOfDeleteOptionIdByTag = { - 4 : SelectOptionChangesetPayload_OneOfDeleteOptionId.deleteOptionId, + 5 : SelectOptionChangesetPayload_OneOfDeleteOptionId.deleteOptionId, 0 : SelectOptionChangesetPayload_OneOfDeleteOptionId.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionChangesetPayload', createEmptyInstance: create) - ..oo(0, [3]) - ..oo(1, [4]) + ..oo(0, [4]) + ..oo(1, [5]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOptionId') - ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOptionId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOptionId') + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOptionId') ..hasRequiredFields = false ; @@ -231,6 +232,7 @@ class SelectOptionChangesetPayload extends $pb.GeneratedMessage { factory SelectOptionChangesetPayload({ $core.String? gridId, $core.String? rowId, + $core.String? fieldId, $core.String? insertOptionId, $core.String? deleteOptionId, }) { @@ -241,6 +243,9 @@ class SelectOptionChangesetPayload extends $pb.GeneratedMessage { if (rowId != null) { _result.rowId = rowId; } + if (fieldId != null) { + _result.fieldId = fieldId; + } if (insertOptionId != null) { _result.insertOptionId = insertOptionId; } @@ -295,22 +300,31 @@ class SelectOptionChangesetPayload extends $pb.GeneratedMessage { void clearRowId() => clearField(2); @$pb.TagNumber(3) - $core.String get insertOptionId => $_getSZ(2); + $core.String get fieldId => $_getSZ(2); @$pb.TagNumber(3) - set insertOptionId($core.String v) { $_setString(2, v); } + set fieldId($core.String v) { $_setString(2, v); } @$pb.TagNumber(3) - $core.bool hasInsertOptionId() => $_has(2); + $core.bool hasFieldId() => $_has(2); @$pb.TagNumber(3) - void clearInsertOptionId() => clearField(3); + void clearFieldId() => clearField(3); @$pb.TagNumber(4) - $core.String get deleteOptionId => $_getSZ(3); + $core.String get insertOptionId => $_getSZ(3); @$pb.TagNumber(4) - set deleteOptionId($core.String v) { $_setString(3, v); } + set insertOptionId($core.String v) { $_setString(3, v); } @$pb.TagNumber(4) - $core.bool hasDeleteOptionId() => $_has(3); + $core.bool hasInsertOptionId() => $_has(3); @$pb.TagNumber(4) - void clearDeleteOptionId() => clearField(4); + void clearInsertOptionId() => clearField(4); + + @$pb.TagNumber(5) + $core.String get deleteOptionId => $_getSZ(4); + @$pb.TagNumber(5) + set deleteOptionId($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasDeleteOptionId() => $_has(4); + @$pb.TagNumber(5) + void clearDeleteOptionId() => clearField(5); } class SelectOptionContext extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart index 4002db9a33..04c44a3004 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart @@ -66,8 +66,9 @@ const SelectOptionChangesetPayload$json = const { '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': 'insert_option_id', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'insertOptionId'}, - const {'1': 'delete_option_id', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'deleteOptionId'}, + const {'1': 'field_id', '3': 3, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'insert_option_id', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'insertOptionId'}, + const {'1': 'delete_option_id', '3': 5, '4': 1, '5': 9, '9': 1, '10': 'deleteOptionId'}, ], '8': const [ const {'1': 'one_of_insert_option_id'}, @@ -76,7 +77,7 @@ const SelectOptionChangesetPayload$json = const { }; /// Descriptor for `SelectOptionChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionChangesetPayloadDescriptor = $convert.base64Decode('ChxTZWxlY3RPcHRpb25DaGFuZ2VzZXRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEioKEGluc2VydF9vcHRpb25faWQYAyABKAlIAFIOaW5zZXJ0T3B0aW9uSWQSKgoQZGVsZXRlX29wdGlvbl9pZBgEIAEoCUgBUg5kZWxldGVPcHRpb25JZEIZChdvbmVfb2ZfaW5zZXJ0X29wdGlvbl9pZEIZChdvbmVfb2ZfZGVsZXRlX29wdGlvbl9pZA=='); +final $typed_data.Uint8List selectOptionChangesetPayloadDescriptor = $convert.base64Decode('ChxTZWxlY3RPcHRpb25DaGFuZ2VzZXRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElkEioKEGluc2VydF9vcHRpb25faWQYBCABKAlIAFIOaW5zZXJ0T3B0aW9uSWQSKgoQZGVsZXRlX29wdGlvbl9pZBgFIAEoCUgBUg5kZWxldGVPcHRpb25JZEIZChdvbmVfb2ZfaW5zZXJ0X29wdGlvbl9pZEIZChdvbmVfb2ZfZGVsZXRlX29wdGlvbl9pZA=='); @$core.Deprecated('Use selectOptionContextDescriptor instead') const SelectOptionContext$json = const { '1': 'SelectOptionContext', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index dd7675e803..62cbb4abec 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,7 +1,7 @@ use crate::manager::GridManager; use crate::services::field::{ - default_type_option_builder_from_type, type_option_builder_from_json_str, SelectOption, - SelectOptionChangesetParams, SelectOptionChangesetPayload, + default_type_option_builder_from_type, type_option_builder_from_json_str, MultiSelectTypeOption, SelectOption, + SelectOptionChangesetParams, SelectOptionChangesetPayload, SelectOptionContext, SingleSelectTypeOption, }; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; @@ -93,7 +93,10 @@ pub(crate) async fn switch_to_field_handler( .switch_to_field_type(¶ms.field_id, ¶ms.field_type) .await?; - let field_meta = editor.get_field(¶ms.field_id).await?; + let field_meta = editor + .get_field_metas(Some(vec![params.field_id.as_str()])) + .await? + .pop(); let edit_context = make_field_edit_context( ¶ms.grid_id, Some(params.field_id), @@ -124,6 +127,44 @@ pub(crate) async fn create_select_option_handler( data_result(SelectOption::new(¶ms.option_name)) } +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn get_select_option_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: CellIdentifierParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + match editor + .get_field_metas(Some(vec![params.field_id.as_str()])) + .await? + .pop() + { + None => { + tracing::error!("Can't find the corresponding field with id: {}", params.field_id); + data_result(SelectOptionContext::default()) + } + Some(field_meta) => { + let cell_meta = editor.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?; + match field_meta.field_type { + FieldType::SingleSelect => { + let type_option = SingleSelectTypeOption::from(&field_meta); + let select_option_context = type_option.select_option_context(&cell_meta); + data_result(select_option_context) + } + FieldType::MultiSelect => { + let type_option = MultiSelectTypeOption::from(&field_meta); + let select_option_context = type_option.select_option_context(&cell_meta); + data_result(select_option_context) + } + ty => { + tracing::error!("Unsupported field type: {:?} for this handler", ty); + data_result(SelectOptionContext::default()) + } + } + } + } +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_field_context_handler( data: Data, @@ -164,13 +205,13 @@ async fn get_or_create_field_meta( field_type: &FieldType, editor: Arc, ) -> FlowyResult { - if field_id.is_some() { - if let Some(field_meta) = editor.get_field(field_id.as_ref().unwrap()).await? { - return Ok(field_meta); - } + match field_id { + None => editor.create_next_field_meta(field_type).await, + Some(field_id) => match editor.get_field_metas(Some(vec![field_id.as_str()])).await?.pop() { + None => editor.create_next_field_meta(field_type).await, + Some(field_meta) => Ok(field_meta), + }, } - - editor.create_next_field_meta(field_type).await } #[tracing::instrument(level = "debug", skip(data, manager), err)] @@ -180,7 +221,7 @@ pub(crate) async fn get_row_handler( ) -> DataResult { let params: QueryRowParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - match editor.get_row(¶ms.block_id, ¶ms.row_id).await? { + match editor.get_row(¶ms.row_id).await? { None => Err(FlowyError::record_not_found().context("Can not find the row")), Some(row) => data_result(row), } @@ -209,12 +250,13 @@ pub(crate) async fn update_cell_handler( } #[tracing::instrument(level = "debug", skip_all, err)] -pub(crate) async fn insert_select_option_handler( +pub(crate) async fn apply_select_option_changeset_handler( data: Data, manager: AppData>, ) -> Result<(), FlowyError> { let params: SelectOptionChangesetParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.insert_select_option(params).await?; + let changeset: CellMetaChangeset = params.into(); + let _ = editor.update_cell(changeset).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 64c7c70e56..2af4b28e35 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -10,18 +10,26 @@ pub fn create(grid_manager: Arc) -> Module { module = module .event(GridEvent::GetGridData, get_grid_data_handler) .event(GridEvent::GetGridBlocks, get_grid_blocks_handler) + // Field .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) .event(GridEvent::CreateField, create_field_handler) .event(GridEvent::DeleteField, delete_field_handler) .event(GridEvent::SwitchToField, switch_to_field_handler) .event(GridEvent::DuplicateField, duplicate_field_handler) - .event(GridEvent::GetEditFieldContext, get_field_context_handler) - .event(GridEvent::CreateSelectOption, create_select_option_handler) + // Row .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) + // Cell .event(GridEvent::UpdateCell, update_cell_handler) - .event(GridEvent::InsertSelectOption, insert_select_option_handler); + // SelectOption + .event(GridEvent::CreateSelectOption, create_select_option_handler) + .event(GridEvent::GetSelectOptions, get_select_option_handler) + .event( + GridEvent::ApplySelectOptionChangeset, + apply_select_option_changeset_handler, + ) + .event(GridEvent::GetEditFieldContext, get_field_context_handler); module } @@ -59,7 +67,7 @@ pub enum GridEvent { #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] CreateSelectOption = 30, - #[event(input = "FieldIdentifierPayload", output = "SelectOptionContext")] + #[event(input = "CellIdentifierPayload", output = "SelectOptionContext")] GetSelectOptions = 31, #[event(input = "CreateRowPayload", output = "Row")] @@ -71,6 +79,6 @@ pub enum GridEvent { #[event(input = "CellMetaChangeset")] UpdateCell = 70, - #[event(input = "InsertSelectOptionPayload")] - InsertSelectOption = 71, + #[event(input = "SelectOptionChangesetPayload")] + ApplySelectOptionChangeset = 71, } diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 686f539b74..d82b2950da 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -12,7 +12,6 @@ use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket}; use flowy_sync::client_grid::{make_block_meta_delta, make_grid_delta}; use flowy_sync::entities::revision::{RepeatedRevision, Revision}; use std::sync::Arc; -use tokio::sync::RwLock; pub trait GridUser: Send + Sync { fn user_id(&self) -> Result; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index ae1dfe161d..72a0601391 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -39,7 +39,7 @@ pub enum GridEvent { CreateRow = 50, GetRow = 51, UpdateCell = 70, - InsertSelectOption = 71, + ApplySelectOptionChangeset = 71, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -63,7 +63,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), 70 => ::std::option::Option::Some(GridEvent::UpdateCell), - 71 => ::std::option::Option::Some(GridEvent::InsertSelectOption), + 71 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset), _ => ::std::option::Option::None } } @@ -84,7 +84,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, - GridEvent::InsertSelectOption, + GridEvent::ApplySelectOptionChangeset, ]; values } @@ -113,14 +113,14 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xa2\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xaa\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x16\n\x12Creat\ eSelectOption\x10\x1e\x12\x14\n\x10GetSelectOptions\x10\x1f\x12\r\n\tCre\ - ateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\x16\n\ - \x12InsertSelectOption\x10Gb\x06proto3\ + ateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\x1e\n\ + \x1aApplySelectOptionChangeset\x10Gb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs index ba0e1bebe9..7a65da1171 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs @@ -662,6 +662,7 @@ pub struct SelectOptionChangesetPayload { // message fields pub grid_id: ::std::string::String, pub row_id: ::std::string::String, + pub field_id: ::std::string::String, // message oneof groups pub one_of_insert_option_id: ::std::option::Option, pub one_of_delete_option_id: ::std::option::Option, @@ -743,7 +744,33 @@ impl SelectOptionChangesetPayload { ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) } - // string insert_option_id = 3; + // string field_id = 3; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string insert_option_id = 4; pub fn get_insert_option_id(&self) -> &str { @@ -792,7 +819,7 @@ impl SelectOptionChangesetPayload { } } - // string delete_option_id = 4; + // string delete_option_id = 5; pub fn get_delete_option_id(&self) -> &str { @@ -858,12 +885,15 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; }, 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 4 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); }, - 4 => { + 5 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } @@ -887,17 +917,20 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { if !self.row_id.is_empty() { my_size += ::protobuf::rt::string_size(2, &self.row_id); } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.field_id); + } if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { match v { &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { - my_size += ::protobuf::rt::string_size(3, &v); + my_size += ::protobuf::rt::string_size(4, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { match v { &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { - my_size += ::protobuf::rt::string_size(4, &v); + my_size += ::protobuf::rt::string_size(5, &v); }, }; } @@ -913,17 +946,20 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { if !self.row_id.is_empty() { os.write_string(2, &self.row_id)?; } + if !self.field_id.is_empty() { + os.write_string(3, &self.field_id)?; + } if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { match v { &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { - os.write_string(3, v)?; + os.write_string(4, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { match v { &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { - os.write_string(4, v)?; + os.write_string(5, v)?; }, }; } @@ -975,6 +1011,11 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { |m: &SelectOptionChangesetPayload| { &m.row_id }, |m: &mut SelectOptionChangesetPayload| { &mut m.row_id }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &SelectOptionChangesetPayload| { &m.field_id }, + |m: &mut SelectOptionChangesetPayload| { &mut m.field_id }, + )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "insert_option_id", SelectOptionChangesetPayload::has_insert_option_id, @@ -1003,6 +1044,7 @@ impl ::protobuf::Clear for SelectOptionChangesetPayload { fn clear(&mut self) { self.grid_id.clear(); self.row_id.clear(); + self.field_id.clear(); self.one_of_insert_option_id = ::std::option::Option::None; self.one_of_delete_option_id = ::std::option::Option::None; self.unknown_fields.clear(); @@ -1315,18 +1357,19 @@ static file_descriptor_proto_data: &'static [u8] = b"\ s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"\\\n\x0cS\ electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ \x18\x02\x20\x01(\tR\x04name\x12(\n\x05color\x18\x03\x20\x01(\x0e2\x12.S\ - electOptionColorR\x05color\"\xdc\x01\n\x1cSelectOptionChangesetPayload\ + electOptionColorR\x05color\"\xf7\x01\n\x1cSelectOptionChangesetPayload\ \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\ - \x18\x02\x20\x01(\tR\x05rowId\x12*\n\x10insert_option_id\x18\x03\x20\x01\ - (\tH\0R\x0einsertOptionId\x12*\n\x10delete_option_id\x18\x04\x20\x01(\tH\ - \x01R\x0edeleteOptionIdB\x19\n\x17one_of_insert_option_idB\x19\n\x17one_\ - of_delete_option_id\"t\n\x13SelectOptionContext\x12'\n\x07options\x18\ - \x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x124\n\x0eselect_options\ - \x18\x02\x20\x03(\x0b2\r.SelectOptionR\rselectOptions*y\n\x11SelectOptio\ - nColor\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightP\ - ink\x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\ - \n\x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\ - \x12\x08\n\x04Blue\x10\x08b\x06proto3\ + \x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\ + \x07fieldId\x12*\n\x10insert_option_id\x18\x04\x20\x01(\tH\0R\x0einsertO\ + ptionId\x12*\n\x10delete_option_id\x18\x05\x20\x01(\tH\x01R\x0edeleteOpt\ + ionIdB\x19\n\x17one_of_insert_option_idB\x19\n\x17one_of_delete_option_i\ + d\"t\n\x13SelectOptionContext\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.\ + SelectOptionR\x07options\x124\n\x0eselect_options\x18\x02\x20\x03(\x0b2\ + \r.SelectOptionR\rselectOptions*y\n\x11SelectOptionColor\x12\n\n\x06Purp\ + le\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\x10\x02\x12\n\n\ + \x06Orange\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\n\x04Lime\x10\x05\ + \x12\t\n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\x12\x08\n\x04Blue\ + \x10\x08b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index 4703711cb3..b423fee748 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -15,5 +15,5 @@ enum GridEvent { CreateRow = 50; GetRow = 51; UpdateCell = 70; - InsertSelectOption = 71; + ApplySelectOptionChangeset = 71; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto index 37dc0a36c1..3431373504 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto @@ -16,8 +16,9 @@ message SelectOption { message SelectOptionChangesetPayload { string grid_id = 1; string row_id = 2; - oneof one_of_insert_option_id { string insert_option_id = 3; }; - oneof one_of_delete_option_id { string delete_option_id = 4; }; + string field_id = 3; + oneof one_of_insert_option_id { string insert_option_id = 4; }; + oneof one_of_delete_option_id { string delete_option_id = 5; }; } message SelectOptionContext { repeated SelectOption options = 1; 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 c5082a1c2e..abdf1d5cbe 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 @@ -22,9 +22,6 @@ use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; -type RowId = String; -type BlockId = String; - pub(crate) struct GridBlockMetaEditorManager { grid_id: String, user: Arc, @@ -145,6 +142,11 @@ impl GridBlockMetaEditorManager { for block_id in block_ids { let editor = self.get_editor(&block_id).await?; let row_metas = editor.get_row_metas(None).await?; + + row_metas.iter().for_each(|row| { + let _ = self.persistence.insert_or_update(&row.block_id, &row.id); + }); + snapshots.push(GridBlockSnapshot { block_id, row_metas }); } Ok(snapshots) diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index b91409c904..2afdadb2f4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,10 +1,10 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{CellDataOperation, TypeOptionCellData}; +use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -41,7 +41,7 @@ const YES: &str = "Yes"; const NO: &str = "No"; impl CellDataOperation for CheckboxTypeOption { - fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_text() || !type_option_cell_data.is_checkbox() { return String::new(); @@ -55,8 +55,13 @@ impl CellDataOperation for CheckboxTypeOption { String::new() } - fn serialize_cell_data(&self, data: &str) -> Result { - let s = match string_to_bool(data) { + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result { + let changeset = changeset.into(); + let s = match string_to_bool(&changeset) { true => YES, false => NO, }; @@ -89,16 +94,16 @@ mod tests { let type_option = CheckboxTypeOption::default(); let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); - assert_eq!(type_option.serialize_cell_data("true").unwrap(), "1".to_owned()); - assert_eq!(type_option.serialize_cell_data("1").unwrap(), "1".to_owned()); - assert_eq!(type_option.serialize_cell_data("yes").unwrap(), "1".to_owned()); + assert_eq!(type_option.apply_changeset("true").unwrap(), "1".to_owned()); + assert_eq!(type_option.apply_changeset("1").unwrap(), "1".to_owned()); + assert_eq!(type_option.apply_changeset("yes").unwrap(), "1".to_owned()); - assert_eq!(type_option.serialize_cell_data("false").unwrap(), "0".to_owned()); - assert_eq!(type_option.serialize_cell_data("no").unwrap(), "0".to_owned()); - assert_eq!(type_option.serialize_cell_data("123").unwrap(), "0".to_owned()); + assert_eq!(type_option.apply_changeset("false").unwrap(), "0".to_owned()); + assert_eq!(type_option.apply_changeset("no").unwrap(), "0".to_owned()); + assert_eq!(type_option.apply_changeset("123").unwrap(), "0".to_owned()); assert_eq!( - type_option.deserialize_cell_data("1".to_owned(), &field_meta), + type_option.decode_cell_data("1".to_owned(), &field_meta), "1".to_owned() ); } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 2c67c69fe5..6472b91bb7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,11 +1,11 @@ use crate::impl_type_option; -use crate::services::row::{CellDataOperation, TypeOptionCellData}; +use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -43,7 +43,7 @@ impl DateTypeOption { } impl CellDataOperation for DateTypeOption { - fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if !type_option_cell_data.is_date() { return String::new(); @@ -63,13 +63,18 @@ impl CellDataOperation for DateTypeOption { String::new() } - fn serialize_cell_data(&self, data: &str) -> Result { - if let Err(e) = data.parse::() { - tracing::error!("Parse {} to i64 failed: {}", data, e); + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result { + let changeset = changeset.into(); + if let Err(e) = changeset.parse::() { + tracing::error!("Parse {} to i64 failed: {}", changeset.to_string(), e); return Err(FlowyError::internal().context(e)); }; - Ok(TypeOptionCellData::new(data, self.field_type()).json()) + Ok(TypeOptionCellData::new(changeset, self.field_type()).json()) } } @@ -195,7 +200,7 @@ mod tests { let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); assert_eq!( "".to_owned(), - type_option.deserialize_cell_data("1e".to_owned(), &field_meta) + type_option.decode_cell_data("1e".to_owned(), &field_meta) ); } @@ -209,33 +214,33 @@ mod tests { DateFormat::Friendly => { assert_eq!( "Mar 14,2022 17:56".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); assert_eq!( "Mar 14,2022 17:56".to_owned(), - type_option.deserialize_cell_data(data("Mar 14,2022 17:56"), &field_meta) + type_option.decode_cell_data(data("Mar 14,2022 17:56"), &field_meta) ); } DateFormat::US => { assert_eq!( "2022/03/14 17:56".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); assert_eq!( "2022/03/14 17:56".to_owned(), - type_option.deserialize_cell_data(data("2022/03/14 17:56"), &field_meta) + type_option.decode_cell_data(data("2022/03/14 17:56"), &field_meta) ); } DateFormat::ISO => { assert_eq!( "2022-03-14 17:56".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); } DateFormat::Local => { assert_eq!( "2022/03/14 17:56".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); } } @@ -256,7 +261,7 @@ mod tests { ); assert_eq!( "Mar 14,2022 17:56".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); } TimeFormat::TwelveHour => { @@ -266,7 +271,7 @@ mod tests { ); assert_eq!( "Mar 14,2022 05:56:02 PM".to_owned(), - type_option.deserialize_cell_data(data("1647251762"), &field_meta) + type_option.decode_cell_data(data("1647251762"), &field_meta) ); } } @@ -277,7 +282,7 @@ mod tests { #[should_panic] fn date_description_invalid_data_test() { let type_option = DateTypeOption::default(); - type_option.serialize_cell_data("he").unwrap(); + type_option.apply_changeset("he").unwrap(); } fn data(s: &str) -> String { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 55ce729a7f..b0b5967a9d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -1,8 +1,8 @@ use crate::impl_type_option; -use crate::services::row::{CellDataOperation, TypeOptionCellData}; +use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellData}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use lazy_static::lazy_static; use rust_decimal::Decimal; @@ -77,7 +77,7 @@ pub struct NumberTypeOption { impl_type_option!(NumberTypeOption, FieldType::Number); impl CellDataOperation for NumberTypeOption { - fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if type_option_cell_data.is_date() { return String::new(); @@ -101,8 +101,13 @@ impl CellDataOperation for NumberTypeOption { } } - fn serialize_cell_data(&self, data: &str) -> Result { - let data = self.strip_symbol(data); + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result { + let changeset = changeset.into(); + let data = self.strip_symbol(changeset); if !data.chars().all(char::is_numeric) { return Err(FlowyError::invalid_data().context("Should only contain numbers")); @@ -149,8 +154,8 @@ impl NumberTypeOption { } } - fn strip_symbol(&self, s: &str) -> String { - let mut s = String::from(s); + fn strip_symbol(&self, s: T) -> String { + let mut s = s.to_string(); if !s.chars().all(char::is_numeric) { s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string())); } @@ -213,11 +218,8 @@ mod tests { fn number_description_invalid_input_test() { let type_option = NumberTypeOption::default(); let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); - assert_eq!("".to_owned(), type_option.deserialize_cell_data(data(""), &field_meta)); - assert_eq!( - "".to_owned(), - type_option.deserialize_cell_data(data("abc"), &field_meta) - ); + assert_eq!("".to_owned(), type_option.decode_cell_data(data(""), &field_meta)); + assert_eq!("".to_owned(), type_option.decode_cell_data(data("abc"), &field_meta)); } #[test] @@ -233,30 +235,27 @@ mod tests { match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "$18,443".to_owned() ); - assert_eq!(type_option.deserialize_cell_data(data(""), &field_meta), "".to_owned()); - assert_eq!( - type_option.deserialize_cell_data(data("abc"), &field_meta), - "".to_owned() - ); + assert_eq!(type_option.decode_cell_data(data(""), &field_meta), "".to_owned()); + assert_eq!(type_option.decode_cell_data(data("abc"), &field_meta), "".to_owned()); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "€18.443".to_owned() ); } @@ -281,25 +280,25 @@ mod tests { match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "$1,844.3".to_owned() ); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "Â¥1,844.3".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "€1.844,3".to_owned() ); } @@ -320,25 +319,25 @@ mod tests { match format { NumberFormat::Number => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "18443".to_owned() ); } NumberFormat::USD => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "-$18,443".to_owned() ); } NumberFormat::CNY => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "-Â¥18,443".to_owned() ); } NumberFormat::EUR => { assert_eq!( - type_option.deserialize_cell_data(data("18443"), &field_meta), + type_option.decode_cell_data(data("18443"), &field_meta), "-€18.443".to_owned() ); } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 1774b12ce3..07bef42e5f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,11 +1,13 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{CellDataOperation, TypeOptionCellData}; +use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellData}; use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::entities::{ + CellMeta, CellMetaChangeset, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry, +}; use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; @@ -25,26 +27,66 @@ pub struct SingleSelectTypeOption { } impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); +impl SingleSelectTypeOption { + pub fn select_option_context(&self, cell_meta: &Option) -> SelectOptionContext { + let select_options = make_select_context_from(cell_meta, &self.options); + SelectOptionContext { + options: self.options.clone(), + select_options, + } + } +} + +fn make_select_context_from(cell_meta: &Option, options: &Vec) -> Vec { + match cell_meta { + None => vec![], + Some(cell_meta) => { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&cell_meta.data) { + select_option_ids(type_option_cell_data.data) + .into_iter() + .flat_map(|option_id| options.iter().find(|option| option.id == option_id).cloned()) + .collect() + } else { + vec![] + } + } + } +} + impl CellDataOperation for SingleSelectTypeOption { - fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { - if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { + if !type_option_cell_data.is_single_select() { return String::new(); } - let option_id = type_option_cell_data.data; - match self.options.iter().find(|option| option.id == option_id) { + match select_option_ids(type_option_cell_data.data).pop() { None => String::new(), - Some(option) => option.name.clone(), + Some(option_id) => match self.options.iter().find(|option| option.id == option_id) { + None => String::new(), + Some(option) => option.name.clone(), + }, } } else { String::new() } } - fn serialize_cell_data(&self, data: &str) -> Result { - let data = single_select_option_id_from_data(data.to_owned())?; - Ok(TypeOptionCellData::new(&data, self.field_type()).json()) + fn apply_changeset>( + &self, + changeset: T, + _cell_meta: Option, + ) -> Result { + let changeset = changeset.into(); + let select_option_changeset: SelectOptionChangeset = serde_json::from_str(&changeset)?; + let new_cell_data: String; + if let Some(insert_option_id) = select_option_changeset.insert_option_id { + new_cell_data = insert_option_id; + } else { + new_cell_data = "".to_string() + } + + return Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()); } } @@ -81,33 +123,59 @@ pub struct MultiSelectTypeOption { } impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl MultiSelectTypeOption { + pub fn select_option_context(&self, cell_meta: &Option) -> SelectOptionContext { + todo!() + } +} + impl CellDataOperation for MultiSelectTypeOption { - fn deserialize_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { - if !type_option_cell_data.is_single_select() || !type_option_cell_data.is_multi_select() { + if !type_option_cell_data.is_multi_select() { return String::new(); } - - match select_option_ids(type_option_cell_data.data) { - Ok(option_ids) => { - // - self.options - .iter() - .filter(|option| option_ids.contains(&option.id)) - .map(|option| option.name.clone()) - .collect::>() - .join(SELECTION_IDS_SEPARATOR) - } - Err(_) => String::new(), - } + let option_ids = select_option_ids(type_option_cell_data.data); + self.options + .iter() + .filter(|option| option_ids.contains(&option.id)) + .map(|option| option.name.clone()) + .collect::>() + .join(SELECTION_IDS_SEPARATOR) } else { String::new() } } - fn serialize_cell_data(&self, data: &str) -> Result { - let data = multi_select_option_id_from_data(data.to_owned())?; - Ok(TypeOptionCellData::new(&data, self.field_type()).json()) + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result { + let changeset = changeset.into(); + let select_option_changeset: SelectOptionChangeset = serde_json::from_str(&changeset)?; + let new_cell_data: String; + match cell_meta { + None => { + new_cell_data = select_option_changeset + .insert_option_id + .unwrap_or_else(|| "".to_owned()); + } + Some(cell_meta) => { + let mut selected_options = select_option_ids(cell_meta.data); + if let Some(insert_option_id) = select_option_changeset.insert_option_id { + selected_options.push(insert_option_id); + } + + if let Some(delete_option_id) = select_option_changeset.delete_option_id { + selected_options.retain(|id| id != &delete_option_id); + } + + new_cell_data = selected_options.join(SELECTION_IDS_SEPARATOR); + } + } + + Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()) } } @@ -132,41 +200,10 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { } } -fn single_select_option_id_from_data(data: String) -> FlowyResult { - let select_option_ids = select_option_ids(data)?; - if select_option_ids.is_empty() { - return Ok("".to_owned()); - } - - Ok(select_option_ids.split_first().unwrap().0.to_string()) -} - -fn multi_select_option_id_from_data(data: String) -> FlowyResult { - let select_option_ids = select_option_ids(data)?; - Ok(select_option_ids.join(SELECTION_IDS_SEPARATOR)) -} - -fn select_option_ids(mut data: String) -> FlowyResult> { - data.retain(|c| !c.is_whitespace()); - let select_option_ids = data.split(SELECTION_IDS_SEPARATOR).collect::>(); - if select_option_ids - .par_iter() - .find_first(|option_id| match Uuid::parse_str(option_id) { - Ok(_) => false, - Err(e) => { - tracing::error!("{}", e); - true - } - }) - .is_some() - { - let msg = format!( - "Invalid selection id string: {}. It should consist of the uuid string and separated by comma", - data - ); - return Err(FlowyError::internal().context(msg)); - } - Ok(select_option_ids.iter().map(|id| id.to_string()).collect::>()) +fn select_option_ids(data: String) -> Vec { + data.split(SELECTION_IDS_SEPARATOR) + .map(|id| id.to_string()) + .collect::>() } #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] @@ -209,7 +246,6 @@ pub struct SelectOptionChangesetPayload { pub delete_option_id: Option, } -#[derive(Clone)] pub struct SelectOptionChangesetParams { pub grid_id: String, pub field_id: String, @@ -218,6 +254,28 @@ pub struct SelectOptionChangesetParams { pub delete_option_id: Option, } +#[derive(Clone, Serialize, Deserialize)] +pub struct SelectOptionChangeset { + pub insert_option_id: Option, + pub delete_option_id: Option, +} + +impl std::convert::From for CellMetaChangeset { + fn from(params: SelectOptionChangesetParams) -> Self { + let changeset = SelectOptionChangeset { + insert_option_id: params.insert_option_id, + delete_option_id: params.delete_option_id, + }; + let s = serde_json::to_string(&changeset).unwrap(); + CellMetaChangeset { + grid_id: params.grid_id, + row_id: params.row_id, + field_id: params.field_id, + data: Some(s), + } + } +} + impl TryInto for SelectOptionChangesetPayload { type Error = ErrorCode; @@ -228,7 +286,7 @@ impl TryInto for SelectOptionChangesetPayload { let insert_option_id = match self.insert_option_id { None => None, Some(insert_option_id) => Some( - NotEmptyStr::parse(insert_option_id) + NotEmptyUuid::parse(insert_option_id) .map_err(|_| ErrorCode::OptionIdIsEmpty)? .0, ), @@ -237,7 +295,7 @@ impl TryInto for SelectOptionChangesetPayload { let delete_option_id = match self.delete_option_id { None => None, Some(delete_option_id) => Some( - NotEmptyStr::parse(delete_option_id) + NotEmptyUuid::parse(delete_option_id) .map_err(|_| ErrorCode::OptionIdIsEmpty)? .0, ), @@ -291,9 +349,9 @@ mod tests { #[should_panic] fn selection_description_test() { let type_option = SingleSelectTypeOption::default(); - assert_eq!(type_option.serialize_cell_data("1,2,3").unwrap(), "1".to_owned()); + assert_eq!(type_option.apply_changeset("1,2,3").unwrap(), "1".to_owned()); let type_option = MultiSelectTypeOption::default(); - assert_eq!(type_option.serialize_cell_data("1,2,3").unwrap(), "1,2,3".to_owned()); + assert_eq!(type_option.apply_changeset("1,2,3").unwrap(), "1,2,3".to_owned()); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 4b7195a305..f38f24ac9d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,10 +1,10 @@ use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; -use crate::services::row::{deserialize_cell_data, CellDataOperation, TypeOptionCellData}; +use crate::services::row::{decode_cell_data, CellDataChangeset, CellDataOperation, TypeOptionCellData}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; +use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -31,14 +31,14 @@ pub struct RichTextTypeOption { impl_type_option!(RichTextTypeOption, FieldType::RichText); impl CellDataOperation for RichTextTypeOption { - fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String { + fn decode_cell_data(&self, data: String, field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { if type_option_cell_data.is_date() || type_option_cell_data.is_single_select() || type_option_cell_data.is_multi_select() || type_option_cell_data.is_number() { - deserialize_cell_data(data, field_meta).unwrap_or_else(|_| "".to_owned()) + decode_cell_data(data, field_meta).unwrap_or_else(|_| "".to_owned()) } else { type_option_cell_data.data } @@ -47,8 +47,12 @@ impl CellDataOperation for RichTextTypeOption { } } - fn serialize_cell_data(&self, data: &str) -> Result { - let data = data.to_owned(); + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result { + let data = changeset.into(); if data.len() > 10000 { Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000")) } else { @@ -72,7 +76,7 @@ mod tests { let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); let data = TypeOptionCellData::new("1647251762", FieldType::DateTime).json(); assert_eq!( - type_option.deserialize_cell_data(data, &date_time_field_meta), + type_option.decode_cell_data(data, &date_time_field_meta), "Mar 14,2022 17:56".to_owned() ); @@ -83,7 +87,7 @@ mod tests { let single_select_field_meta = FieldBuilder::new(single_select).build(); let data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); assert_eq!( - type_option.deserialize_cell_data(data, &single_select_field_meta), + type_option.decode_cell_data(data, &single_select_field_meta), "Done".to_owned() ); @@ -103,7 +107,7 @@ mod tests { ) .json(); assert_eq!( - type_option.deserialize_cell_data(data, &multi_select_field_meta), + type_option.decode_cell_data(data, &multi_select_field_meta), "Google,Facebook".to_owned() ); @@ -112,7 +116,7 @@ mod tests { let number_field_meta = FieldBuilder::new(number).build(); let data = TypeOptionCellData::new("18443", FieldType::Number).json(); assert_eq!( - type_option.deserialize_cell_data(data, &number_field_meta), + type_option.decode_cell_data(data, &number_field_meta), "$18,443".to_owned() ); } 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 708e07fd74..17fb852e07 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,9 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{ - default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder, SelectOptionChangesetParams, -}; +use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::persistence::block_index::BlockIndexPersistence; use crate::services::row::*; use bytes::Bytes; @@ -40,7 +38,7 @@ impl ClientGridEditor { let grid_pad = rev_manager.load::(Some(cloud)).await?; let rev_manager = Arc::new(rev_manager); let pad = Arc::new(RwLock::new(grid_pad)); - let blocks = pad.read().await.get_block_metas().clone(); + let blocks = pad.read().await.get_block_metas(); let block_meta_manager = Arc::new(GridBlockMetaEditorManager::new(grid_id, &user, blocks, persistence).await?); Ok(Arc::new(Self { @@ -100,7 +98,7 @@ impl ClientGridEditor { pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let field_id = params.field_id.clone(); - let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { + let deserializer = match self.pad.read().await.get_field(params.field_id.as_str()) { None => return Err(ErrorCode::FieldDoesNotExist.into()), Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), }; @@ -147,11 +145,27 @@ impl ClientGridEditor { Ok(()) } - pub async fn get_field(&self, field_id: &str) -> FlowyResult> { - match self.pad.read().await.get_field(field_id) { - None => Ok(None), - Some(field_meta) => Ok(Some(field_meta.clone())), + pub async fn get_field_metas(&self, field_orders: Option>) -> FlowyResult> + where + T: Into, + { + if field_orders.is_none() { + let field_metas = self.pad.read().await.get_field_metas(None)?; + return Ok(field_metas); } + + let to_field_orders = |item: Vec| item.into_iter().map(|data| data.into()).collect(); + let field_orders = field_orders.map_or(vec![], to_field_orders); + let expected_len = field_orders.len(); + let field_metas = self.pad.read().await.get_field_metas(Some(field_orders))?; + if expected_len != 0 && field_metas.len() != expected_len { + tracing::error!( + "This is a bug. The len of the field_metas should equal to {}", + expected_len + ); + debug_assert!(field_metas.len() == expected_len); + } + Ok(field_metas) } pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> { @@ -217,7 +231,7 @@ impl ClientGridEditor { debug_assert_eq!(grid_block_snapshot.len(), 1); if grid_block_snapshot.len() == 1 { let snapshot = grid_block_snapshot.pop().unwrap(); - let field_metas = self.get_field_metas(None).await?; + let field_metas = self.get_field_metas::(None).await?; let rows = make_rows_from_row_metas(&field_metas, &snapshot.row_metas); Ok(rows.into()) } else { @@ -229,7 +243,7 @@ impl ClientGridEditor { match self.block_meta_manager.get_row_meta(row_id).await? { None => Ok(None), Some(row_meta) => { - let field_metas = self.get_field_metas(None).await?; + let field_metas = self.get_field_metas::(None).await?; let row_metas = vec![row_meta]; let mut rows = make_rows_from_row_metas(&field_metas, &row_metas); debug_assert!(rows.len() == 1); @@ -249,32 +263,30 @@ impl ClientGridEditor { } } - pub async fn apply_select_option(&self, params: SelectOptionChangesetParams) -> FlowyResult<()> { - let cell_meta = self.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?; - todo!() - } - pub async fn update_cell(&self, mut changeset: CellMetaChangeset) -> FlowyResult<()> { - if let Some(cell_data) = changeset.data.as_ref() { - match self.pad.read().await.get_field(&changeset.field_id) { - None => { - let msg = format!("Can not find the field with id: {}", &changeset.field_id); - return Err(FlowyError::internal().context(msg)); - } - Some(field_meta) => { - let cell_data = serialize_cell_data(cell_data, field_meta)?; - changeset.data = Some(cell_data); - } - } + if changeset.data.as_ref().is_none() { + return Ok(()); } - let field_metas = self.get_field_metas(None).await?; - let row_changeset: RowMetaChangeset = changeset.into(); - let _ = self - .block_meta_manager - .update_row_cells(&field_metas, row_changeset) - .await?; - Ok(()) + let cell_data_changeset = changeset.data.unwrap(); + let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?; + match self.pad.read().await.get_field(&changeset.field_id) { + None => { + let msg = format!("Field not found with id: {}", &changeset.field_id); + return Err(FlowyError::internal().context(msg)); + } + Some(field_meta) => { + // Update the changeset.data property with the return value. + changeset.data = Some(apply_cell_data_changeset(cell_data_changeset, cell_meta, field_meta)?); + let field_metas = self.get_field_metas::(None).await?; + let row_changeset: RowMetaChangeset = changeset.into(); + let _ = self + .block_meta_manager + .update_row_cells(&field_metas, row_changeset) + .await?; + Ok(()) + } + } } pub async fn get_blocks(&self, block_ids: Option>) -> FlowyResult { @@ -314,23 +326,6 @@ impl ClientGridEditor { }) } - pub async fn get_field_metas(&self, field_orders: Option>) -> FlowyResult> { - let expected_len = match field_orders.as_ref() { - None => 0, - Some(field_orders) => field_orders.len(), - }; - - let field_metas = self.pad.read().await.get_field_metas(field_orders)?; - if expected_len != 0 && field_metas.len() != expected_len { - tracing::error!( - "This is a bug. The len of the field_metas should equal to {}", - expected_len - ); - debug_assert!(field_metas.len() == expected_len); - } - Ok(field_metas) - } - pub async fn grid_block_snapshots(&self, block_ids: Option>) -> FlowyResult> { let block_ids = match block_ids { None => self @@ -393,7 +388,7 @@ impl ClientGridEditor { } async fn notify_did_update_fields(&self) -> FlowyResult<()> { - let field_metas = self.get_field_metas(None).await?; + 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::DidUpdateFields) .payload(repeated_field) @@ -402,8 +397,7 @@ impl ClientGridEditor { } async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> { - let field_order = FieldOrder::from(field_id); - let mut field_metas = self.get_field_metas(Some(field_order.into())).await?; + let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?; debug_assert!(field_metas.len() == 1); if let Some(field_meta) = field_metas.pop() { diff --git a/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs b/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs index a639776394..df75ec629c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs +++ b/frontend/rust-lib/flowy-grid/src/services/persistence/block_index.rs @@ -3,7 +3,6 @@ use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; use flowy_database::{ prelude::*, schema::{grid_block_index_table, grid_block_index_table::dsl}, - ConnectionPool, }; use flowy_error::FlowyResult; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs b/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs index cf66211fab..06a5a2d68f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs +++ b/frontend/rust-lib/flowy-grid/src/services/persistence/kv.rs @@ -5,7 +5,6 @@ use diesel::SqliteConnection; use flowy_database::{ prelude::*, schema::{kv_table, kv_table::dsl}, - ConnectionPool, }; use flowy_error::{FlowyError, FlowyResult}; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs index ad0dcb1646..9c8a04bdc3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs @@ -1,16 +1,44 @@ use crate::services::field::*; -use bytes::Bytes; +use std::fmt::Formatter; + use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType}; use serde::{Deserialize, Serialize}; pub trait CellDataOperation { - fn deserialize_cell_data(&self, data: String, field_meta: &FieldMeta) -> String; - fn serialize_cell_data(&self, data: &str) -> Result; - // fn apply_changeset() + fn decode_cell_data(&self, data: String, field_meta: &FieldMeta) -> String; + fn apply_changeset>( + &self, + changeset: T, + cell_meta: Option, + ) -> Result; } -#[derive(Serialize, Deserialize)] +#[derive(Debug)] +pub struct CellDataChangeset(String); + +impl std::fmt::Display for CellDataChangeset { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", &self.0) + } +} + +impl> std::convert::From for CellDataChangeset { + fn from(s: T) -> Self { + let s = s.as_ref().to_owned(); + CellDataChangeset(s) + } +} + +impl std::ops::Deref for CellDataChangeset { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Debug, Serialize, Deserialize)] pub struct TypeOptionCellData { pub data: String, pub field_type: FieldType, @@ -26,9 +54,9 @@ impl std::str::FromStr for TypeOptionCellData { } impl TypeOptionCellData { - pub fn new(data: &str, field_type: FieldType) -> Self { + pub fn new(data: T, field_type: FieldType) -> Self { TypeOptionCellData { - data: data.to_owned(), + data: data.to_string(), field_type, } } @@ -62,25 +90,34 @@ impl TypeOptionCellData { } } -pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result { +/// The function,apply_cell_data_changeset, will apply the cell_data_changeset. +/// +/// The cell_data_changeset will be deserialized into specific data base on the FieldType. +pub fn apply_cell_data_changeset>( + changeset: T, + cell_meta: Option, + field_meta: &FieldMeta, +) -> Result { match field_meta.field_type { - FieldType::RichText => RichTextTypeOption::from(field_meta).serialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field_meta).serialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field_meta).serialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).serialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).serialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::RichText => RichTextTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), + FieldType::Number => NumberTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), + FieldType::DateTime => DateTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), } } -pub fn deserialize_cell_data(data: String, field_meta: &FieldMeta) -> Result { +#[tracing::instrument(level = "trace", skip(field_meta, data), fields(content), err)] +pub fn decode_cell_data(data: String, field_meta: &FieldMeta) -> Result { let s = match field_meta.field_type { - FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), - FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), - FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), - FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), - FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), - FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data, field_meta), + FieldType::RichText => RichTextTypeOption::from(field_meta).decode_cell_data(data, field_meta), + FieldType::Number => NumberTypeOption::from(field_meta).decode_cell_data(data, field_meta), + FieldType::DateTime => DateTypeOption::from(field_meta).decode_cell_data(data, field_meta), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).decode_cell_data(data, field_meta), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).decode_cell_data(data, field_meta), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).decode_cell_data(data, field_meta), }; + tracing::Span::current().record("content", &format!("{:?}: {}", field_meta.field_type, s).as_str()); Ok(s) } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index 698d4ac4ec..22fc0f14ae 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -1,5 +1,5 @@ -use crate::services::row::serialize_cell_data; -use bytes::Bytes; +use crate::services::row::apply_cell_data_changeset; + use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{CellMeta, FieldMeta, RowMeta, DEFAULT_ROW_HEIGHT}; use std::collections::HashMap; @@ -36,7 +36,7 @@ impl<'a> CreateRowMetaBuilder<'a> { Err(FlowyError::internal().context(msg)) } Some(field_meta) => { - let data = serialize_cell_data(&data, field_meta)?; + let data = apply_cell_data_changeset(&data, None, field_meta)?; let cell = CellMeta::new(field_id, data); self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); Ok(()) 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 c497d7e12d..b37d937c0f 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 @@ -1,4 +1,4 @@ -use crate::services::row::deserialize_cell_data; +use crate::services::row::decode_cell_data; use flowy_error::FlowyResult; use flowy_grid_data_model::entities::{ Cell, CellMeta, FieldMeta, GridBlock, RepeatedGridBlock, Row, RowMeta, RowOrder, @@ -47,7 +47,7 @@ pub fn make_cell_by_field_id( cell_meta: CellMeta, ) -> Option<(String, Cell)> { let field_meta = field_map.get(&field_id)?; - match deserialize_cell_data(cell_meta.data, field_meta) { + match decode_cell_data(cell_meta.data, field_meta) { Ok(content) => { let cell = Cell::new(&field_id, content); Some((field_id, cell)) @@ -62,8 +62,8 @@ pub fn make_cell_by_field_id( #[allow(dead_code)] pub fn make_cell(field_id: &str, field_meta: &FieldMeta, row_meta: &RowMeta) -> Option { let cell_meta = row_meta.cell_by_field_id.get(field_id)?.clone(); - match deserialize_cell_data(cell_meta.data, field_meta) { - Ok(content) => Some(Cell::new(&field_id, content)), + match decode_cell_data(cell_meta.data, field_meta) { + Ok(content) => Some(Cell::new(field_id, content)), Err(e) => { tracing::error!("{}", e); None diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 26dd3896dc..c14c937f00 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -4,7 +4,7 @@ use chrono::NaiveDateTime; use flowy_grid::services::field::{ MultiSelectTypeOption, SelectOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, }; -use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataOperation, CreateRowMetaBuilder}; +use flowy_grid::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ CellMetaChangeset, FieldChangesetParams, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset, TypeOptionDataEntry, @@ -242,21 +242,21 @@ async fn grid_row_add_cells_test() { for field in &test.field_metas { match field.field_type { FieldType::RichText => { - let data = serialize_cell_data("hello world", field).unwrap(); + let data = apply_cell_data_changeset("hello world", field).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::Number => { - let data = serialize_cell_data("Â¥18,443", field).unwrap(); + let data = apply_cell_data_changeset("Â¥18,443", field).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::DateTime => { - let data = serialize_cell_data("1647251762", field).unwrap(); + let data = apply_cell_data_changeset("1647251762", field).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::SingleSelect => { let type_option = SingleSelectTypeOption::from(field); let options = type_option.options.first().unwrap(); - let data = type_option.serialize_cell_data(&options.id).unwrap(); + let data = type_option.apply_changeset(&options.id).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::MultiSelect => { @@ -267,11 +267,11 @@ async fn grid_row_add_cells_test() { .map(|option| option.id.clone()) .collect::>() .join(SELECTION_IDS_SEPARATOR); - let data = type_option.serialize_cell_data(&options).unwrap(); + let data = type_option.apply_changeset(&options).unwrap(); builder.add_cell(&field.id, data).unwrap(); } FieldType::Checkbox => { - let data = serialize_cell_data("false", field).unwrap(); + let data = apply_cell_data_changeset("false", field).unwrap(); builder.add_cell(&field.id, data).unwrap(); } } @@ -357,7 +357,7 @@ async fn grid_row_add_date_cell_test() { let date_field = date_field.unwrap(); let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone(); assert_eq!( - deserialize_cell_data(cell_data.data.clone(), &date_field).unwrap(), + decode_cell_data(cell_data.data.clone(), &date_field).unwrap(), "2022/03/16 08:31", ); let scripts = vec![CreateRow { context }]; 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 c92a3b23a4..de15556008 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -64,12 +64,8 @@ pub struct FieldIdentifierPayload { pub grid_id: String, } -#[derive(Debug, Clone, Default, ProtoBuf)] pub struct FieldIdentifierParams { - #[pb(index = 1)] pub field_id: String, - - #[pb(index = 2)] pub grid_id: String, } @@ -92,12 +88,6 @@ pub struct FieldOrder { pub field_id: String, } -impl std::convert::Into> for FieldOrder { - fn into(self) -> Vec { - vec![self] - } -} - impl std::convert::From<&FieldMeta> for FieldOrder { fn from(field_meta: &FieldMeta) -> Self { Self { @@ -112,6 +102,12 @@ impl std::convert::From<&str> for FieldOrder { } } +impl std::convert::From for FieldOrder { + fn from(s: String) -> Self { + FieldOrder { field_id: s } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct GetEditFieldContextPayload { #[pb(index = 1)] @@ -211,6 +207,14 @@ impl std::convert::From> for RepeatedFieldOrder { } } +impl std::convert::From for RepeatedFieldOrder { + fn from(s: String) -> Self { + RepeatedFieldOrder { + items: vec![FieldOrder::from(s)], + } + } +} + #[derive(Debug, Default, Clone, ProtoBuf)] pub struct RowOrder { #[pb(index = 1)] @@ -327,6 +331,39 @@ impl Cell { } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct CellIdentifierPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field_id: String, + + #[pb(index = 3)] + pub row_id: String, +} + +pub struct CellIdentifierParams { + pub grid_id: String, + pub field_id: String, + pub row_id: String, +} + +impl TryInto for CellIdentifierPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + Ok(CellIdentifierParams { + grid_id: grid_id.0, + field_id: field_id.0, + row_id: row_id.0, + }) + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct RepeatedCell { #[pb(index = 1)] @@ -430,7 +467,6 @@ pub struct CreateFieldPayload { pub start_field_id: Option, } -#[derive(Default, Clone)] pub struct CreateFieldParams { pub grid_id: String, pub field: Field, @@ -468,7 +504,6 @@ pub struct QueryFieldPayload { pub field_orders: RepeatedFieldOrder, } -#[derive(Default)] pub struct QueryFieldParams { pub grid_id: String, pub field_orders: RepeatedFieldOrder, @@ -495,7 +530,6 @@ pub struct QueryGridBlocksPayload { pub block_orders: Vec, } -#[derive(Default)] pub struct QueryGridBlocksParams { pub grid_id: String, pub block_orders: Vec, @@ -518,17 +552,12 @@ pub struct QueryRowPayload { #[pb(index = 1)] pub grid_id: String, - #[pb(index = 2)] - pub block_id: String, - #[pb(index = 3)] pub row_id: String, } -#[derive(Default)] pub struct QueryRowParams { pub grid_id: String, - pub block_id: String, pub row_id: String, } @@ -537,12 +566,10 @@ impl TryInto for QueryRowPayload { fn try_into(self) -> Result { let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?; let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; Ok(QueryRowParams { grid_id: grid_id.0, - block_id: block_id.0, row_id: row_id.0, }) } @@ -552,10 +579,14 @@ impl TryInto for QueryRowPayload { pub struct CreateSelectOptionPayload { #[pb(index = 1)] pub option_name: String, + + #[pb(index = 2)] + pub selected: bool, } pub struct CreateSelectOptionParams { pub option_name: String, + pub selected: bool, } impl TryInto for CreateSelectOptionPayload { @@ -565,6 +596,7 @@ impl TryInto for CreateSelectOptionPayload { let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?; Ok(CreateSelectOptionParams { option_name: option_name.0, + selected: self.selected, }) } } 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 7d13585c86..e80c31d8ad 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 @@ -860,207 +860,6 @@ impl ::protobuf::reflect::ProtobufValue for FieldIdentifierPayload { } } -#[derive(PartialEq,Clone,Default)] -pub struct FieldIdentifierParams { - // message fields - pub field_id: ::std::string::String, - pub grid_id: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a FieldIdentifierParams { - fn default() -> &'a FieldIdentifierParams { - ::default_instance() - } -} - -impl FieldIdentifierParams { - pub fn new() -> FieldIdentifierParams { - ::std::default::Default::default() - } - - // string field_id = 1; - - - pub fn get_field_id(&self) -> &str { - &self.field_id - } - pub fn clear_field_id(&mut self) { - self.field_id.clear(); - } - - // Param is passed by value, moved - pub fn set_field_id(&mut self, v: ::std::string::String) { - self.field_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_field_id(&mut self) -> &mut ::std::string::String { - &mut self.field_id - } - - // Take field - pub fn take_field_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) - } - - // string grid_id = 2; - - - pub fn get_grid_id(&self) -> &str { - &self.grid_id - } - pub fn clear_grid_id(&mut self) { - self.grid_id.clear(); - } - - // Param is passed by value, moved - pub fn set_grid_id(&mut self, v: ::std::string::String) { - self.grid_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { - &mut self.grid_id - } - - // Take field - pub fn take_grid_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for FieldIdentifierParams { - 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.field_id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; - }, - _ => { - ::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.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.field_id); - } - if !self.grid_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.grid_id); - } - 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.field_id.is_empty() { - os.write_string(1, &self.field_id)?; - } - if !self.grid_id.is_empty() { - os.write_string(2, &self.grid_id)?; - } - 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() -> FieldIdentifierParams { - FieldIdentifierParams::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>( - "field_id", - |m: &FieldIdentifierParams| { &m.field_id }, - |m: &mut FieldIdentifierParams| { &mut m.field_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "grid_id", - |m: &FieldIdentifierParams| { &m.grid_id }, - |m: &mut FieldIdentifierParams| { &mut m.grid_id }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "FieldIdentifierParams", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static FieldIdentifierParams { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(FieldIdentifierParams::new) - } -} - -impl ::protobuf::Clear for FieldIdentifierParams { - fn clear(&mut self) { - self.field_id.clear(); - self.grid_id.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for FieldIdentifierParams { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for FieldIdentifierParams { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - #[derive(PartialEq,Clone,Default)] pub struct FieldOrder { // message fields @@ -3681,6 +3480,249 @@ impl ::protobuf::reflect::ProtobufValue for Cell { } } +#[derive(PartialEq,Clone,Default)] +pub struct CellIdentifierPayload { + // message fields + pub grid_id: ::std::string::String, + pub field_id: ::std::string::String, + pub row_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CellIdentifierPayload { + fn default() -> &'a CellIdentifierPayload { + ::default_instance() + } +} + +impl CellIdentifierPayload { + pub fn new() -> CellIdentifierPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string field_id = 2; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string row_id = 3; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for CellIdentifierPayload { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.field_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.row_id); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.field_id.is_empty() { + os.write_string(2, &self.field_id)?; + } + if !self.row_id.is_empty() { + os.write_string(3, &self.row_id)?; + } + 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() -> CellIdentifierPayload { + CellIdentifierPayload::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>( + "grid_id", + |m: &CellIdentifierPayload| { &m.grid_id }, + |m: &mut CellIdentifierPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &CellIdentifierPayload| { &m.field_id }, + |m: &mut CellIdentifierPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &CellIdentifierPayload| { &m.row_id }, + |m: &mut CellIdentifierPayload| { &mut m.row_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CellIdentifierPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CellIdentifierPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CellIdentifierPayload::new) + } +} + +impl ::protobuf::Clear for CellIdentifierPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.field_id.clear(); + self.row_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CellIdentifierPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CellIdentifierPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct RepeatedCell { // message fields @@ -5333,7 +5375,6 @@ impl ::protobuf::reflect::ProtobufValue for QueryGridBlocksPayload { pub struct QueryRowPayload { // message fields pub grid_id: ::std::string::String, - pub block_id: ::std::string::String, pub row_id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -5377,32 +5418,6 @@ impl QueryRowPayload { ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) } - // string block_id = 2; - - - pub fn get_block_id(&self) -> &str { - &self.block_id - } - pub fn clear_block_id(&mut self) { - self.block_id.clear(); - } - - // Param is passed by value, moved - pub fn set_block_id(&mut self, v: ::std::string::String) { - self.block_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_block_id(&mut self) -> &mut ::std::string::String { - &mut self.block_id - } - - // Take field - pub fn take_block_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) - } - // string row_id = 3; @@ -5442,9 +5457,6 @@ impl ::protobuf::Message for QueryRowPayload { 1 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; - }, 3 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; }, @@ -5463,9 +5475,6 @@ impl ::protobuf::Message for QueryRowPayload { if !self.grid_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.grid_id); } - if !self.block_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.block_id); - } if !self.row_id.is_empty() { my_size += ::protobuf::rt::string_size(3, &self.row_id); } @@ -5478,9 +5487,6 @@ impl ::protobuf::Message for QueryRowPayload { if !self.grid_id.is_empty() { os.write_string(1, &self.grid_id)?; } - if !self.block_id.is_empty() { - os.write_string(2, &self.block_id)?; - } if !self.row_id.is_empty() { os.write_string(3, &self.row_id)?; } @@ -5527,11 +5533,6 @@ impl ::protobuf::Message for QueryRowPayload { |m: &QueryRowPayload| { &m.grid_id }, |m: &mut QueryRowPayload| { &mut m.grid_id }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "block_id", - |m: &QueryRowPayload| { &m.block_id }, - |m: &mut QueryRowPayload| { &mut m.block_id }, - )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "row_id", |m: &QueryRowPayload| { &m.row_id }, @@ -5554,7 +5555,6 @@ impl ::protobuf::Message for QueryRowPayload { impl ::protobuf::Clear for QueryRowPayload { fn clear(&mut self) { self.grid_id.clear(); - self.block_id.clear(); self.row_id.clear(); self.unknown_fields.clear(); } @@ -5576,6 +5576,7 @@ impl ::protobuf::reflect::ProtobufValue for QueryRowPayload { pub struct CreateSelectOptionPayload { // message fields pub option_name: ::std::string::String, + pub selected: bool, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -5617,6 +5618,21 @@ impl CreateSelectOptionPayload { pub fn take_option_name(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.option_name, ::std::string::String::new()) } + + // bool selected = 2; + + + pub fn get_selected(&self) -> bool { + self.selected + } + pub fn clear_selected(&mut self) { + self.selected = false; + } + + // Param is passed by value, moved + pub fn set_selected(&mut self, v: bool) { + self.selected = v; + } } impl ::protobuf::Message for CreateSelectOptionPayload { @@ -5631,6 +5647,13 @@ impl ::protobuf::Message for CreateSelectOptionPayload { 1 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.option_name)?; }, + 2 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_bool()?; + self.selected = tmp; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -5646,6 +5669,9 @@ impl ::protobuf::Message for CreateSelectOptionPayload { if !self.option_name.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.option_name); } + if self.selected != false { + my_size += 2; + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -5655,6 +5681,9 @@ impl ::protobuf::Message for CreateSelectOptionPayload { if !self.option_name.is_empty() { os.write_string(1, &self.option_name)?; } + if self.selected != false { + os.write_bool(2, self.selected)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -5698,6 +5727,11 @@ impl ::protobuf::Message for CreateSelectOptionPayload { |m: &CreateSelectOptionPayload| { &m.option_name }, |m: &mut CreateSelectOptionPayload| { &mut m.option_name }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( + "selected", + |m: &CreateSelectOptionPayload| { &m.selected }, + |m: &mut CreateSelectOptionPayload| { &mut m.selected }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateSelectOptionPayload", fields, @@ -5715,6 +5749,7 @@ impl ::protobuf::Message for CreateSelectOptionPayload { impl ::protobuf::Clear for CreateSelectOptionPayload { fn clear(&mut self) { self.option_name.clear(); + self.selected = false; self.unknown_fields.clear(); } } @@ -5742,55 +5777,55 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\ \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"L\n\x16FieldIdentifi\ erPayload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\ - \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"K\n\x15FieldIdentifierParams\ - \x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\ - id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\"\x90\x01\n\x1aGetEditFieldContextPayloa\ - d\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\x08field_\ - id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\ - \x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"q\n\x10EditFiel\ - dPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\ - \x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\nfield_type\x18\x03\ - \x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\x12\x17\ - \n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\x18\x02\ - \x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\x18\x03\ - \x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\x05items\ - \x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\ - \x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\n\x08\ - RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\ - lock_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\x03\x20\ - \x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\ - \tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellB\ - yFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\ - \x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01\ - (\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\ - \x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\ - \x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05items\x18\x01\ - \x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\x19\n\ - \x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\x0e\n\ - \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ - 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ - \x01(\tR\x07fieldId\x12\x18\n\x07content\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(\t\ - R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\ - lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\ - \"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ - idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\ - \x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\ - rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\ - \x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\ - \x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\ - \x0cstartFieldIdB\x17\n\x15one_of_start_field_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\"e\n\ - \x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\ - ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\ - \x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\ - \x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\ - kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"<\n\x19CreateSelec\ - tOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionNameb\ - \x06proto3\ + \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08\ + field_id\x18\x01\x20\x01(\tR\x07fieldId\"\x90\x01\n\x1aGetEditFieldConte\ + xtPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\ + \x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\ + \x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"q\ + \n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridI\ + d\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\nfield_typ\ + e\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\ + \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\ + \x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\ + \x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\ + \x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFiel\ + dOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\ + \n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\ + \n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\ + \x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\ + \x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.\ + Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\ + \x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\ + \x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.Cel\ + lR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\ + \x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05item\ + s\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\ + \x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\ + \x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\ + \x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\ + \x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07\ + content\"b\n\x15CellIdentifierPayload\x12\x17\n\x07grid_id\x18\x01\x20\ + \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ + \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"+\n\x0cRepeatedCell\ + \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11Cre\ + ateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06\ + GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\x0bGridBlock\ + Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayl\ + oad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cstart_\ + row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\ + \"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\ + \tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05fie\ + ld\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\ + \x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\ + \x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\ + \x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\ + \x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayl\ + oad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_o\ + rders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"A\n\x0fQ\ + ueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ + \x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"X\n\x19CreateSelectOption\ + Payload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionName\x12\x1a\ + \n\x08selected\x18\x02\x20\x01(\x08R\x08selectedb\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 6e4a4f31cf..b3fcea8740 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 @@ -19,10 +19,6 @@ message FieldIdentifierPayload { string field_id = 1; string grid_id = 2; } -message FieldIdentifierParams { - string field_id = 1; - string grid_id = 2; -} message FieldOrder { string field_id = 1; } @@ -74,6 +70,11 @@ message Cell { string field_id = 1; string content = 2; } +message CellIdentifierPayload { + string grid_id = 1; + string field_id = 2; + string row_id = 3; +} message RepeatedCell { repeated Cell items = 1; } @@ -106,9 +107,9 @@ message QueryGridBlocksPayload { } message QueryRowPayload { string grid_id = 1; - string block_id = 2; string row_id = 3; } message CreateSelectOptionPayload { string option_name = 1; + bool selected = 2; } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index f022488f0a..2d2e9888f6 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -4,7 +4,6 @@ use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; use flowy_grid_data_model::entities::{ FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta, GridBlockMetaChangeset, GridMeta, - RepeatedFieldOrder, }; use lib_infra::uuid; From c7a3bb73b98785c2c34eba565ded2c7c335c4ce9 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 5 Apr 2022 22:46:23 +0800 Subject: [PATCH 40/47] chore: listen on row update --- .../application/grid/grid_block_service.dart | 2 +- .../application/grid/row/row_bloc.dart | 61 +++++++++-------- .../application/grid/row/row_listener.dart | 9 +-- .../flowy-grid/dart_notification.pbenum.dart | 6 +- .../flowy-grid/dart_notification.pbjson.dart | 6 +- .../flowy-grid/src/dart_notification.rs | 4 +- .../src/protobuf/model/dart_notification.rs | 18 ++--- .../protobuf/proto/dart_notification.proto | 4 +- .../src/services/block_meta_editor.rs | 67 ++++++++++++------- 9 files changed, 94 insertions(+), 83 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart index 668b523c74..1dcd9685d1 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart @@ -80,7 +80,7 @@ class GridBlockListener { void _handleObservableType(GridNotification ty, Either result) { switch (ty) { - case GridNotification.DidUpdateRow: + case GridNotification.DidUpdateBlock: result.fold( (payload) => blockUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), (error) => blockUpdateNotifier.value = right(error), diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 14f30b4359..8592f4b1c3 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -36,28 +36,42 @@ class RowBloc extends Bloc { initial: (_InitialRow value) async { _startListening(); await _loadRow(emit); - add(const RowEvent.didUpdateCell()); }, createRow: (_CreateRow value) { rowService.createRow(); }, - didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fields: value.fields)); - add(const RowEvent.didUpdateCell()); + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) async { + await _handleFieldUpdate(emit, value); }, - didUpdateCell: (_DidUpdateCell value) async { - final optionRow = await state.row; - final CellDataMap cellDataMap = optionRow.fold( - () => CellDataMap.identity(), - (row) => _makeCellDatas(row), - ); - emit(state.copyWith(cellDataMap: Some(cellDataMap))); + didUpdateRow: (_DidUpdateRow value) async { + _handleRowUpdate(value, emit); }, ); }, ); } + void _handleRowUpdate(_DidUpdateRow value, Emitter emit) { + final CellDataMap cellDataMap = _makeCellDatas(value.row); + emit(state.copyWith( + row: Future(() => Some(value.row)), + cellDataMap: Some(cellDataMap), + )); + } + + Future _handleFieldUpdate(Emitter emit, _DidReceiveFieldUpdate value) async { + final optionRow = await state.row; + final CellDataMap cellDataMap = optionRow.fold( + () => CellDataMap.identity(), + (row) => _makeCellDatas(row), + ); + + emit(state.copyWith( + fields: value.fields, + cellDataMap: Some(cellDataMap), + )); + } + @override Future close() async { await rowlistener.stop(); @@ -68,18 +82,7 @@ class RowBloc extends Bloc { Future _startListening() async { rowlistener.updateRowNotifier.addPublishListener((result) { result.fold( - (row) { - // - }, - (err) => Log.error(err), - ); - }); - - rowlistener.updateCellNotifier.addPublishListener((result) { - result.fold( - (repeatedCell) { - Log.info("$repeatedCell"); - }, + (row) => add(RowEvent.didUpdateRow(row)), (err) => Log.error(err), ); }); @@ -96,16 +99,12 @@ class RowBloc extends Bloc { } Future _loadRow(Emitter emit) async { - final Future> row = rowService.getRow().then((result) { + rowService.getRow().then((result) { return result.fold( - (row) => Some(row), - (err) { - Log.error(err); - return none(); - }, + (row) => add(RowEvent.didUpdateRow(row)), + (err) => Log.error(err), ); }); - emit(state.copyWith(row: row)); } CellDataMap _makeCellDatas(Row row) { @@ -130,7 +129,7 @@ class RowEvent with _$RowEvent { const factory RowEvent.initial() = _InitialRow; const factory RowEvent.createRow() = _CreateRow; const factory RowEvent.didReceiveFieldUpdate(List fields) = _DidReceiveFieldUpdate; - const factory RowEvent.didUpdateCell() = _DidUpdateCell; + const factory RowEvent.didUpdateRow(Row row) = _DidUpdateRow; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart index 011dbd8636..12efb78a1b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart @@ -9,13 +9,11 @@ import 'dart:typed_data'; import 'package:app_flowy/core/notification_helper.dart'; import 'package:dartz/dartz.dart'; -typedef UpdateCellNotifiedValue = Either; typedef UpdateRowNotifiedValue = Either; typedef UpdateFieldNotifiedValue = Either, FlowyError>; class RowListener { final String rowId; - PublishNotifier updateCellNotifier = PublishNotifier(); PublishNotifier updateRowNotifier = PublishNotifier(); StreamSubscription? _subscription; GridNotificationParser? _parser; @@ -35,10 +33,10 @@ class RowListener { void _handleObservableType(GridNotification ty, Either result) { switch (ty) { - case GridNotification.GridDidUpdateCells: + case GridNotification.DidUpdateRow: result.fold( - (payload) => updateCellNotifier.value = left(RepeatedCell.fromBuffer(payload)), - (error) => updateCellNotifier.value = right(error), + (payload) => updateRowNotifier.value = left(Row.fromBuffer(payload)), + (error) => updateRowNotifier.value = right(error), ); break; default: @@ -49,7 +47,6 @@ class RowListener { Future stop() async { _parser = null; await _subscription?.cancel(); - updateCellNotifier.dispose(); updateRowNotifier.dispose(); } } 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 index 634de1b7f2..bf1367e43f 100644 --- 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 @@ -12,16 +12,16 @@ 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 DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock'); - static const GridNotification DidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); - static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); + static const GridNotification DidUpdateBlock = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateBlock'); + static const GridNotification DidUpdateRow = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField'); static const $core.List values = [ Unknown, DidCreateBlock, + DidUpdateBlock, DidUpdateRow, - GridDidUpdateCells, DidUpdateFields, DidUpdateField, ]; 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 index 571fe64399..92639052c0 100644 --- 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 @@ -14,12 +14,12 @@ const GridNotification$json = const { '2': const [ const {'1': 'Unknown', '2': 0}, const {'1': 'DidCreateBlock', '2': 11}, - const {'1': 'DidUpdateRow', '2': 20}, - const {'1': 'GridDidUpdateCells', '2': 30}, + const {'1': 'DidUpdateBlock', '2': 20}, + const {'1': 'DidUpdateRow', '2': 30}, const {'1': 'DidUpdateFields', '2': 40}, const {'1': 'DidUpdateField', '2': 41}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhAKDERpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEwoPRGlkVXBkYXRlRmllbGRzECgSEgoORGlkVXBkYXRlRmllbGQQKQ=='); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 364c42f680..2a8ffea466 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -6,8 +6,8 @@ const OBSERVABLE_CATEGORY: &str = "Grid"; pub enum GridNotification { Unknown = 0, DidCreateBlock = 11, - DidUpdateRow = 20, - GridDidUpdateCells = 30, + DidUpdateBlock = 20, + DidUpdateRow = 30, DidUpdateFields = 40, DidUpdateField = 41, } 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 index 32e697b36e..2c118b9c1e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -27,8 +27,8 @@ pub enum GridNotification { Unknown = 0, DidCreateBlock = 11, - DidUpdateRow = 20, - GridDidUpdateCells = 30, + DidUpdateBlock = 20, + DidUpdateRow = 30, DidUpdateFields = 40, DidUpdateField = 41, } @@ -42,8 +42,8 @@ impl ::protobuf::ProtobufEnum for GridNotification { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), 11 => ::std::option::Option::Some(GridNotification::DidCreateBlock), - 20 => ::std::option::Option::Some(GridNotification::DidUpdateRow), - 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), + 20 => ::std::option::Option::Some(GridNotification::DidUpdateBlock), + 30 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), 41 => ::std::option::Option::Some(GridNotification::DidUpdateField), _ => ::std::option::Option::None @@ -54,8 +54,8 @@ impl ::protobuf::ProtobufEnum for GridNotification { static values: &'static [GridNotification] = &[ GridNotification::Unknown, GridNotification::DidCreateBlock, + GridNotification::DidUpdateBlock, GridNotification::DidUpdateRow, - GridNotification::GridDidUpdateCells, GridNotification::DidUpdateFields, GridNotification::DidUpdateField, ]; @@ -86,10 +86,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x86\x01\n\x10GridNotification\x12\x0b\n\ - \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUp\ - dateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDid\ - UpdateFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\ + \n\x17dart_notification.proto*\x82\x01\n\x10GridNotification\x12\x0b\n\ + \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x12\n\x0eDidUp\ + dateBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x13\n\x0fDidUpda\ + teFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 index 176e0d83a4..62230e6376 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -3,8 +3,8 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; DidCreateBlock = 11; - DidUpdateRow = 20; - GridDidUpdateCells = 30; + DidUpdateBlock = 20; + DidUpdateRow = 30; DidUpdateFields = 40; DidUpdateField = 41; } 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 abdf1d5cbe..9a8ecd4655 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,12 +1,12 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::persistence::block_index::BlockIndexPersistence; -use crate::services::row::{make_block_row_ids, make_cell_by_field_id, GridBlockSnapshot}; +use crate::services::row::{make_block_row_ids, make_cell_by_field_id, make_rows_from_row_metas, GridBlockSnapshot}; use bytes::Bytes; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - CellMeta, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, + CellMeta, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, Row, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; @@ -120,9 +120,10 @@ impl GridBlockMetaEditorManager { } pub async fn update_row_cells(&self, field_metas: &[FieldMeta], changeset: RowMetaChangeset) -> FlowyResult<()> { - let editor = self.get_editor_from_row_id(&changeset.row_id).await?; + let row_id = changeset.row_id.clone(); + let editor = self.get_editor_from_row_id(&row_id).await?; let _ = editor.update_row(changeset.clone()).await?; - self.notify_did_update_cells(changeset, field_metas)?; + self.notify_did_update_row(&row_id, field_metas).await?; Ok(()) } @@ -171,35 +172,49 @@ impl GridBlockMetaEditorManager { async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { let block_order: GridBlockOrder = block_id.into(); - send_dart_notification(&self.grid_id, GridNotification::DidUpdateRow) + send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) .payload(block_order) .send(); Ok(()) } - 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_by_field_id(&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(); + async fn notify_did_update_row(&self, row_id: &str, field_metas: &[FieldMeta]) -> FlowyResult<()> { + match self.get_row_meta(row_id).await? { + None => {} + Some(row_meta) => { + let row_metas = vec![row_meta]; + if let Some(row) = make_rows_from_row_metas(&field_metas, &row_metas).pop() { + send_dart_notification(row_id, GridNotification::DidUpdateRow) + .payload(row) + .send(); + } + } } Ok(()) + + // + // 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_by_field_id(&field_meta_map, field_id, cell_meta) { + // None => {} + // Some((_, cell)) => cells.push(cell), + // }, + // ); + // + // if !cells.is_empty() { + // send_dart_notification(&changeset.row_id, GridNotification::DidUpdateRow) + // .payload(RepeatedCell::from(cells)) + // .send(); + // } + // Ok(()) } } From 6a36e2bcfdc914f9e2b8793248eb53f1a437f103 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 6 Apr 2022 10:32:08 +0800 Subject: [PATCH 41/47] chore: listen on cell update --- .../lib/core/notification_helper.dart | 19 + .../grid/cell_bloc/cell_listener.dart | 40 ++ .../grid/cell_bloc/selection_cell_bloc.dart | 17 +- .../grid/field/field_listener.dart | 23 +- .../application/grid/field/grid_listenr.dart | 20 +- .../application/grid/grid_block_service.dart | 20 +- .../application/grid/row/row_bloc.dart | 1 - .../application/grid/row/row_listener.dart | 19 +- .../application/grid/row/row_service.dart | 2 - .../grid/src/widgets/row/grid_row.dart | 26 +- .../flowy-grid-data-model/grid.pb.dart | 102 +++++ .../flowy-grid-data-model/grid.pbjson.dart | 16 + .../flowy-grid/dart_notification.pbenum.dart | 2 + .../flowy-grid/dart_notification.pbjson.dart | 3 +- frontend/rust-lib/dart-ffi/Cargo.toml | 2 +- .../flowy-grid/src/dart_notification.rs | 1 + .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- .../src/protobuf/model/dart_notification.rs | 10 +- .../protobuf/proto/dart_notification.proto | 1 + .../src/services/block_meta_editor.rs | 26 +- .../flowy-grid/src/services/grid_editor.rs | 7 +- .../src/entities/grid.rs | 23 +- .../src/protobuf/model/grid.rs | 369 +++++++++++++++++- .../src/protobuf/proto/grid.proto | 6 + 24 files changed, 640 insertions(+), 117 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_listener.dart diff --git a/frontend/app_flowy/lib/core/notification_helper.dart b/frontend/app_flowy/lib/core/notification_helper.dart index d815bf92bb..650abc544c 100644 --- a/frontend/app_flowy/lib/core/notification_helper.dart +++ b/frontend/app_flowy/lib/core/notification_helper.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:typed_data'; import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; @@ -5,6 +6,7 @@ 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'; +import 'package:flowy_sdk/rust_stream.dart'; // User typedef UserNotificationCallback = void Function(UserNotification, Either); @@ -45,6 +47,23 @@ class GridNotificationParser extends NotificationParser result); + +class GridNotificationListener { + StreamSubscription? _subscription; + GridNotificationParser? _parser; + + GridNotificationListener({required String objectId, required GridNotificationHandler handler}) + : _parser = GridNotificationParser(id: objectId, callback: handler) { + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); + } + + Future stop() async { + _parser = null; + await _subscription?.cancel(); + } +} + class NotificationParser { String? id; void Function(T, Either) callback; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_listener.dart new file mode 100644 index 0000000000..d1fb0acc0c --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_listener.dart @@ -0,0 +1,40 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'dart:async'; +import 'dart:typed_data'; +import 'package:app_flowy/core/notification_helper.dart'; + +typedef UpdateFieldNotifiedValue = Either; + +class CellListener { + final String rowId; + final String fieldId; + PublishNotifier updateCellNotifier = PublishNotifier(); + GridNotificationListener? _listener; + CellListener({required this.rowId, required this.fieldId}); + + void start() { + _listener = GridNotificationListener(objectId: "$rowId:$fieldId", handler: _handler); + } + + void _handler(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.DidUpdateCell: + result.fold( + (payload) => updateCellNotifier.value = left(CellNotificationData.fromBuffer(payload)), + (error) => updateCellNotifier.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + updateCellNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 1b38376e86..48c11622fe 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -1,7 +1,6 @@ -import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -12,17 +11,20 @@ part 'selection_cell_bloc.freezed.dart'; class SelectionCellBloc extends Bloc { final CellService _service; + final CellListener _listener; SelectionCellBloc({ required CellService service, required CellData cellData, }) : _service = service, + _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), super(SelectionCellState.initial(cellData)) { on( (event, emit) async { await event.map( initial: (_InitialCell value) async { _loadOptions(); + _startListening(); }, didReceiveOptions: (_DidReceiveOptions value) { emit(state.copyWith(options: value.options, selectedOptions: value.selectedOptions)); @@ -34,6 +36,7 @@ class SelectionCellBloc extends Bloc { @override Future close() async { + await _listener.stop(); return super.close(); } @@ -52,6 +55,16 @@ class SelectionCellBloc extends Bloc { (err) => Log.error(err), ); } + + void _startListening() { + _listener.updateCellNotifier.addPublishListener((result) { + result.fold( + (notificationData) => _loadOptions(), + (err) => Log.error(err), + ); + }); + _listener.start(); + } } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart index eda5d83e69..ed09ca9b82 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart @@ -1,9 +1,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -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/dart_notification.pb.dart'; -import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_infra/notifier.dart'; import 'dart:async'; import 'dart:typed_data'; @@ -14,23 +12,21 @@ typedef UpdateFieldNotifiedValue = Either; class FieldListener { final String fieldId; PublishNotifier updateFieldNotifier = PublishNotifier(); - StreamSubscription? _subscription; - GridNotificationParser? _parser; + GridNotificationListener? _listener; FieldListener({required this.fieldId}); void start() { - _parser = GridNotificationParser( - id: fieldId, - callback: (ty, result) { - _handleObservableType(ty, result); - }, + _listener = GridNotificationListener( + objectId: fieldId, + handler: _handler, ); - - _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } - void _handleObservableType(GridNotification ty, Either result) { + void _handler( + GridNotification ty, + Either result, + ) { switch (ty) { case GridNotification.DidUpdateField: result.fold( @@ -44,8 +40,7 @@ class FieldListener { } Future stop() async { - _parser = null; - await _subscription?.cancel(); + await _listener?.stop(); updateFieldNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart index 60ff7dd415..fa92d84b79 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart @@ -1,9 +1,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -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/dart_notification.pb.dart'; -import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_infra/notifier.dart'; import 'dart:async'; import 'dart:typed_data'; @@ -14,22 +12,17 @@ typedef UpdateFieldNotifiedValue = Either, FlowyError>; class GridFieldsListener { final String gridId; PublishNotifier updateFieldsNotifier = PublishNotifier(); - StreamSubscription? _subscription; - GridNotificationParser? _parser; + GridNotificationListener? _listener; GridFieldsListener({required this.gridId}); void start() { - _parser = GridNotificationParser( - id: gridId, - callback: (ty, result) { - _handleObservableType(ty, result); - }, + _listener = GridNotificationListener( + objectId: gridId, + handler: _handler, ); - - _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } - void _handleObservableType(GridNotification ty, Either result) { + void _handler(GridNotification ty, Either result) { switch (ty) { case GridNotification.DidUpdateFields: result.fold( @@ -43,8 +36,7 @@ class GridFieldsListener { } Future stop() async { - _parser = null; - await _subscription?.cancel(); + await _listener?.stop(); updateFieldsNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart index 1dcd9685d1..e6ecad0949 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_block_service.dart @@ -3,10 +3,8 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -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/dart_notification.pb.dart'; -import 'package:flowy_sdk/rust_stream.dart'; import 'package:flowy_infra/notifier.dart'; import 'dart:async'; import 'dart:typed_data'; @@ -62,23 +60,18 @@ class GridBlockService { class GridBlockListener { final String gridId; PublishNotifier, FlowyError>> blockUpdateNotifier = PublishNotifier(comparable: null); - StreamSubscription? _subscription; - GridNotificationParser? _parser; + GridNotificationListener? _listener; GridBlockListener({required this.gridId}); void start() { - _parser = GridNotificationParser( - id: gridId, - callback: (ty, result) { - _handleObservableType(ty, result); - }, + _listener = GridNotificationListener( + objectId: gridId, + handler: _handler, ); - - _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } - void _handleObservableType(GridNotification ty, Either result) { + void _handler(GridNotification ty, Either result) { switch (ty) { case GridNotification.DidUpdateBlock: result.fold( @@ -93,8 +86,7 @@ class GridBlockListener { } Future stop() async { - _parser = null; - await _subscription?.cancel(); + await _listener?.stop(); blockUpdateNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 8592f4b1c3..3c29d82d46 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -114,7 +114,6 @@ class RowBloc extends Bloc { map[field.id] = CellData( rowId: row.id, gridId: rowService.gridId, - blockId: rowService.blockId, cell: row.cellByFieldId[field.id], field: field, ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart index 12efb78a1b..716d252802 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_listener.dart @@ -1,8 +1,6 @@ -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'; @@ -15,23 +13,15 @@ typedef UpdateFieldNotifiedValue = Either, FlowyError>; class RowListener { final String rowId; PublishNotifier updateRowNotifier = PublishNotifier(); - StreamSubscription? _subscription; - GridNotificationParser? _parser; + GridNotificationListener? _listener; RowListener({required this.rowId}); void start() { - _parser = GridNotificationParser( - id: rowId, - callback: (ty, result) { - _handleObservableType(ty, result); - }, - ); - - _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); + _listener = GridNotificationListener(objectId: rowId, handler: _handler); } - void _handleObservableType(GridNotification ty, Either result) { + void _handler(GridNotification ty, Either result) { switch (ty) { case GridNotification.DidUpdateRow: result.fold( @@ -45,8 +35,7 @@ class RowListener { } Future stop() async { - _parser = null; - await _subscription?.cancel(); + await _listener?.stop(); updateRowNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 1b3f9e87ec..8875f9dc98 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -31,14 +31,12 @@ class RowService { class CellData extends Equatable { final String gridId; final String rowId; - final String blockId; final Field field; final Cell? cell; const CellData({ required this.rowId, required this.gridId, - required this.blockId, required this.field, required this.cell, }); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index 5586328e32..d3ac6d8ce3 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -122,24 +122,22 @@ class _RowCells extends StatelessWidget { return BlocBuilder( buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap, builder: (context, state) { - final List children = state.cellDataMap.fold( - () => [], - (dataMap) { - return dataMap.values.map( - (value) { - return CellContainer( - width: value.field.width.toDouble(), - child: buildGridCell(value), - ); - }, - ).toList(); - }, - ); - + final List children = state.cellDataMap.fold(() => [], _toCells); return Row(children: children); }, ); } + + List _toCells(CellDataMap dataMap) { + return dataMap.values.map( + (cellData) { + return CellContainer( + width: cellData.field.width.toDouble(), + child: buildGridCell(cellData), + ); + }, + ).toList(); + } } class RowRegionStateNotifier extends ChangeNotifier { 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 ab195308c6..2cd87115bf 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 @@ -1099,6 +1099,108 @@ class CellIdentifierPayload extends $pb.GeneratedMessage { void clearRowId() => clearField(3); } +enum CellNotificationData_OneOfContent { + content, + notSet +} + +class CellNotificationData extends $pb.GeneratedMessage { + static const $core.Map<$core.int, CellNotificationData_OneOfContent> _CellNotificationData_OneOfContentByTag = { + 4 : CellNotificationData_OneOfContent.content, + 0 : CellNotificationData_OneOfContent.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellNotificationData', createEmptyInstance: create) + ..oo(0, [4]) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content') + ..hasRequiredFields = false + ; + + CellNotificationData._() : super(); + factory CellNotificationData({ + $core.String? gridId, + $core.String? fieldId, + $core.String? rowId, + $core.String? content, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (rowId != null) { + _result.rowId = rowId; + } + if (content != null) { + _result.content = content; + } + return _result; + } + factory CellNotificationData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CellNotificationData.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') + CellNotificationData clone() => CellNotificationData()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CellNotificationData copyWith(void Function(CellNotificationData) updates) => super.copyWith((message) => updates(message as CellNotificationData)) as CellNotificationData; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CellNotificationData create() => CellNotificationData._(); + CellNotificationData createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CellNotificationData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CellNotificationData? _defaultInstance; + + CellNotificationData_OneOfContent whichOneOfContent() => _CellNotificationData_OneOfContentByTag[$_whichOneof(0)]!; + void clearOneOfContent() => clearField($_whichOneof(0)); + + @$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 fieldId => $_getSZ(1); + @$pb.TagNumber(2) + set fieldId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasFieldId() => $_has(1); + @$pb.TagNumber(2) + void clearFieldId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get rowId => $_getSZ(2); + @$pb.TagNumber(3) + set rowId($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasRowId() => $_has(2); + @$pb.TagNumber(3) + void clearRowId() => clearField(3); + + @$pb.TagNumber(4) + $core.String get content => $_getSZ(3); + @$pb.TagNumber(4) + set content($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasContent() => $_has(3); + @$pb.TagNumber(4) + void clearContent() => clearField(4); +} + 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) 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 c51a224a9e..cf58ec74a2 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 @@ -215,6 +215,22 @@ const CellIdentifierPayload$json = const { /// Descriptor for `CellIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List cellIdentifierPayloadDescriptor = $convert.base64Decode('ChVDZWxsSWRlbnRpZmllclBheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); +@$core.Deprecated('Use cellNotificationDataDescriptor instead') +const CellNotificationData$json = const { + '1': 'CellNotificationData', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, + const {'1': 'content', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'content'}, + ], + '8': const [ + const {'1': 'one_of_content'}, + ], +}; + +/// Descriptor for `CellNotificationData`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List cellNotificationDataDescriptor = $convert.base64Decode('ChRDZWxsTm90aWZpY2F0aW9uRGF0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSGQoIZmllbGRfaWQYAiABKAlSB2ZpZWxkSWQSFQoGcm93X2lkGAMgASgJUgVyb3dJZBIaCgdjb250ZW50GAQgASgJSABSB2NvbnRlbnRCEAoOb25lX29mX2NvbnRlbnQ='); @$core.Deprecated('Use repeatedCellDescriptor instead') const RepeatedCell$json = const { '1': 'RepeatedCell', 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 index bf1367e43f..8f1cd90c29 100644 --- 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 @@ -14,6 +14,7 @@ class GridNotification extends $pb.ProtobufEnum { static const GridNotification DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock'); static const GridNotification DidUpdateBlock = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateBlock'); static const GridNotification DidUpdateRow = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); + static const GridNotification DidUpdateCell = GridNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateCell'); static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField'); @@ -22,6 +23,7 @@ class GridNotification extends $pb.ProtobufEnum { DidCreateBlock, DidUpdateBlock, DidUpdateRow, + DidUpdateCell, DidUpdateFields, DidUpdateField, ]; 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 index 92639052c0..504d7e56f5 100644 --- 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 @@ -16,10 +16,11 @@ const GridNotification$json = const { const {'1': 'DidCreateBlock', '2': 11}, const {'1': 'DidUpdateBlock', '2': 20}, const {'1': 'DidUpdateRow', '2': 30}, + const {'1': 'DidUpdateCell', '2': 31}, const {'1': 'DidUpdateFields', '2': 40}, const {'1': 'DidUpdateField', '2': 41}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEwoPRGlkVXBkYXRlRmllbGRzECgSEgoORGlkVXBkYXRlRmllbGQQKQ=='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEQoNRGlkVXBkYXRlQ2VsbBAfEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk='); diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index df26694331..143dc76b1e 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" name = "dart_ffi" # this value will change depending on the target os # default static lib -crate-type = ["staticlib"] +crate-type = ["cdylib"] [dependencies] diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 2a8ffea466..914b3088f5 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -8,6 +8,7 @@ pub enum GridNotification { DidCreateBlock = 11, DidUpdateBlock = 20, DidUpdateRow = 30, + DidUpdateCell = 31, DidUpdateFields = 40, DidUpdateField = 41, } diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 62cbb4abec..2a8bb86103 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -132,7 +132,7 @@ pub(crate) async fn get_select_option_handler( data: Data, manager: AppData>, ) -> DataResult { - let params: CellIdentifierParams = data.into_inner().try_into()?; + let params: CellIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; match editor .get_field_metas(Some(vec![params.field_id.as_str()])) 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 index 2c118b9c1e..e02f234e9f 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -29,6 +29,7 @@ pub enum GridNotification { DidCreateBlock = 11, DidUpdateBlock = 20, DidUpdateRow = 30, + DidUpdateCell = 31, DidUpdateFields = 40, DidUpdateField = 41, } @@ -44,6 +45,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { 11 => ::std::option::Option::Some(GridNotification::DidCreateBlock), 20 => ::std::option::Option::Some(GridNotification::DidUpdateBlock), 30 => ::std::option::Option::Some(GridNotification::DidUpdateRow), + 31 => ::std::option::Option::Some(GridNotification::DidUpdateCell), 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), 41 => ::std::option::Option::Some(GridNotification::DidUpdateField), _ => ::std::option::Option::None @@ -56,6 +58,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { GridNotification::DidCreateBlock, GridNotification::DidUpdateBlock, GridNotification::DidUpdateRow, + GridNotification::DidUpdateCell, GridNotification::DidUpdateFields, GridNotification::DidUpdateField, ]; @@ -86,10 +89,11 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x82\x01\n\x10GridNotification\x12\x0b\n\ + \n\x17dart_notification.proto*\x95\x01\n\x10GridNotification\x12\x0b\n\ \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x12\n\x0eDidUp\ - dateBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x13\n\x0fDidUpda\ - teFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\ + dateBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x11\n\rDidUpdate\ + Cell\x10\x1f\x12\x13\n\x0fDidUpdateFields\x10(\x12\x12\n\x0eDidUpdateFie\ + ld\x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; 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 index 62230e6376..6ecb36847a 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -5,6 +5,7 @@ enum GridNotification { DidCreateBlock = 11; DidUpdateBlock = 20; DidUpdateRow = 30; + DidUpdateCell = 31; DidUpdateFields = 40; DidUpdateField = 41; } 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 9a8ecd4655..d8231dbb2e 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 @@ -6,8 +6,8 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - CellMeta, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, Row, RowMeta, - RowMetaChangeset, RowOrder, + CellIdentifier, CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, + GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, Row, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{ @@ -119,11 +119,19 @@ impl GridBlockMetaEditorManager { Ok(()) } - pub async fn update_row_cells(&self, field_metas: &[FieldMeta], changeset: RowMetaChangeset) -> FlowyResult<()> { + pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { let row_id = changeset.row_id.clone(); let editor = self.get_editor_from_row_id(&row_id).await?; - let _ = editor.update_row(changeset.clone()).await?; - self.notify_did_update_row(&row_id, field_metas).await?; + let row_changeset: RowMetaChangeset = changeset.clone().into(); + let _ = editor.update_row(row_changeset).await?; + + let cell_notification_data = CellNotificationData { + grid_id: changeset.grid_id, + field_id: changeset.field_id, + row_id: changeset.row_id, + content: changeset.data, + }; + self.notify_did_update_cell(cell_notification_data).await?; Ok(()) } @@ -178,6 +186,14 @@ impl GridBlockMetaEditorManager { Ok(()) } + async fn notify_did_update_cell(&self, data: CellNotificationData) -> FlowyResult<()> { + let id = format!("{}:{}", data.row_id, data.field_id); + send_dart_notification(&id, GridNotification::DidUpdateCell) + .payload(data) + .send(); + Ok(()) + } + async fn notify_did_update_row(&self, row_id: &str, field_metas: &[FieldMeta]) -> FlowyResult<()> { match self.get_row_meta(row_id).await? { None => {} 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 17fb852e07..1a184d51e9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -278,12 +278,7 @@ impl ClientGridEditor { Some(field_meta) => { // Update the changeset.data property with the return value. changeset.data = Some(apply_cell_data_changeset(cell_data_changeset, cell_meta, field_meta)?); - let field_metas = self.get_field_metas::(None).await?; - let row_changeset: RowMetaChangeset = changeset.into(); - let _ = self - .block_meta_manager - .update_row_cells(&field_metas, row_changeset) - .await?; + let _ = self.block_meta_manager.update_cell(changeset).await?; Ok(()) } } 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 de15556008..56c76d1925 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -343,20 +343,20 @@ pub struct CellIdentifierPayload { pub row_id: String, } -pub struct CellIdentifierParams { +pub struct CellIdentifier { pub grid_id: String, pub field_id: String, pub row_id: String, } -impl TryInto for CellIdentifierPayload { +impl TryInto for CellIdentifierPayload { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - Ok(CellIdentifierParams { + Ok(CellIdentifier { grid_id: grid_id.0, field_id: field_id.0, row_id: row_id.0, @@ -364,6 +364,21 @@ impl TryInto for CellIdentifierPayload { } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct CellNotificationData { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field_id: String, + + #[pb(index = 3)] + pub row_id: String, + + #[pb(index = 4, one_of)] + pub content: Option, +} + #[derive(Debug, Default, ProtoBuf)] pub struct RepeatedCell { #[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 e80c31d8ad..a64dad9191 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 @@ -3723,6 +3723,331 @@ impl ::protobuf::reflect::ProtobufValue for CellIdentifierPayload { } } +#[derive(PartialEq,Clone,Default)] +pub struct CellNotificationData { + // message fields + pub grid_id: ::std::string::String, + pub field_id: ::std::string::String, + pub row_id: ::std::string::String, + // message oneof groups + pub one_of_content: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CellNotificationData { + fn default() -> &'a CellNotificationData { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum CellNotificationData_oneof_one_of_content { + content(::std::string::String), +} + +impl CellNotificationData { + pub fn new() -> CellNotificationData { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string field_id = 2; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string row_id = 3; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } + + // string content = 4; + + + pub fn get_content(&self) -> &str { + match self.one_of_content { + ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(ref v)) => v, + _ => "", + } + } + pub fn clear_content(&mut self) { + self.one_of_content = ::std::option::Option::None; + } + + pub fn has_content(&self) -> bool { + match self.one_of_content { + ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_content(&mut self, v: ::std::string::String) { + self.one_of_content = ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(v)) + } + + // Mutable pointer to the field. + pub fn mut_content(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(_)) = self.one_of_content { + } else { + self.one_of_content = ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(::std::string::String::new())); + } + match self.one_of_content { + ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_content(&mut self) -> ::std::string::String { + if self.has_content() { + match self.one_of_content.take() { + ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } +} + +impl ::protobuf::Message for CellNotificationData { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_content = ::std::option::Option::Some(CellNotificationData_oneof_one_of_content::content(is.read_string()?)); + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.field_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.row_id); + } + if let ::std::option::Option::Some(ref v) = self.one_of_content { + match v { + &CellNotificationData_oneof_one_of_content::content(ref v) => { + my_size += ::protobuf::rt::string_size(4, &v); + }, + }; + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.field_id.is_empty() { + os.write_string(2, &self.field_id)?; + } + if !self.row_id.is_empty() { + os.write_string(3, &self.row_id)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_content { + match v { + &CellNotificationData_oneof_one_of_content::content(ref v) => { + os.write_string(4, v)?; + }, + }; + } + 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() -> CellNotificationData { + CellNotificationData::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>( + "grid_id", + |m: &CellNotificationData| { &m.grid_id }, + |m: &mut CellNotificationData| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &CellNotificationData| { &m.field_id }, + |m: &mut CellNotificationData| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &CellNotificationData| { &m.row_id }, + |m: &mut CellNotificationData| { &mut m.row_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "content", + CellNotificationData::has_content, + CellNotificationData::get_content, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CellNotificationData", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CellNotificationData { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CellNotificationData::new) + } +} + +impl ::protobuf::Clear for CellNotificationData { + fn clear(&mut self) { + self.grid_id.clear(); + self.field_id.clear(); + self.row_id.clear(); + self.one_of_content = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CellNotificationData { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CellNotificationData { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct RepeatedCell { // message fields @@ -5806,26 +6131,30 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07\ content\"b\n\x15CellIdentifierPayload\x12\x17\n\x07grid_id\x18\x01\x20\ \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ - \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"+\n\x0cRepeatedCell\ - \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11Cre\ - ateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06\ - GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\x0bGridBlock\ - Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayl\ - oad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cstart_\ - row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\ - \"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\ - \tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05fie\ - ld\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\ - \x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\ - \x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\ - \x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\ - \x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayl\ - oad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_o\ - rders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"A\n\x0fQ\ - ueryRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ - \x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"X\n\x19CreateSelectOption\ - Payload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionName\x12\x1a\ - \n\x08selected\x18\x02\x20\x01(\x08R\x08selectedb\x06proto3\ + \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"\x8f\x01\n\x14CellNot\ + ificationData\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\ + \n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\ + \x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\ + \x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05i\ + tems\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\ + \x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\ + \n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gri\ + dId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\ + \x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0es\ + tart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_st\ + art_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\ + \x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.Repe\ + atedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\ + \x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"A\n\x0fQueryRowPayloa\ + d\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\ + \x18\x03\x20\x01(\tR\x05rowId\"X\n\x19CreateSelectOptionPayload\x12\x1f\ + \n\x0boption_name\x18\x01\x20\x01(\tR\noptionName\x12\x1a\n\x08selected\ + \x18\x02\x20\x01(\x08R\x08selectedb\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 b3fcea8740..6be5bf1a64 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 @@ -75,6 +75,12 @@ message CellIdentifierPayload { string field_id = 2; string row_id = 3; } +message CellNotificationData { + string grid_id = 1; + string field_id = 2; + string row_id = 3; + oneof one_of_content { string content = 4; }; +} message RepeatedCell { repeated Cell items = 1; } From d09a5bf42b25d1c87195d5bf23baa89b562983f8 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 08:33:10 +0800 Subject: [PATCH 42/47] chore: update and delete select option --- .../app_flowy/lib/startup/deps_resolver.dart | 1 - .../grid/cell_bloc/cell_service.dart | 41 - .../grid/cell_bloc/select_option_service.dart | 109 ++ .../grid/cell_bloc/selection_cell_bloc.dart | 9 +- .../grid/cell_bloc/selection_editor_bloc.dart | 140 ++- .../grid/field/field_editor_bloc.dart | 2 +- .../application/grid/field/field_service.dart | 3 +- .../application/grid/field/grid_listenr.dart | 2 +- .../field/type_option/multi_select_bloc.dart | 2 +- .../field/type_option/single_select_bloc.dart | 2 +- .../type_option/type_option_service.dart | 12 +- .../application/grid/row/row_service.dart | 3 +- .../cell/selection_cell/extension.dart | 17 +- .../cell/selection_cell/selection_cell.dart | 2 - .../cell/selection_cell/selection_editor.dart | 52 +- .../header/type_option/option_pannel.dart | 1 - .../src/flowy_overlay/overlay_container.dart | 4 +- .../dart_event/flowy-grid/dart_event.dart | 41 +- .../flowy_sdk/lib/dispatch/dispatch.dart | 3 + .../flowy-error-code/code.pbenum.dart | 4 + .../flowy-error-code/code.pbjson.dart | 4 +- .../flowy-grid-data-model/grid.pb.dart | 258 ----- .../flowy-grid-data-model/grid.pbjson.dart | 45 - .../flowy-grid-data-model/protobuf.dart | 2 +- .../protobuf/flowy-grid/cell_entities.pb.dart | 196 ++++ .../flowy-grid/cell_entities.pbenum.dart | 7 + .../flowy-grid/cell_entities.pbjson.dart | 43 + .../flowy-grid/cell_entities.pbserver.dart | 9 + .../flowy-grid/dart_notification.pbenum.dart | 4 +- .../flowy-grid/dart_notification.pbjson.dart | 4 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 14 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 9 +- .../flowy-grid/field_entities.pb.dart | 72 ++ .../flowy-grid/field_entities.pbenum.dart | 7 + .../flowy-grid/field_entities.pbjson.dart | 21 + .../flowy-grid/field_entities.pbserver.dart | 9 + .../lib/protobuf/flowy-grid/protobuf.dart | 3 + .../protobuf/flowy-grid/row_entities.pb.dart | 72 ++ .../flowy-grid/row_entities.pbenum.dart | 7 + .../flowy-grid/row_entities.pbjson.dart | 21 + .../flowy-grid/row_entities.pbserver.dart | 9 + .../flowy-grid/selection_type_option.pb.dart | 181 +++- .../selection_type_option.pbjson.dart | 20 +- frontend/rust-lib/dart-ffi/Cargo.toml | 2 +- frontend/rust-lib/flowy-grid/Flowy.toml | 9 +- .../flowy-grid/src/dart_notification.rs | 2 +- .../rust-lib/flowy-grid/src/event_handler.rs | 155 +-- frontend/rust-lib/flowy-grid/src/event_map.rs | 24 +- .../src/protobuf/model/cell_entities.rs | 664 ++++++++++++ .../src/protobuf/model/dart_notification.rs | 12 +- .../src/protobuf/model/event_map.rs | 32 +- .../src/protobuf/model/field_entities.rs | 243 +++++ .../flowy-grid/src/protobuf/model/mod.rs | 9 + .../src/protobuf/model/row_entities.rs | 243 +++++ .../protobuf/model/selection_type_option.rs | 498 +++++++-- .../src/protobuf/proto/cell_entities.proto | 14 + .../protobuf/proto/dart_notification.proto | 2 +- .../src/protobuf/proto/event_map.proto | 7 +- .../src/protobuf/proto/field_entities.proto | 6 + .../src/protobuf/proto/row_entities.proto | 6 + .../proto/selection_type_option.proto | 6 + .../src/services/block_meta_editor.rs | 4 +- .../src/services/cell/cell_entities.rs | 69 ++ .../flowy-grid/src/services/cell/mod.rs | 3 + .../src/services/field/field_entities.rs | 30 + .../flowy-grid/src/services/field/mod.rs | 4 +- .../type_options/selection_type_option.rs | 154 ++- .../flowy-grid/src/services/grid_editor.rs | 50 +- .../rust-lib/flowy-grid/src/services/mod.rs | 1 + .../src/services/row/cell_data_operation.rs | 5 +- .../flowy-grid/src/services/row/mod.rs | 1 + .../src/services/row/row_entities.rs | 31 + .../flowy-grid/tests/grid/grid_test.rs | 13 +- shared-lib/flowy-error-code/src/code.rs | 4 + .../src/protobuf/model/code.rs | 15 +- .../src/protobuf/proto/code.proto | 2 + .../src/entities/grid.rs | 114 -- .../src/protobuf/model/grid.rs | 941 +---------------- .../src/protobuf/model/mod.rs | 3 + .../src/protobuf/model/type_option.rs | 978 ++++++++++++++++++ .../src/protobuf/proto/grid.proto | 17 - .../src/protobuf/proto/type_option.proto | 29 + .../src/client_grid/grid_meta_pad.rs | 113 +- 83 files changed, 4181 insertions(+), 1801 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/cell_bloc/select_option_service.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbserver.dart create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/model/cell_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/model/field_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/model/row_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/proto/cell_entities.proto create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/proto/field_entities.proto create mode 100644 frontend/rust-lib/flowy-grid/src/protobuf/proto/row_entities.proto create mode 100644 frontend/rust-lib/flowy-grid/src/services/cell/cell_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/cell/mod.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/field/field_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs create mode 100644 shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs create mode 100644 shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index c23b259bfe..58ad1cf9cc 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -188,7 +188,6 @@ void _resolveGridDeps(GetIt getIt) { getIt.registerFactoryParam( (cellData, _) => SelectionCellBloc( - service: CellService(), cellData: cellData, ), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index f7a0247a98..b36727adcc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -8,47 +8,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; class CellService { CellService(); - Future> addSelectOpiton({ - required String gridId, - required String fieldId, - required String rowId, - required String optionId, - }) { - final payload = SelectOptionChangesetPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..rowId = rowId - ..insertOptionId = optionId; - return GridEventApplySelectOptionChangeset(payload).send(); - } - - Future> getSelectOpitonContext({ - required String gridId, - required String fieldId, - required String rowId, - }) { - final payload = CellIdentifierPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..rowId = rowId; - - return GridEventGetSelectOptions(payload).send(); - } - - Future> removeSelectOpiton({ - required String gridId, - required String fieldId, - required String rowId, - required String optionId, - }) { - final payload = SelectOptionChangesetPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..rowId = rowId - ..deleteOptionId = optionId; - return GridEventApplySelectOptionChangeset(payload).send(); - } - Future> updateCell({ required String gridId, required String fieldId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/select_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/select_option_service.dart new file mode 100644 index 0000000000..ad0a1888b3 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/select_option_service.dart @@ -0,0 +1,109 @@ +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; + +class SelectOptionService { + SelectOptionService(); + + Future> create({ + required String gridId, + required String fieldId, + required String rowId, + required String name, + }) { + return GridEventNewSelectOption(SelectOptionName.create()..name = name).send().then( + (result) { + return result.fold( + (option) { + final cellIdentifier = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + final payload = SelectOptionChangesetPayload.create() + ..insertOption = option + ..cellIdentifier = cellIdentifier; + return GridEventApplySelectOptionChangeset(payload).send(); + }, + (r) => right(r), + ); + }, + ); + } + + Future> insert({ + required String gridId, + required String fieldId, + required String rowId, + required SelectOption option, + }) { + final cellIdentifier = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + final payload = SelectOptionChangesetPayload.create() + ..insertOption = option + ..cellIdentifier = cellIdentifier; + return GridEventApplySelectOptionChangeset(payload).send(); + } + + Future> delete({ + required String gridId, + required String fieldId, + required String rowId, + required SelectOption option, + }) { + final cellIdentifier = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + + final payload = SelectOptionChangesetPayload.create() + ..deleteOption = option + ..cellIdentifier = cellIdentifier; + + return GridEventApplySelectOptionChangeset(payload).send(); + } + + Future> getOpitonContext({ + required String gridId, + required String fieldId, + required String rowId, + }) { + final payload = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + + return GridEventGetSelectOptionContext(payload).send(); + } + + Future> select({ + required String gridId, + required String fieldId, + required String rowId, + required String optionId, + }) { + final payload = SelectOptionCellChangesetPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId + ..insertOptionId = optionId; + return GridEventApplySelectOptionCellChangeset(payload).send(); + } + + Future> remove({ + required String gridId, + required String fieldId, + required String rowId, + required String optionId, + }) { + final payload = SelectOptionCellChangesetPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId + ..deleteOptionId = optionId; + return GridEventApplySelectOptionCellChangeset(payload).send(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart index 48c11622fe..b12b56b827 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_cell_bloc.dart @@ -1,22 +1,21 @@ import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; +import 'package:app_flowy/workspace/application/grid/cell_bloc/select_option_service.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'cell_service.dart'; part 'selection_cell_bloc.freezed.dart'; class SelectionCellBloc extends Bloc { - final CellService _service; + final SelectOptionService _service; final CellListener _listener; SelectionCellBloc({ - required CellService service, required CellData cellData, - }) : _service = service, + }) : _service = SelectOptionService(), _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), super(SelectionCellState.initial(cellData)) { on( @@ -41,7 +40,7 @@ class SelectionCellBloc extends Bloc { } void _loadOptions() async { - final result = await _service.getSelectOpitonContext( + final result = await _service.getOpitonContext( gridId: state.cellData.gridId, fieldId: state.cellData.field.id, rowId: state.cellData.rowId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index 671dc7ae8a..c6396138a9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -1,56 +1,56 @@ +import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; -import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; -import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'cell_service.dart'; +import 'select_option_service.dart'; part 'selection_editor_bloc.freezed.dart'; class SelectOptionEditorBloc extends Bloc { - final TypeOptionService _typeOptionService; - final CellService _cellService; - final FieldListener _listener; + final SelectOptionService _selectOptionService; + final FieldListener _fieldListener; + final CellListener _cellListener; SelectOptionEditorBloc({ required CellData cellData, required List options, required List selectedOptions, - }) : _cellService = CellService(), - _typeOptionService = TypeOptionService(fieldId: cellData.field.id), - _listener = FieldListener(fieldId: cellData.field.id), + }) : _selectOptionService = SelectOptionService(), + _fieldListener = FieldListener(fieldId: cellData.field.id), + _cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), super(SelectOptionEditorState.initial(cellData, options, selectedOptions)) { on( (event, emit) async { await event.map( initial: (_Initial value) async { _startListening(); - _loadOptions(); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { emit(state.copyWith(field: value.field)); _loadOptions(); }, didReceiveOptions: (_DidReceiveOptions value) { - emit(state.copyWith(options: value.options)); + emit(state.copyWith( + options: value.options, + selectedOptions: value.selectedOptions, + )); }, - newOption: (_NewOption value) async { - final result = await _typeOptionService.createOption(value.optionName, selected: true); - result.fold((l) => null, (err) => Log.error(err)); + newOption: (_NewOption value) { + _createOption(value.optionName); + }, + deleteOption: (_DeleteOption value) { + _deleteOption(value.option); + }, + updateOption: (_UpdateOption value) { + _updateOption(value.option); }, selectOption: (_SelectOption value) { - _cellService.addSelectOpiton( - gridId: state.gridId, - fieldId: state.field.id, - rowId: state.rowId, - optionId: value.optionId, - ); + _makeOptionAsSelected(value.optionId); }, ); }, @@ -59,39 +59,84 @@ class SelectOptionEditorBloc extends Bloc close() async { - await _listener.stop(); + await _fieldListener.stop(); + await _cellListener.stop(); return super.close(); } + void _createOption(String name) async { + final result = await _selectOptionService.create( + gridId: state.gridId, + fieldId: state.field.id, + rowId: state.rowId, + name: name, + ); + result.fold((l) => _loadOptions(), (err) => Log.error(err)); + } + + void _deleteOption(SelectOption option) async { + final result = await _selectOptionService.delete( + gridId: state.gridId, + fieldId: state.field.id, + rowId: state.rowId, + option: option, + ); + + result.fold((l) => null, (err) => Log.error(err)); + } + + void _updateOption(SelectOption option) async { + final result = await _selectOptionService.insert( + gridId: state.gridId, + fieldId: state.field.id, + rowId: state.rowId, + option: option, + ); + + result.fold((l) => null, (err) => Log.error(err)); + } + + void _makeOptionAsSelected(String optionId) { + _selectOptionService.select( + gridId: state.gridId, + fieldId: state.field.id, + rowId: state.rowId, + optionId: optionId, + ); + } + + void _loadOptions() async { + final result = await _selectOptionService.getOpitonContext( + gridId: state.gridId, + fieldId: state.field.id, + rowId: state.rowId, + ); + + result.fold( + (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions( + selectOptionContext.options, + selectOptionContext.selectOptions, + )), + (err) => Log.error(err), + ); + } + void _startListening() { - _listener.updateFieldNotifier.addPublishListener((result) { + _cellListener.updateCellNotifier.addPublishListener((result) { + result.fold( + (notificationData) => _loadOptions(), + (err) => Log.error(err), + ); + }); + _cellListener.start(); + + _fieldListener.updateFieldNotifier.addPublishListener((result) { result.fold( (field) => add(SelectOptionEditorEvent.didReceiveFieldUpdate(field)), (err) => Log.error(err), ); }); - } - - void _loadOptions() async { - final result = await FieldContextLoaderAdaptor(gridId: state.gridId, field: state.field).load(); - result.fold( - (context) { - List options = []; - switch (state.field.fieldType) { - case FieldType.MultiSelect: - options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options); - break; - case FieldType.SingleSelect: - options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options); - break; - default: - Log.error("Invalid field type, expect single select or multiple select"); - break; - } - add(SelectOptionEditorEvent.didReceiveOptions(options)); - }, - (err) => Log.error(err), - ); + _fieldListener.start(); } } @@ -99,9 +144,12 @@ class SelectOptionEditorBloc extends Bloc options) = _DidReceiveOptions; + const factory SelectOptionEditorEvent.didReceiveOptions( + List options, List selectedOptions) = _DidReceiveOptions; const factory SelectOptionEditorEvent.newOption(String optionName) = _NewOption; const factory SelectOptionEditorEvent.selectOption(String optionId) = _SelectOption; + const factory SelectOptionEditorEvent.updateOption(SelectOption option) = _UpdateOption; + const factory SelectOptionEditorEvent.deleteOption(SelectOption option) = _DeleteOption; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart index 4556e17d38..dd27f66070 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart @@ -48,7 +48,7 @@ class FieldEditorBloc extends Bloc { () async => null, (field) async { field.name = state.fieldName; - final result = await service.createField( + final result = await service.insertField( field: field, typeOptionData: state.typeOptionData, ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 61ccad6b81..3ea1c46062 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -4,6 +4,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; class FieldService { final String gridId; @@ -60,7 +61,7 @@ class FieldService { } // Create the field if it does not exist. Otherwise, update the field. - Future> createField({ + Future> insertField({ required Field field, List? typeOptionData, String? startFieldId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart index fa92d84b79..434b343d8d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_listenr.dart @@ -24,7 +24,7 @@ class GridFieldsListener { void _handler(GridNotification ty, Either result) { switch (ty) { - case GridNotification.DidUpdateFields: + case GridNotification.DidUpdateGrid: result.fold( (payload) => updateFieldsNotifier.value = left(RepeatedField.fromBuffer(payload).items), (error) => updateFieldsNotifier.value = right(error), diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart index 0a96f5f69b..c5a55e20e1 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart @@ -18,7 +18,7 @@ class MultiSelectTypeOptionBloc extends Bloc> createOption(String name, {bool selected = false}) { - final payload = CreateSelectOptionPayload.create() - ..optionName = name - ..selected = selected; - return GridEventCreateSelectOption(payload).send(); + Future> newOption(String name, {bool selected = false}) { + final payload = SelectOptionName.create()..name = name; + return GridEventNewSelectOption(payload).send(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 8875f9dc98..8b2548b1b2 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; class RowService { final String gridId; @@ -20,7 +21,7 @@ class RowService { } Future> getRow() { - QueryRowPayload payload = QueryRowPayload.create() + final payload = RowIdentifierPayload.create() ..gridId = gridId ..rowId = rowId; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index 9a91999a9d..1b3a81704d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -67,13 +67,16 @@ class SelectOptionTextField extends StatelessWidget { final FocusNode _focusNode; final TextEditingController _controller; final TextfieldTagsController tagController; - final LinkedHashMap optionMap; + final List options; + final LinkedHashMap selectedOptionMap; + final double distanceToText; final Function(String) onNewTag; SelectOptionTextField({ - required this.optionMap, + required this.options, + required this.selectedOptionMap, required this.distanceToText, required this.tagController, required this.onNewTag, @@ -91,12 +94,14 @@ class SelectOptionTextField extends StatelessWidget { return TextFieldTags( textEditingController: _controller, textfieldTagsController: tagController, - initialTags: optionMap.keys.toList(), + initialTags: selectedOptionMap.keys.toList(), focusNode: _focusNode, textSeparators: const [' ', ','], inputfieldBuilder: (BuildContext context, editController, focusNode, error, onChanged, onSubmitted) { return ((context, sc, tags, onTagDelegate) { - tags.retainWhere((name) => optionMap.containsKey(name) == false); + tags.retainWhere((name) { + return options.where((option) => option.name == name).isEmpty; + }); if (tags.isNotEmpty) { assert(tags.length == 1); onNewTag(tags.first); @@ -133,11 +138,11 @@ class SelectOptionTextField extends StatelessWidget { } Widget? _renderTags(ScrollController sc) { - if (optionMap.isEmpty) { + if (selectedOptionMap.isEmpty) { return null; } - final children = optionMap.values.map((option) => SelectOptionTag(option: option)).toList(); + final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList(); return Padding( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 33a935d37e..2187325c95 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -1,7 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index d10a5a8cf8..1df2cd03b6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -3,10 +3,12 @@ import 'dart:collection'; import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; @@ -21,7 +23,7 @@ import 'extension.dart'; const double _editorPannelWidth = 300; -class SelectOptionEditor extends StatelessWidget { +class SelectOptionEditor extends StatelessWidget with FlowyOverlayDelegate { final CellData cellData; final List options; final List selectedOptions; @@ -44,7 +46,7 @@ class SelectOptionEditor extends StatelessWidget { cellData: cellData, options: options, selectedOptions: selectedOptions, - ), + )..add(const SelectOptionEditorEvent.initial()), child: BlocBuilder( builder: (context, state) { return CustomScrollView( @@ -83,12 +85,16 @@ class SelectOptionEditor extends StatelessWidget { identifier: SelectOptionEditor.identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomWithCenterAligned, + delegate: editor, ); } static void hide(BuildContext context) { FlowyOverlay.of(context).remove(identifier()); } + + @override + bool asBarrier() => true; } class _OptionList extends StatelessWidget { @@ -126,18 +132,19 @@ class _TextField extends StatelessWidget { Widget build(BuildContext context) { return BlocConsumer( listener: (context, state) {}, - buildWhen: (previous, current) => previous.field.id != current.field.id, builder: (context, state) { final optionMap = LinkedHashMap.fromIterable(state.selectedOptions, key: (option) => option.name, value: (option) => option); + return SizedBox( height: 42, child: SelectOptionTextField( - optionMap: optionMap, + options: state.options, + selectedOptionMap: optionMap, distanceToText: _editorPannelWidth * 0.7, tagController: _tagController, - onNewTag: (newTagName) { - context.read().add(SelectOptionEditorEvent.newOption(newTagName)); + onNewTag: (tagName) { + context.read().add(SelectOptionEditorEvent.newOption(tagName)); }, ), ); @@ -188,7 +195,12 @@ class _SelectOptionCell extends StatelessWidget { ]; if (onHover) { - children.add(svgWidget("editor/details", color: theme.iconColor)); + children.add(FlowyIconButton( + width: 28, + onPressed: () => _showEditOptionPannel(context), + iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), + icon: svgWidget("editor/details", color: theme.iconColor), + )); } return Padding( @@ -200,4 +212,30 @@ class _SelectOptionCell extends StatelessWidget { ), ); } + + void _showEditOptionPannel(BuildContext context) { + final pannel = EditSelectOptionPannel( + option: option, + onDeleted: () { + context.read().add(SelectOptionEditorEvent.deleteOption(option)); + }, + onUpdated: (updatedOption) { + context.read().add(SelectOptionEditorEvent.updateOption(updatedOption)); + }, + // key: ValueKey(option.id), + ); + final overlayIdentifier = pannel.toString(); + + FlowyOverlay.of(context).remove(overlayIdentifier); + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + child: pannel, + constraints: BoxConstraints.loose(const Size(200, 300)), + ), + identifier: overlayIdentifier, + anchorContext: context, + anchorDirection: AnchorDirection.rightWithCenterAligned, + anchorOffset: Offset(2 * overlayContainerPadding.left, 0), + ); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart index 7c93f63ee7..034accfb19 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart @@ -165,7 +165,6 @@ class _OptionList extends StatelessWidget { delegate.hideOverlay(context); context.read().add(OptionPannelEvent.updateOption(updatedOption)); }, - key: ValueKey(option.id), ); delegate.showOverlay(context, pannel); }, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart index b1f18b6695..85de2c71a7 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/overlay_container.dart @@ -3,6 +3,8 @@ import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +const overlayContainerPadding = EdgeInsets.all(12); + class OverlayContainer extends StatelessWidget { final Widget child; final BoxConstraints? constraints; @@ -10,7 +12,7 @@ class OverlayContainer extends StatelessWidget { const OverlayContainer({ required this.child, this.constraints, - this.padding = const EdgeInsets.all(12), + this.padding = overlayContainerPadding, Key? key, }) : super(key: key); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 2a23cfad4a..3003b4c6f8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -154,13 +154,13 @@ class GridEventGetEditFieldContext { } } -class GridEventCreateSelectOption { - CreateSelectOptionPayload request; - GridEventCreateSelectOption(this.request); +class GridEventNewSelectOption { + SelectOptionName request; + GridEventNewSelectOption(this.request); Future> send() { final request = FFIRequest.create() - ..event = GridEvent.CreateSelectOption.toString() + ..event = GridEvent.NewSelectOption.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) @@ -171,13 +171,13 @@ class GridEventCreateSelectOption { } } -class GridEventGetSelectOptions { +class GridEventGetSelectOptionContext { CellIdentifierPayload request; - GridEventGetSelectOptions(this.request); + GridEventGetSelectOptionContext(this.request); Future> send() { final request = FFIRequest.create() - ..event = GridEvent.GetSelectOptions.toString() + ..event = GridEvent.GetSelectOptionContext.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) @@ -188,6 +188,23 @@ class GridEventGetSelectOptions { } } +class GridEventApplySelectOptionChangeset { + SelectOptionChangesetPayload request; + GridEventApplySelectOptionChangeset(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.ApplySelectOptionChangeset.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventCreateRow { CreateRowPayload request; GridEventCreateRow(this.request); @@ -206,7 +223,7 @@ class GridEventCreateRow { } class GridEventGetRow { - QueryRowPayload request; + RowIdentifierPayload request; GridEventGetRow(this.request); Future> send() { @@ -239,13 +256,13 @@ class GridEventUpdateCell { } } -class GridEventApplySelectOptionChangeset { - SelectOptionChangesetPayload request; - GridEventApplySelectOptionChangeset(this.request); +class GridEventApplySelectOptionCellChangeset { + SelectOptionCellChangesetPayload request; + GridEventApplySelectOptionCellChangeset(this.request); Future> send() { final request = FFIRequest.create() - ..event = GridEvent.ApplySelectOptionChangeset.toString() + ..event = GridEvent.ApplySelectOptionCellChangeset.toString() ..payload = requestToBytes(this.request); return Dispatch.asyncRequest(request) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index e2be9f11a2..db010e9f75 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -4,6 +4,9 @@ import 'package:flowy_sdk/log.dart'; // ignore: unnecessary_import import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart index a638e65405..0d1eabddf8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart @@ -49,6 +49,8 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty'); static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist'); static const ErrorCode SelectOptionNameIsEmpty = ErrorCode._(442, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SelectOptionNameIsEmpty'); + static const ErrorCode FieldNotExists = ErrorCode._(443, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldNotExists'); + static const ErrorCode FieldInvalidOperation = ErrorCode._(444, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldInvalidOperation'); static const ErrorCode TypeOptionDataIsEmpty = ErrorCode._(450, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionDataIsEmpty'); static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData'); @@ -92,6 +94,8 @@ class ErrorCode extends $pb.ProtobufEnum { FieldIdIsEmpty, FieldDoesNotExist, SelectOptionNameIsEmpty, + FieldNotExists, + FieldInvalidOperation, TypeOptionDataIsEmpty, InvalidData, ]; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart index 625e2d9572..fa6ba4076b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart @@ -51,10 +51,12 @@ const ErrorCode$json = const { const {'1': 'FieldIdIsEmpty', '2': 440}, const {'1': 'FieldDoesNotExist', '2': 441}, const {'1': 'SelectOptionNameIsEmpty', '2': 442}, + const {'1': 'FieldNotExists', '2': 443}, + const {'1': 'FieldInvalidOperation', '2': 444}, const {'1': 'TypeOptionDataIsEmpty', '2': 450}, const {'1': 'InvalidData', '2': 500}, ], }; /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxIUCg9PcHRpb25JZElzRW1wdHkQrwMSEwoORmllbGRJZElzRW1wdHkQuAMSFgoRRmllbGREb2VzTm90RXhpc3QQuQMSHAoXU2VsZWN0T3B0aW9uTmFtZUlzRW1wdHkQugMSGgoVVHlwZU9wdGlvbkRhdGFJc0VtcHR5EMIDEhAKC0ludmFsaWREYXRhEPQD'); +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxIUCg9PcHRpb25JZElzRW1wdHkQrwMSEwoORmllbGRJZElzRW1wdHkQuAMSFgoRRmllbGREb2VzTm90RXhpc3QQuQMSHAoXU2VsZWN0T3B0aW9uTmFtZUlzRW1wdHkQugMSEwoORmllbGROb3RFeGlzdHMQuwMSGgoVRmllbGRJbnZhbGlkT3BlcmF0aW9uELwDEhoKFVR5cGVPcHRpb25EYXRhSXNFbXB0eRDCAxIQCgtJbnZhbGlkRGF0YRD0Aw=='); 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 2cd87115bf..e27e019be3 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 @@ -205,67 +205,6 @@ class Field extends $pb.GeneratedMessage { void clearWidth() => clearField(7); } -class FieldIdentifierPayload extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierPayload', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..hasRequiredFields = false - ; - - FieldIdentifierPayload._() : super(); - factory FieldIdentifierPayload({ - $core.String? fieldId, - $core.String? gridId, - }) { - final _result = create(); - if (fieldId != null) { - _result.fieldId = fieldId; - } - if (gridId != null) { - _result.gridId = gridId; - } - return _result; - } - factory FieldIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory FieldIdentifierPayload.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') - FieldIdentifierPayload clone() => FieldIdentifierPayload()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - FieldIdentifierPayload copyWith(void Function(FieldIdentifierPayload) updates) => super.copyWith((message) => updates(message as FieldIdentifierPayload)) as FieldIdentifierPayload; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static FieldIdentifierPayload create() => FieldIdentifierPayload._(); - FieldIdentifierPayload createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static FieldIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static FieldIdentifierPayload? _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.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); -} - 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') @@ -1024,81 +963,6 @@ class Cell extends $pb.GeneratedMessage { void clearContent() => clearField(2); } -class CellIdentifierPayload extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellIdentifierPayload', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') - ..hasRequiredFields = false - ; - - CellIdentifierPayload._() : super(); - factory CellIdentifierPayload({ - $core.String? gridId, - $core.String? fieldId, - $core.String? rowId, - }) { - final _result = create(); - if (gridId != null) { - _result.gridId = gridId; - } - if (fieldId != null) { - _result.fieldId = fieldId; - } - if (rowId != null) { - _result.rowId = rowId; - } - return _result; - } - factory CellIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CellIdentifierPayload.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') - CellIdentifierPayload clone() => CellIdentifierPayload()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - CellIdentifierPayload copyWith(void Function(CellIdentifierPayload) updates) => super.copyWith((message) => updates(message as CellIdentifierPayload)) as CellIdentifierPayload; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static CellIdentifierPayload create() => CellIdentifierPayload._(); - CellIdentifierPayload createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static CellIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CellIdentifierPayload? _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 fieldId => $_getSZ(1); - @$pb.TagNumber(2) - set fieldId($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasFieldId() => $_has(1); - @$pb.TagNumber(2) - void clearFieldId() => clearField(2); - - @$pb.TagNumber(3) - $core.String get rowId => $_getSZ(2); - @$pb.TagNumber(3) - set rowId($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasRowId() => $_has(2); - @$pb.TagNumber(3) - void clearRowId() => clearField(3); -} - enum CellNotificationData_OneOfContent { content, notSet @@ -1679,125 +1543,3 @@ class QueryGridBlocksPayload extends $pb.GeneratedMessage { $core.List get blockOrders => $_getList(1); } -class QueryRowPayload extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'QueryRowPayload', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') - ..hasRequiredFields = false - ; - - QueryRowPayload._() : super(); - factory QueryRowPayload({ - $core.String? gridId, - $core.String? rowId, - }) { - final _result = create(); - if (gridId != null) { - _result.gridId = gridId; - } - if (rowId != null) { - _result.rowId = rowId; - } - return _result; - } - factory QueryRowPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory QueryRowPayload.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') - QueryRowPayload clone() => QueryRowPayload()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - QueryRowPayload copyWith(void Function(QueryRowPayload) updates) => super.copyWith((message) => updates(message as QueryRowPayload)) as QueryRowPayload; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static QueryRowPayload create() => QueryRowPayload._(); - QueryRowPayload createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static QueryRowPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static QueryRowPayload? _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(3) - $core.String get rowId => $_getSZ(1); - @$pb.TagNumber(3) - set rowId($core.String v) { $_setString(1, v); } - @$pb.TagNumber(3) - $core.bool hasRowId() => $_has(1); - @$pb.TagNumber(3) - void clearRowId() => clearField(3); -} - -class CreateSelectOptionPayload extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateSelectOptionPayload', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'optionName') - ..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selected') - ..hasRequiredFields = false - ; - - CreateSelectOptionPayload._() : super(); - factory CreateSelectOptionPayload({ - $core.String? optionName, - $core.bool? selected, - }) { - final _result = create(); - if (optionName != null) { - _result.optionName = optionName; - } - if (selected != null) { - _result.selected = selected; - } - return _result; - } - factory CreateSelectOptionPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CreateSelectOptionPayload.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') - CreateSelectOptionPayload clone() => CreateSelectOptionPayload()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - CreateSelectOptionPayload copyWith(void Function(CreateSelectOptionPayload) updates) => super.copyWith((message) => updates(message as CreateSelectOptionPayload)) as CreateSelectOptionPayload; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static CreateSelectOptionPayload create() => CreateSelectOptionPayload._(); - CreateSelectOptionPayload createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static CreateSelectOptionPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CreateSelectOptionPayload? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get optionName => $_getSZ(0); - @$pb.TagNumber(1) - set optionName($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasOptionName() => $_has(0); - @$pb.TagNumber(1) - void clearOptionName() => clearField(1); - - @$pb.TagNumber(2) - $core.bool get selected => $_getBF(1); - @$pb.TagNumber(2) - set selected($core.bool v) { $_setBool(1, v); } - @$pb.TagNumber(2) - $core.bool hasSelected() => $_has(1); - @$pb.TagNumber(2) - void clearSelected() => clearField(2); -} - 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 cf58ec74a2..3cd228af79 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 @@ -36,17 +36,6 @@ const Field$json = const { /// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aA=='); -@$core.Deprecated('Use fieldIdentifierPayloadDescriptor instead') -const FieldIdentifierPayload$json = const { - '1': 'FieldIdentifierPayload', - '2': const [ - const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, - ], -}; - -/// Descriptor for `FieldIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldIdentifierPayloadDescriptor = $convert.base64Decode('ChZGaWVsZElkZW50aWZpZXJQYXlsb2FkEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZA=='); @$core.Deprecated('Use fieldOrderDescriptor instead') const FieldOrder$json = const { '1': 'FieldOrder', @@ -203,18 +192,6 @@ const Cell$json = const { /// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhgKB2NvbnRlbnQYAiABKAlSB2NvbnRlbnQ='); -@$core.Deprecated('Use cellIdentifierPayloadDescriptor instead') -const CellIdentifierPayload$json = const { - '1': 'CellIdentifierPayload', - '2': const [ - const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, - const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, - ], -}; - -/// Descriptor for `CellIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List cellIdentifierPayloadDescriptor = $convert.base64Decode('ChVDZWxsSWRlbnRpZmllclBheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); @$core.Deprecated('Use cellNotificationDataDescriptor instead') const CellNotificationData$json = const { '1': 'CellNotificationData', @@ -323,25 +300,3 @@ const QueryGridBlocksPayload$json = const { /// Descriptor for `QueryGridBlocksPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List queryGridBlocksPayloadDescriptor = $convert.base64Decode('ChZRdWVyeUdyaWRCbG9ja3NQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIyCgxibG9ja19vcmRlcnMYAiADKAsyDy5HcmlkQmxvY2tPcmRlclILYmxvY2tPcmRlcnM='); -@$core.Deprecated('Use queryRowPayloadDescriptor instead') -const QueryRowPayload$json = const { - '1': 'QueryRowPayload', - '2': const [ - const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, - const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, - ], -}; - -/// Descriptor for `QueryRowPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List queryRowPayloadDescriptor = $convert.base64Decode('Cg9RdWVyeVJvd1BheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); -@$core.Deprecated('Use createSelectOptionPayloadDescriptor instead') -const CreateSelectOptionPayload$json = const { - '1': 'CreateSelectOptionPayload', - '2': const [ - const {'1': 'option_name', '3': 1, '4': 1, '5': 9, '10': 'optionName'}, - const {'1': 'selected', '3': 2, '4': 1, '5': 8, '10': 'selected'}, - ], -}; - -/// Descriptor for `CreateSelectOptionPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEh8KC29wdGlvbl9uYW1lGAEgASgJUgpvcHRpb25OYW1lEhoKCHNlbGVjdGVkGAIgASgIUghzZWxlY3RlZA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart index 2c253e0494..6cedb363ef 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart @@ -1,3 +1,3 @@ -// Auto-generated, do not edit +// Auto-generated, do not edit export './grid.pb.dart'; export './meta.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pb.dart new file mode 100644 index 0000000000..259fcf1422 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pb.dart @@ -0,0 +1,196 @@ +/// +// Generated code. Do not modify. +// source: cell_entities.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:protobuf/protobuf.dart' as $pb; + +class CreateSelectOptionPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateSelectOptionPayload', createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cellIdentifier', subBuilder: CellIdentifierPayload.create) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'optionName') + ..hasRequiredFields = false + ; + + CreateSelectOptionPayload._() : super(); + factory CreateSelectOptionPayload({ + CellIdentifierPayload? cellIdentifier, + $core.String? optionName, + }) { + final _result = create(); + if (cellIdentifier != null) { + _result.cellIdentifier = cellIdentifier; + } + if (optionName != null) { + _result.optionName = optionName; + } + return _result; + } + factory CreateSelectOptionPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateSelectOptionPayload.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') + CreateSelectOptionPayload clone() => CreateSelectOptionPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CreateSelectOptionPayload copyWith(void Function(CreateSelectOptionPayload) updates) => super.copyWith((message) => updates(message as CreateSelectOptionPayload)) as CreateSelectOptionPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateSelectOptionPayload create() => CreateSelectOptionPayload._(); + CreateSelectOptionPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CreateSelectOptionPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateSelectOptionPayload? _defaultInstance; + + @$pb.TagNumber(1) + CellIdentifierPayload get cellIdentifier => $_getN(0); + @$pb.TagNumber(1) + set cellIdentifier(CellIdentifierPayload v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasCellIdentifier() => $_has(0); + @$pb.TagNumber(1) + void clearCellIdentifier() => clearField(1); + @$pb.TagNumber(1) + CellIdentifierPayload ensureCellIdentifier() => $_ensure(0); + + @$pb.TagNumber(2) + $core.String get optionName => $_getSZ(1); + @$pb.TagNumber(2) + set optionName($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasOptionName() => $_has(1); + @$pb.TagNumber(2) + void clearOptionName() => clearField(2); +} + +class CellIdentifierPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellIdentifierPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..hasRequiredFields = false + ; + + CellIdentifierPayload._() : super(); + factory CellIdentifierPayload({ + $core.String? gridId, + $core.String? fieldId, + $core.String? rowId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (rowId != null) { + _result.rowId = rowId; + } + return _result; + } + factory CellIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CellIdentifierPayload.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') + CellIdentifierPayload clone() => CellIdentifierPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CellIdentifierPayload copyWith(void Function(CellIdentifierPayload) updates) => super.copyWith((message) => updates(message as CellIdentifierPayload)) as CellIdentifierPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CellIdentifierPayload create() => CellIdentifierPayload._(); + CellIdentifierPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CellIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CellIdentifierPayload? _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 fieldId => $_getSZ(1); + @$pb.TagNumber(2) + set fieldId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasFieldId() => $_has(1); + @$pb.TagNumber(2) + void clearFieldId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get rowId => $_getSZ(2); + @$pb.TagNumber(3) + set rowId($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasRowId() => $_has(2); + @$pb.TagNumber(3) + void clearRowId() => clearField(3); +} + +class SelectOptionName extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionName', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..hasRequiredFields = false + ; + + SelectOptionName._() : super(); + factory SelectOptionName({ + $core.String? name, + }) { + final _result = create(); + if (name != null) { + _result.name = name; + } + return _result; + } + factory SelectOptionName.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectOptionName.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') + SelectOptionName clone() => SelectOptionName()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectOptionName copyWith(void Function(SelectOptionName) updates) => super.copyWith((message) => updates(message as SelectOptionName)) as SelectOptionName; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SelectOptionName create() => SelectOptionName._(); + SelectOptionName createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectOptionName getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectOptionName? _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); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbenum.dart new file mode 100644 index 0000000000..a53c27b1fe --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: cell_entities.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 + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbjson.dart new file mode 100644 index 0000000000..ac0c9add9c --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbjson.dart @@ -0,0 +1,43 @@ +/// +// Generated code. Do not modify. +// source: cell_entities.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 createSelectOptionPayloadDescriptor instead') +const CreateSelectOptionPayload$json = const { + '1': 'CreateSelectOptionPayload', + '2': const [ + const {'1': 'cell_identifier', '3': 1, '4': 1, '5': 11, '6': '.CellIdentifierPayload', '10': 'cellIdentifier'}, + const {'1': 'option_name', '3': 2, '4': 1, '5': 9, '10': 'optionName'}, + ], +}; + +/// Descriptor for `CreateSelectOptionPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEj8KD2NlbGxfaWRlbnRpZmllchgBIAEoCzIWLkNlbGxJZGVudGlmaWVyUGF5bG9hZFIOY2VsbElkZW50aWZpZXISHwoLb3B0aW9uX25hbWUYAiABKAlSCm9wdGlvbk5hbWU='); +@$core.Deprecated('Use cellIdentifierPayloadDescriptor instead') +const CellIdentifierPayload$json = const { + '1': 'CellIdentifierPayload', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, + ], +}; + +/// Descriptor for `CellIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List cellIdentifierPayloadDescriptor = $convert.base64Decode('ChVDZWxsSWRlbnRpZmllclBheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ='); +@$core.Deprecated('Use selectOptionNameDescriptor instead') +const SelectOptionName$json = const { + '1': 'SelectOptionName', + '2': const [ + const {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'}, + ], +}; + +/// Descriptor for `SelectOptionName`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionNameDescriptor = $convert.base64Decode('ChBTZWxlY3RPcHRpb25OYW1lEhIKBG5hbWUYASABKAlSBG5hbWU='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbserver.dart new file mode 100644 index 0000000000..a0f185bca8 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/cell_entities.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: cell_entities.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 'cell_entities.pb.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 index 8f1cd90c29..4331fef2a7 100644 --- 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 @@ -15,7 +15,7 @@ class GridNotification extends $pb.ProtobufEnum { static const GridNotification DidUpdateBlock = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateBlock'); static const GridNotification DidUpdateRow = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification DidUpdateCell = GridNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateCell'); - static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); + static const GridNotification DidUpdateGrid = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateGrid'); static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField'); static const $core.List values = [ @@ -24,7 +24,7 @@ class GridNotification extends $pb.ProtobufEnum { DidUpdateBlock, DidUpdateRow, DidUpdateCell, - DidUpdateFields, + DidUpdateGrid, DidUpdateField, ]; 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 index 504d7e56f5..ed6bbdc2d4 100644 --- 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 @@ -17,10 +17,10 @@ const GridNotification$json = const { const {'1': 'DidUpdateBlock', '2': 20}, const {'1': 'DidUpdateRow', '2': 30}, const {'1': 'DidUpdateCell', '2': 31}, - const {'1': 'DidUpdateFields', '2': 40}, + const {'1': 'DidUpdateGrid', '2': 40}, const {'1': 'DidUpdateField', '2': 41}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEQoNRGlkVXBkYXRlQ2VsbBAfEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhIKDkRpZFVwZGF0ZUJsb2NrEBQSEAoMRGlkVXBkYXRlUm93EB4SEQoNRGlkVXBkYXRlQ2VsbBAfEhEKDURpZFVwZGF0ZUdyaWQQKBISCg5EaWRVcGRhdGVGaWVsZBAp'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 4c8cff633b..7c190dcd98 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -19,12 +19,13 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent SwitchToField = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SwitchToField'); static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); static const GridEvent GetEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetEditFieldContext'); - static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption'); - static const GridEvent GetSelectOptions = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptions'); + static const GridEvent NewSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewSelectOption'); + static const GridEvent GetSelectOptionContext = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptionContext'); + static const GridEvent ApplySelectOptionChangeset = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset'); static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); - static const GridEvent ApplySelectOptionChangeset = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset'); + static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset'); static const $core.List values = [ GetGridData, @@ -36,12 +37,13 @@ class GridEvent extends $pb.ProtobufEnum { SwitchToField, DuplicateField, GetEditFieldContext, - CreateSelectOption, - GetSelectOptions, + NewSelectOption, + GetSelectOptionContext, + ApplySelectOptionChangeset, CreateRow, GetRow, UpdateCell, - ApplySelectOptionChangeset, + ApplySelectOptionCellChangeset, ]; static final $core.Map<$core.int, GridEvent> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 017dc4b1aa..1c07877726 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -21,14 +21,15 @@ const GridEvent$json = const { const {'1': 'SwitchToField', '2': 14}, const {'1': 'DuplicateField', '2': 15}, const {'1': 'GetEditFieldContext', '2': 16}, - const {'1': 'CreateSelectOption', '2': 30}, - const {'1': 'GetSelectOptions', '2': 31}, + const {'1': 'NewSelectOption', '2': 30}, + const {'1': 'GetSelectOptionContext', '2': 31}, + const {'1': 'ApplySelectOptionChangeset', '2': 32}, const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, const {'1': 'UpdateCell', '2': 70}, - const {'1': 'ApplySelectOptionChangeset', '2': 71}, + const {'1': 'ApplySelectOptionCellChangeset', '2': 71}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhYKEkNyZWF0ZVNlbGVjdE9wdGlvbhAeEhQKEEdldFNlbGVjdE9wdGlvbnMQHxINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxIOCgpVcGRhdGVDZWxsEEYSHgoaQXBwbHlTZWxlY3RPcHRpb25DaGFuZ2VzZXQQRw=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg4KClVwZGF0ZUNlbGwQRhIiCh5BcHBseVNlbGVjdE9wdGlvbkNlbGxDaGFuZ2VzZXQQRw=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pb.dart new file mode 100644 index 0000000000..a99c401bf2 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pb.dart @@ -0,0 +1,72 @@ +/// +// Generated code. Do not modify. +// source: field_entities.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:protobuf/protobuf.dart' as $pb; + +class FieldIdentifierPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..hasRequiredFields = false + ; + + FieldIdentifierPayload._() : super(); + factory FieldIdentifierPayload({ + $core.String? fieldId, + $core.String? gridId, + }) { + final _result = create(); + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (gridId != null) { + _result.gridId = gridId; + } + return _result; + } + factory FieldIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FieldIdentifierPayload.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') + FieldIdentifierPayload clone() => FieldIdentifierPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + FieldIdentifierPayload copyWith(void Function(FieldIdentifierPayload) updates) => super.copyWith((message) => updates(message as FieldIdentifierPayload)) as FieldIdentifierPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static FieldIdentifierPayload create() => FieldIdentifierPayload._(); + FieldIdentifierPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static FieldIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FieldIdentifierPayload? _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.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); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbenum.dart new file mode 100644 index 0000000000..e9ca968924 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: field_entities.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 + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbjson.dart new file mode 100644 index 0000000000..e8b768c21a --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbjson.dart @@ -0,0 +1,21 @@ +/// +// Generated code. Do not modify. +// source: field_entities.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 fieldIdentifierPayloadDescriptor instead') +const FieldIdentifierPayload$json = const { + '1': 'FieldIdentifierPayload', + '2': const [ + const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'}, + ], +}; + +/// Descriptor for `FieldIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List fieldIdentifierPayloadDescriptor = $convert.base64Decode('ChZGaWVsZElkZW50aWZpZXJQYXlsb2FkEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbserver.dart new file mode 100644 index 0000000000..9c99be4d1d --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/field_entities.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: field_entities.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 'field_entities.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 874107f9be..af6583c106 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,7 +1,10 @@ // Auto-generated, do not edit +export './field_entities.pb.dart'; export './number_type_option.pb.dart'; export './dart_notification.pb.dart'; export './selection_type_option.pb.dart'; +export './row_entities.pb.dart'; +export './cell_entities.pb.dart'; export './checkbox_type_option.pb.dart'; export './event_map.pb.dart'; export './text_type_option.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pb.dart new file mode 100644 index 0000000000..8f8c278b12 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pb.dart @@ -0,0 +1,72 @@ +/// +// Generated code. Do not modify. +// source: row_entities.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:protobuf/protobuf.dart' as $pb; + +class RowIdentifierPayload extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RowIdentifierPayload', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..hasRequiredFields = false + ; + + RowIdentifierPayload._() : super(); + factory RowIdentifierPayload({ + $core.String? gridId, + $core.String? rowId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (rowId != null) { + _result.rowId = rowId; + } + return _result; + } + factory RowIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RowIdentifierPayload.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') + RowIdentifierPayload clone() => RowIdentifierPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + RowIdentifierPayload copyWith(void Function(RowIdentifierPayload) updates) => super.copyWith((message) => updates(message as RowIdentifierPayload)) as RowIdentifierPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RowIdentifierPayload create() => RowIdentifierPayload._(); + RowIdentifierPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static RowIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static RowIdentifierPayload? _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(3) + $core.String get rowId => $_getSZ(1); + @$pb.TagNumber(3) + set rowId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(3) + $core.bool hasRowId() => $_has(1); + @$pb.TagNumber(3) + void clearRowId() => clearField(3); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbenum.dart new file mode 100644 index 0000000000..a53bd30bf7 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: row_entities.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 + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbjson.dart new file mode 100644 index 0000000000..b5dd44d360 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbjson.dart @@ -0,0 +1,21 @@ +/// +// Generated code. Do not modify. +// source: row_entities.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 rowIdentifierPayloadDescriptor instead') +const RowIdentifierPayload$json = const { + '1': 'RowIdentifierPayload', + '2': const [ + const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, + const {'1': 'row_id', '3': 3, '4': 1, '5': 9, '10': 'rowId'}, + ], +}; + +/// Descriptor for `RowIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List rowIdentifierPayloadDescriptor = $convert.base64Decode('ChRSb3dJZGVudGlmaWVyUGF5bG9hZBIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSFQoGcm93X2lkGAMgASgJUgVyb3dJZA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbserver.dart new file mode 100644 index 0000000000..905505060a --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/row_entities.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: row_entities.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 'row_entities.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart index 350806f275..5b2576d7eb 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart @@ -9,6 +9,8 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; +import 'cell_entities.pb.dart' as $0; + import 'selection_type_option.pbenum.dart'; export 'selection_type_option.pbenum.dart'; @@ -198,59 +200,49 @@ class SelectOption extends $pb.GeneratedMessage { void clearColor() => clearField(3); } -enum SelectOptionChangesetPayload_OneOfInsertOptionId { - insertOptionId, +enum SelectOptionChangesetPayload_OneOfInsertOption { + insertOption, notSet } -enum SelectOptionChangesetPayload_OneOfDeleteOptionId { - deleteOptionId, +enum SelectOptionChangesetPayload_OneOfDeleteOption { + deleteOption, notSet } class SelectOptionChangesetPayload extends $pb.GeneratedMessage { - static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfInsertOptionId> _SelectOptionChangesetPayload_OneOfInsertOptionIdByTag = { - 4 : SelectOptionChangesetPayload_OneOfInsertOptionId.insertOptionId, - 0 : SelectOptionChangesetPayload_OneOfInsertOptionId.notSet + static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfInsertOption> _SelectOptionChangesetPayload_OneOfInsertOptionByTag = { + 2 : SelectOptionChangesetPayload_OneOfInsertOption.insertOption, + 0 : SelectOptionChangesetPayload_OneOfInsertOption.notSet }; - static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfDeleteOptionId> _SelectOptionChangesetPayload_OneOfDeleteOptionIdByTag = { - 5 : SelectOptionChangesetPayload_OneOfDeleteOptionId.deleteOptionId, - 0 : SelectOptionChangesetPayload_OneOfDeleteOptionId.notSet + static const $core.Map<$core.int, SelectOptionChangesetPayload_OneOfDeleteOption> _SelectOptionChangesetPayload_OneOfDeleteOptionByTag = { + 3 : SelectOptionChangesetPayload_OneOfDeleteOption.deleteOption, + 0 : SelectOptionChangesetPayload_OneOfDeleteOption.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionChangesetPayload', createEmptyInstance: create) - ..oo(0, [4]) - ..oo(1, [5]) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOptionId') - ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOptionId') + ..oo(0, [2]) + ..oo(1, [3]) + ..aOM<$0.CellIdentifierPayload>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'cellIdentifier', subBuilder: $0.CellIdentifierPayload.create) + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOption', subBuilder: SelectOption.create) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOption', subBuilder: SelectOption.create) ..hasRequiredFields = false ; SelectOptionChangesetPayload._() : super(); factory SelectOptionChangesetPayload({ - $core.String? gridId, - $core.String? rowId, - $core.String? fieldId, - $core.String? insertOptionId, - $core.String? deleteOptionId, + $0.CellIdentifierPayload? cellIdentifier, + SelectOption? insertOption, + SelectOption? deleteOption, }) { final _result = create(); - if (gridId != null) { - _result.gridId = gridId; + if (cellIdentifier != null) { + _result.cellIdentifier = cellIdentifier; } - if (rowId != null) { - _result.rowId = rowId; + if (insertOption != null) { + _result.insertOption = insertOption; } - if (fieldId != null) { - _result.fieldId = fieldId; - } - if (insertOptionId != null) { - _result.insertOptionId = insertOptionId; - } - if (deleteOptionId != null) { - _result.deleteOptionId = deleteOptionId; + if (deleteOption != null) { + _result.deleteOption = deleteOption; } return _result; } @@ -275,10 +267,127 @@ class SelectOptionChangesetPayload extends $pb.GeneratedMessage { static SelectOptionChangesetPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static SelectOptionChangesetPayload? _defaultInstance; - SelectOptionChangesetPayload_OneOfInsertOptionId whichOneOfInsertOptionId() => _SelectOptionChangesetPayload_OneOfInsertOptionIdByTag[$_whichOneof(0)]!; + SelectOptionChangesetPayload_OneOfInsertOption whichOneOfInsertOption() => _SelectOptionChangesetPayload_OneOfInsertOptionByTag[$_whichOneof(0)]!; + void clearOneOfInsertOption() => clearField($_whichOneof(0)); + + SelectOptionChangesetPayload_OneOfDeleteOption whichOneOfDeleteOption() => _SelectOptionChangesetPayload_OneOfDeleteOptionByTag[$_whichOneof(1)]!; + void clearOneOfDeleteOption() => clearField($_whichOneof(1)); + + @$pb.TagNumber(1) + $0.CellIdentifierPayload get cellIdentifier => $_getN(0); + @$pb.TagNumber(1) + set cellIdentifier($0.CellIdentifierPayload v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasCellIdentifier() => $_has(0); + @$pb.TagNumber(1) + void clearCellIdentifier() => clearField(1); + @$pb.TagNumber(1) + $0.CellIdentifierPayload ensureCellIdentifier() => $_ensure(0); + + @$pb.TagNumber(2) + SelectOption get insertOption => $_getN(1); + @$pb.TagNumber(2) + set insertOption(SelectOption v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasInsertOption() => $_has(1); + @$pb.TagNumber(2) + void clearInsertOption() => clearField(2); + @$pb.TagNumber(2) + SelectOption ensureInsertOption() => $_ensure(1); + + @$pb.TagNumber(3) + SelectOption get deleteOption => $_getN(2); + @$pb.TagNumber(3) + set deleteOption(SelectOption v) { setField(3, v); } + @$pb.TagNumber(3) + $core.bool hasDeleteOption() => $_has(2); + @$pb.TagNumber(3) + void clearDeleteOption() => clearField(3); + @$pb.TagNumber(3) + SelectOption ensureDeleteOption() => $_ensure(2); +} + +enum SelectOptionCellChangesetPayload_OneOfInsertOptionId { + insertOptionId, + notSet +} + +enum SelectOptionCellChangesetPayload_OneOfDeleteOptionId { + deleteOptionId, + notSet +} + +class SelectOptionCellChangesetPayload extends $pb.GeneratedMessage { + static const $core.Map<$core.int, SelectOptionCellChangesetPayload_OneOfInsertOptionId> _SelectOptionCellChangesetPayload_OneOfInsertOptionIdByTag = { + 4 : SelectOptionCellChangesetPayload_OneOfInsertOptionId.insertOptionId, + 0 : SelectOptionCellChangesetPayload_OneOfInsertOptionId.notSet + }; + static const $core.Map<$core.int, SelectOptionCellChangesetPayload_OneOfDeleteOptionId> _SelectOptionCellChangesetPayload_OneOfDeleteOptionIdByTag = { + 5 : SelectOptionCellChangesetPayload_OneOfDeleteOptionId.deleteOptionId, + 0 : SelectOptionCellChangesetPayload_OneOfDeleteOptionId.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionCellChangesetPayload', createEmptyInstance: create) + ..oo(0, [4]) + ..oo(1, [5]) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'insertOptionId') + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deleteOptionId') + ..hasRequiredFields = false + ; + + SelectOptionCellChangesetPayload._() : super(); + factory SelectOptionCellChangesetPayload({ + $core.String? gridId, + $core.String? rowId, + $core.String? fieldId, + $core.String? insertOptionId, + $core.String? deleteOptionId, + }) { + final _result = create(); + if (gridId != null) { + _result.gridId = gridId; + } + if (rowId != null) { + _result.rowId = rowId; + } + if (fieldId != null) { + _result.fieldId = fieldId; + } + if (insertOptionId != null) { + _result.insertOptionId = insertOptionId; + } + if (deleteOptionId != null) { + _result.deleteOptionId = deleteOptionId; + } + return _result; + } + factory SelectOptionCellChangesetPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SelectOptionCellChangesetPayload.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') + SelectOptionCellChangesetPayload clone() => SelectOptionCellChangesetPayload()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SelectOptionCellChangesetPayload copyWith(void Function(SelectOptionCellChangesetPayload) updates) => super.copyWith((message) => updates(message as SelectOptionCellChangesetPayload)) as SelectOptionCellChangesetPayload; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SelectOptionCellChangesetPayload create() => SelectOptionCellChangesetPayload._(); + SelectOptionCellChangesetPayload createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SelectOptionCellChangesetPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SelectOptionCellChangesetPayload? _defaultInstance; + + SelectOptionCellChangesetPayload_OneOfInsertOptionId whichOneOfInsertOptionId() => _SelectOptionCellChangesetPayload_OneOfInsertOptionIdByTag[$_whichOneof(0)]!; void clearOneOfInsertOptionId() => clearField($_whichOneof(0)); - SelectOptionChangesetPayload_OneOfDeleteOptionId whichOneOfDeleteOptionId() => _SelectOptionChangesetPayload_OneOfDeleteOptionIdByTag[$_whichOneof(1)]!; + SelectOptionCellChangesetPayload_OneOfDeleteOptionId whichOneOfDeleteOptionId() => _SelectOptionCellChangesetPayload_OneOfDeleteOptionIdByTag[$_whichOneof(1)]!; void clearOneOfDeleteOptionId() => clearField($_whichOneof(1)); @$pb.TagNumber(1) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart index 04c44a3004..7a160d582d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart @@ -63,6 +63,22 @@ final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxT @$core.Deprecated('Use selectOptionChangesetPayloadDescriptor instead') const SelectOptionChangesetPayload$json = const { '1': 'SelectOptionChangesetPayload', + '2': const [ + const {'1': 'cell_identifier', '3': 1, '4': 1, '5': 11, '6': '.CellIdentifierPayload', '10': 'cellIdentifier'}, + const {'1': 'insert_option', '3': 2, '4': 1, '5': 11, '6': '.SelectOption', '9': 0, '10': 'insertOption'}, + const {'1': 'delete_option', '3': 3, '4': 1, '5': 11, '6': '.SelectOption', '9': 1, '10': 'deleteOption'}, + ], + '8': const [ + const {'1': 'one_of_insert_option'}, + const {'1': 'one_of_delete_option'}, + ], +}; + +/// Descriptor for `SelectOptionChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionChangesetPayloadDescriptor = $convert.base64Decode('ChxTZWxlY3RPcHRpb25DaGFuZ2VzZXRQYXlsb2FkEj8KD2NlbGxfaWRlbnRpZmllchgBIAEoCzIWLkNlbGxJZGVudGlmaWVyUGF5bG9hZFIOY2VsbElkZW50aWZpZXISNAoNaW5zZXJ0X29wdGlvbhgCIAEoCzINLlNlbGVjdE9wdGlvbkgAUgxpbnNlcnRPcHRpb24SNAoNZGVsZXRlX29wdGlvbhgDIAEoCzINLlNlbGVjdE9wdGlvbkgBUgxkZWxldGVPcHRpb25CFgoUb25lX29mX2luc2VydF9vcHRpb25CFgoUb25lX29mX2RlbGV0ZV9vcHRpb24='); +@$core.Deprecated('Use selectOptionCellChangesetPayloadDescriptor instead') +const SelectOptionCellChangesetPayload$json = const { + '1': 'SelectOptionCellChangesetPayload', '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'}, @@ -76,8 +92,8 @@ const SelectOptionChangesetPayload$json = const { ], }; -/// Descriptor for `SelectOptionChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List selectOptionChangesetPayloadDescriptor = $convert.base64Decode('ChxTZWxlY3RPcHRpb25DaGFuZ2VzZXRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElkEioKEGluc2VydF9vcHRpb25faWQYBCABKAlIAFIOaW5zZXJ0T3B0aW9uSWQSKgoQZGVsZXRlX29wdGlvbl9pZBgFIAEoCUgBUg5kZWxldGVPcHRpb25JZEIZChdvbmVfb2ZfaW5zZXJ0X29wdGlvbl9pZEIZChdvbmVfb2ZfZGVsZXRlX29wdGlvbl9pZA=='); +/// Descriptor for `SelectOptionCellChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List selectOptionCellChangesetPayloadDescriptor = $convert.base64Decode('CiBTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0UGF5bG9hZBIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSFQoGcm93X2lkGAIgASgJUgVyb3dJZBIZCghmaWVsZF9pZBgDIAEoCVIHZmllbGRJZBIqChBpbnNlcnRfb3B0aW9uX2lkGAQgASgJSABSDmluc2VydE9wdGlvbklkEioKEGRlbGV0ZV9vcHRpb25faWQYBSABKAlIAVIOZGVsZXRlT3B0aW9uSWRCGQoXb25lX29mX2luc2VydF9vcHRpb25faWRCGQoXb25lX29mX2RlbGV0ZV9vcHRpb25faWQ='); @$core.Deprecated('Use selectOptionContextDescriptor instead') const SelectOptionContext$json = const { '1': 'SelectOptionContext', diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 143dc76b1e..df26694331 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" name = "dart_ffi" # this value will change depending on the target os # default static lib -crate-type = ["cdylib"] +crate-type = ["staticlib"] [dependencies] diff --git a/frontend/rust-lib/flowy-grid/Flowy.toml b/frontend/rust-lib/flowy-grid/Flowy.toml index d0b6c8dec5..b0b15a1a2a 100644 --- a/frontend/rust-lib/flowy-grid/Flowy.toml +++ b/frontend/rust-lib/flowy-grid/Flowy.toml @@ -1,3 +1,10 @@ -proto_crates = ["src/event_map.rs", "src/services/field/type_options", "src/dart_notification.rs"] +proto_crates = [ + "src/event_map.rs", + "src/services/field/type_options", + "src/services/field/field_entities.rs", + "src/services/cell/cell_entities.rs", + "src/services/row/row_entities.rs", + "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 index 914b3088f5..cc910e30c6 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -9,7 +9,7 @@ pub enum GridNotification { DidUpdateBlock = 20, DidUpdateRow = 30, DidUpdateCell = 31, - DidUpdateFields = 40, + DidUpdateGrid = 40, DidUpdateField = 41, } diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 2a8bb86103..3d46349240 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,10 +1,11 @@ use crate::manager::GridManager; -use crate::services::field::{ - default_type_option_builder_from_type, type_option_builder_from_json_str, MultiSelectTypeOption, SelectOption, - SelectOptionChangesetParams, SelectOptionChangesetPayload, SelectOptionContext, SingleSelectTypeOption, -}; +use crate::services::cell::cell_entities::*; +use crate::services::field::field_entities::*; +use crate::services::field::type_options::*; +use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str}; use crate::services::grid_editor::ClientGridEditor; -use flowy_error::{FlowyError, FlowyResult}; +use crate::services::row::row_entities::*; +use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; @@ -76,7 +77,7 @@ pub(crate) async fn delete_field_handler( data: Data, manager: AppData>, ) -> Result<(), FlowyError> { - let params: FieldIdentifierParams = data.into_inner().try_into()?; + let params: FieldIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; let _ = editor.delete_field(¶ms.field_id).await?; Ok(()) @@ -93,10 +94,7 @@ pub(crate) async fn switch_to_field_handler( .switch_to_field_type(¶ms.field_id, ¶ms.field_type) .await?; - let field_meta = editor - .get_field_metas(Some(vec![params.field_id.as_str()])) - .await? - .pop(); + let field_meta = editor.get_field_meta(¶ms.field_id).await; let edit_context = make_field_edit_context( ¶ms.grid_id, Some(params.field_id), @@ -113,58 +111,12 @@ pub(crate) async fn duplicate_field_handler( data: Data, manager: AppData>, ) -> Result<(), FlowyError> { - let params: FieldIdentifierParams = data.into_inner().try_into()?; + let params: FieldIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; let _ = editor.duplicate_field(¶ms.field_id).await?; Ok(()) } -#[tracing::instrument(level = "debug", skip(data), err)] -pub(crate) async fn create_select_option_handler( - data: Data, -) -> DataResult { - let params: CreateSelectOptionParams = data.into_inner().try_into()?; - data_result(SelectOption::new(¶ms.option_name)) -} - -#[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn get_select_option_handler( - data: Data, - manager: AppData>, -) -> DataResult { - let params: CellIdentifier = data.into_inner().try_into()?; - let editor = manager.get_grid_editor(¶ms.grid_id)?; - match editor - .get_field_metas(Some(vec![params.field_id.as_str()])) - .await? - .pop() - { - None => { - tracing::error!("Can't find the corresponding field with id: {}", params.field_id); - data_result(SelectOptionContext::default()) - } - Some(field_meta) => { - let cell_meta = editor.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?; - match field_meta.field_type { - FieldType::SingleSelect => { - let type_option = SingleSelectTypeOption::from(&field_meta); - let select_option_context = type_option.select_option_context(&cell_meta); - data_result(select_option_context) - } - FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(&field_meta); - let select_option_context = type_option.select_option_context(&cell_meta); - data_result(select_option_context) - } - ty => { - tracing::error!("Unsupported field type: {:?} for this handler", ty); - data_result(SelectOptionContext::default()) - } - } - } - } -} - #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_field_context_handler( data: Data, @@ -207,7 +159,7 @@ async fn get_or_create_field_meta( ) -> FlowyResult { match field_id { None => editor.create_next_field_meta(field_type).await, - Some(field_id) => match editor.get_field_metas(Some(vec![field_id.as_str()])).await?.pop() { + Some(field_id) => match editor.get_field_meta(&field_id).await { None => editor.create_next_field_meta(field_type).await, Some(field_meta) => Ok(field_meta), }, @@ -216,10 +168,10 @@ async fn get_or_create_field_meta( #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_row_handler( - data: Data, + data: Data, manager: AppData>, ) -> DataResult { - let params: QueryRowParams = data.into_inner().try_into()?; + let params: RowIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; match editor.get_row(¶ms.row_id).await? { None => Err(FlowyError::record_not_found().context("Can not find the row")), @@ -250,13 +202,92 @@ pub(crate) async fn update_cell_handler( } #[tracing::instrument(level = "debug", skip_all, err)] -pub(crate) async fn apply_select_option_changeset_handler( +pub(crate) async fn new_select_option_handler(data: Data) -> DataResult { + let params = data.into_inner(); + data_result(SelectOption::new(¶ms.name)) +} + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn select_option_changeset_handler( data: Data, manager: AppData>, ) -> Result<(), FlowyError> { - let params: SelectOptionChangesetParams = data.into_inner().try_into()?; + let changeset: SelectOptionChangeset = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(&changeset.cell_identifier.grid_id)?; + + if let Some(mut field_meta) = editor.get_field_meta(&changeset.cell_identifier.field_id).await { + let mut type_option = select_option_operation(&field_meta)?; + let mut cell_data = None; + if let Some(option) = changeset.insert_option { + cell_data = Some(SelectOptionCellChangeset::from_insert(&option.id).cell_data()); + type_option.insert_option(option); + } + + if let Some(option) = changeset.delete_option { + cell_data = Some(SelectOptionCellChangeset::from_delete(&option.id).cell_data()); + type_option.delete_option(option); + } + + field_meta.insert_type_option_entry(&*type_option); + let _ = editor.replace_field(field_meta).await?; + + let changeset = CellMetaChangeset { + grid_id: changeset.cell_identifier.grid_id, + row_id: changeset.cell_identifier.row_id, + field_id: changeset.cell_identifier.field_id, + data: cell_data, + }; + let _ = editor.update_cell(changeset).await?; + } + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn get_select_option_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: CellIdentifier = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + match editor.get_field_meta(¶ms.field_id).await { + None => { + tracing::error!("Can't find the corresponding field with id: {}", params.field_id); + data_result(SelectOptionContext::default()) + } + Some(field_meta) => { + let cell_meta = editor.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?; + let type_option = select_option_operation(&field_meta)?; + let option_context = type_option.option_context(&cell_meta); + data_result(option_context) + } + } +} + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn select_option_cell_changeset_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let params: SelectOptionCellChangesetParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; let changeset: CellMetaChangeset = params.into(); let _ = editor.update_cell(changeset).await?; Ok(()) } + +fn select_option_operation(field_meta: &FieldMeta) -> FlowyResult> { + match &field_meta.field_type { + FieldType::SingleSelect => { + let type_option = SingleSelectTypeOption::from(field_meta); + Ok(Box::new(type_option)) + } + FieldType::MultiSelect => { + let type_option = MultiSelectTypeOption::from(field_meta); + Ok(Box::new(type_option)) + } + ty => { + tracing::error!("Unsupported field type: {:?} for this handler", ty); + Err(ErrorCode::FieldInvalidOperation.into()) + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 2af4b28e35..711ad46255 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -23,11 +23,12 @@ pub fn create(grid_manager: Arc) -> Module { // Cell .event(GridEvent::UpdateCell, update_cell_handler) // SelectOption - .event(GridEvent::CreateSelectOption, create_select_option_handler) - .event(GridEvent::GetSelectOptions, get_select_option_handler) + .event(GridEvent::NewSelectOption, new_select_option_handler) + .event(GridEvent::ApplySelectOptionChangeset, select_option_changeset_handler) + .event(GridEvent::GetSelectOptionContext, get_select_option_handler) .event( - GridEvent::ApplySelectOptionChangeset, - apply_select_option_changeset_handler, + GridEvent::ApplySelectOptionCellChangeset, + select_option_cell_changeset_handler, ) .event(GridEvent::GetEditFieldContext, get_field_context_handler); @@ -64,21 +65,24 @@ pub enum GridEvent { #[event(input = "GetEditFieldContextPayload", output = "EditFieldContext")] GetEditFieldContext = 16, - #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] - CreateSelectOption = 30, + #[event(input = "SelectOptionName", output = "SelectOption")] + NewSelectOption = 30, #[event(input = "CellIdentifierPayload", output = "SelectOptionContext")] - GetSelectOptions = 31, + GetSelectOptionContext = 31, + + #[event(input = "SelectOptionChangesetPayload")] + ApplySelectOptionChangeset = 32, #[event(input = "CreateRowPayload", output = "Row")] CreateRow = 50, - #[event(input = "QueryRowPayload", output = "Row")] + #[event(input = "RowIdentifierPayload", output = "Row")] GetRow = 51, #[event(input = "CellMetaChangeset")] UpdateCell = 70, - #[event(input = "SelectOptionChangesetPayload")] - ApplySelectOptionChangeset = 71, + #[event(input = "SelectOptionCellChangesetPayload")] + ApplySelectOptionCellChangeset = 71, } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/cell_entities.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/cell_entities.rs new file mode 100644 index 0000000000..107f783e59 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/cell_entities.rs @@ -0,0 +1,664 @@ +// 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 `cell_entities.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; + +#[derive(PartialEq,Clone,Default)] +pub struct CreateSelectOptionPayload { + // message fields + pub cell_identifier: ::protobuf::SingularPtrField, + pub option_name: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CreateSelectOptionPayload { + fn default() -> &'a CreateSelectOptionPayload { + ::default_instance() + } +} + +impl CreateSelectOptionPayload { + pub fn new() -> CreateSelectOptionPayload { + ::std::default::Default::default() + } + + // .CellIdentifierPayload cell_identifier = 1; + + + pub fn get_cell_identifier(&self) -> &CellIdentifierPayload { + self.cell_identifier.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_cell_identifier(&mut self) { + self.cell_identifier.clear(); + } + + pub fn has_cell_identifier(&self) -> bool { + self.cell_identifier.is_some() + } + + // Param is passed by value, moved + pub fn set_cell_identifier(&mut self, v: CellIdentifierPayload) { + self.cell_identifier = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_cell_identifier(&mut self) -> &mut CellIdentifierPayload { + if self.cell_identifier.is_none() { + self.cell_identifier.set_default(); + } + self.cell_identifier.as_mut().unwrap() + } + + // Take field + pub fn take_cell_identifier(&mut self) -> CellIdentifierPayload { + self.cell_identifier.take().unwrap_or_else(|| CellIdentifierPayload::new()) + } + + // string option_name = 2; + + + pub fn get_option_name(&self) -> &str { + &self.option_name + } + pub fn clear_option_name(&mut self) { + self.option_name.clear(); + } + + // Param is passed by value, moved + pub fn set_option_name(&mut self, v: ::std::string::String) { + self.option_name = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_option_name(&mut self) -> &mut ::std::string::String { + &mut self.option_name + } + + // Take field + pub fn take_option_name(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.option_name, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for CreateSelectOptionPayload { + fn is_initialized(&self) -> bool { + for v in &self.cell_identifier { + 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_singular_message_into(wire_type, is, &mut self.cell_identifier)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.option_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 let Some(ref v) = self.cell_identifier.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if !self.option_name.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.option_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 let Some(ref v) = self.cell_identifier.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if !self.option_name.is_empty() { + os.write_string(2, &self.option_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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> CreateSelectOptionPayload { + CreateSelectOptionPayload::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_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "cell_identifier", + |m: &CreateSelectOptionPayload| { &m.cell_identifier }, + |m: &mut CreateSelectOptionPayload| { &mut m.cell_identifier }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "option_name", + |m: &CreateSelectOptionPayload| { &m.option_name }, + |m: &mut CreateSelectOptionPayload| { &mut m.option_name }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateSelectOptionPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CreateSelectOptionPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateSelectOptionPayload::new) + } +} + +impl ::protobuf::Clear for CreateSelectOptionPayload { + fn clear(&mut self) { + self.cell_identifier.clear(); + self.option_name.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CreateSelectOptionPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CreateSelectOptionPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct CellIdentifierPayload { + // message fields + pub grid_id: ::std::string::String, + pub field_id: ::std::string::String, + pub row_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CellIdentifierPayload { + fn default() -> &'a CellIdentifierPayload { + ::default_instance() + } +} + +impl CellIdentifierPayload { + pub fn new() -> CellIdentifierPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string field_id = 2; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string row_id = 3; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for CellIdentifierPayload { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.field_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.row_id); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.field_id.is_empty() { + os.write_string(2, &self.field_id)?; + } + if !self.row_id.is_empty() { + os.write_string(3, &self.row_id)?; + } + 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() -> CellIdentifierPayload { + CellIdentifierPayload::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>( + "grid_id", + |m: &CellIdentifierPayload| { &m.grid_id }, + |m: &mut CellIdentifierPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &CellIdentifierPayload| { &m.field_id }, + |m: &mut CellIdentifierPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &CellIdentifierPayload| { &m.row_id }, + |m: &mut CellIdentifierPayload| { &mut m.row_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CellIdentifierPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CellIdentifierPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CellIdentifierPayload::new) + } +} + +impl ::protobuf::Clear for CellIdentifierPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.field_id.clear(); + self.row_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CellIdentifierPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CellIdentifierPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionName { + // 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 SelectOptionName { + fn default() -> &'a SelectOptionName { + ::default_instance() + } +} + +impl SelectOptionName { + pub fn new() -> SelectOptionName { + ::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 SelectOptionName { + 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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> SelectOptionName { + SelectOptionName::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: &SelectOptionName| { &m.name }, + |m: &mut SelectOptionName| { &mut m.name }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionName", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionName { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionName::new) + } +} + +impl ::protobuf::Clear for SelectOptionName { + fn clear(&mut self) { + self.name.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionName { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionName { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x13cell_entities.proto\"}\n\x19CreateSelectOptionPayload\x12?\n\x0fce\ + ll_identifier\x18\x01\x20\x01(\x0b2\x16.CellIdentifierPayloadR\x0ecellId\ + entifier\x12\x1f\n\x0boption_name\x18\x02\x20\x01(\tR\noptionName\"b\n\ + \x15CellIdentifierPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\ + idId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06r\ + ow_id\x18\x03\x20\x01(\tR\x05rowId\"&\n\x10SelectOptionName\x12\x12\n\ + \x04name\x18\x01\x20\x01(\tR\x04nameb\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/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs index e02f234e9f..d5eaa2a6d8 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -30,7 +30,7 @@ pub enum GridNotification { DidUpdateBlock = 20, DidUpdateRow = 30, DidUpdateCell = 31, - DidUpdateFields = 40, + DidUpdateGrid = 40, DidUpdateField = 41, } @@ -46,7 +46,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { 20 => ::std::option::Option::Some(GridNotification::DidUpdateBlock), 30 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 31 => ::std::option::Option::Some(GridNotification::DidUpdateCell), - 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), + 40 => ::std::option::Option::Some(GridNotification::DidUpdateGrid), 41 => ::std::option::Option::Some(GridNotification::DidUpdateField), _ => ::std::option::Option::None } @@ -59,7 +59,7 @@ impl ::protobuf::ProtobufEnum for GridNotification { GridNotification::DidUpdateBlock, GridNotification::DidUpdateRow, GridNotification::DidUpdateCell, - GridNotification::DidUpdateFields, + GridNotification::DidUpdateGrid, GridNotification::DidUpdateField, ]; values @@ -89,11 +89,11 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x95\x01\n\x10GridNotification\x12\x0b\n\ + \n\x17dart_notification.proto*\x93\x01\n\x10GridNotification\x12\x0b\n\ \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x12\n\x0eDidUp\ dateBlock\x10\x14\x12\x10\n\x0cDidUpdateRow\x10\x1e\x12\x11\n\rDidUpdate\ - Cell\x10\x1f\x12\x13\n\x0fDidUpdateFields\x10(\x12\x12\n\x0eDidUpdateFie\ - ld\x10)b\x06proto3\ + Cell\x10\x1f\x12\x11\n\rDidUpdateGrid\x10(\x12\x12\n\x0eDidUpdateField\ + \x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index 72a0601391..ef26608bf1 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -34,12 +34,13 @@ pub enum GridEvent { SwitchToField = 14, DuplicateField = 15, GetEditFieldContext = 16, - CreateSelectOption = 30, - GetSelectOptions = 31, + NewSelectOption = 30, + GetSelectOptionContext = 31, + ApplySelectOptionChangeset = 32, CreateRow = 50, GetRow = 51, UpdateCell = 70, - ApplySelectOptionChangeset = 71, + ApplySelectOptionCellChangeset = 71, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -58,12 +59,13 @@ impl ::protobuf::ProtobufEnum for GridEvent { 14 => ::std::option::Option::Some(GridEvent::SwitchToField), 15 => ::std::option::Option::Some(GridEvent::DuplicateField), 16 => ::std::option::Option::Some(GridEvent::GetEditFieldContext), - 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption), - 31 => ::std::option::Option::Some(GridEvent::GetSelectOptions), + 30 => ::std::option::Option::Some(GridEvent::NewSelectOption), + 31 => ::std::option::Option::Some(GridEvent::GetSelectOptionContext), + 32 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset), 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), 70 => ::std::option::Option::Some(GridEvent::UpdateCell), - 71 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset), + 71 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset), _ => ::std::option::Option::None } } @@ -79,12 +81,13 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::SwitchToField, GridEvent::DuplicateField, GridEvent::GetEditFieldContext, - GridEvent::CreateSelectOption, - GridEvent::GetSelectOptions, + GridEvent::NewSelectOption, + GridEvent::GetSelectOptionContext, + GridEvent::ApplySelectOptionChangeset, GridEvent::CreateRow, GridEvent::GetRow, GridEvent::UpdateCell, - GridEvent::ApplySelectOptionChangeset, + GridEvent::ApplySelectOptionCellChangeset, ]; values } @@ -113,14 +116,15 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xaa\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xd1\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ - ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x16\n\x12Creat\ - eSelectOption\x10\x1e\x12\x14\n\x10GetSelectOptions\x10\x1f\x12\r\n\tCre\ - ateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\x1e\n\ - \x1aApplySelectOptionChangeset\x10Gb\x06proto3\ + ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x13\n\x0fNewSe\ + lectOption\x10\x1e\x12\x1a\n\x16GetSelectOptionContext\x10\x1f\x12\x1e\n\ + \x1aApplySelectOptionChangeset\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\ + \x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\"\n\x1eApplySelectOptionC\ + ellChangeset\x10Gb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/field_entities.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/field_entities.rs new file mode 100644 index 0000000000..fa4edcc070 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/field_entities.rs @@ -0,0 +1,243 @@ +// 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 `field_entities.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; + +#[derive(PartialEq,Clone,Default)] +pub struct FieldIdentifierPayload { + // message fields + pub field_id: ::std::string::String, + pub grid_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a FieldIdentifierPayload { + fn default() -> &'a FieldIdentifierPayload { + ::default_instance() + } +} + +impl FieldIdentifierPayload { + pub fn new() -> FieldIdentifierPayload { + ::std::default::Default::default() + } + + // string field_id = 1; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string grid_id = 2; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for FieldIdentifierPayload { + 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.field_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; + }, + _ => { + ::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.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.field_id); + } + if !self.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.grid_id); + } + 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.field_id.is_empty() { + os.write_string(1, &self.field_id)?; + } + if !self.grid_id.is_empty() { + os.write_string(2, &self.grid_id)?; + } + 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() -> FieldIdentifierPayload { + FieldIdentifierPayload::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>( + "field_id", + |m: &FieldIdentifierPayload| { &m.field_id }, + |m: &mut FieldIdentifierPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "grid_id", + |m: &FieldIdentifierPayload| { &m.grid_id }, + |m: &mut FieldIdentifierPayload| { &mut m.grid_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FieldIdentifierPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static FieldIdentifierPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FieldIdentifierPayload::new) + } +} + +impl ::protobuf::Clear for FieldIdentifierPayload { + fn clear(&mut self) { + self.field_id.clear(); + self.grid_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for FieldIdentifierPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for FieldIdentifierPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x14field_entities.proto\"L\n\x16FieldIdentifierPayload\x12\x19\n\x08f\ + ield_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\ + \x01(\tR\x06gridIdb\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 8408c120c1..99d0ecd1b6 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs @@ -1,6 +1,9 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit +mod field_entities; +pub use field_entities::*; + mod number_type_option; pub use number_type_option::*; @@ -10,6 +13,12 @@ pub use dart_notification::*; mod selection_type_option; pub use selection_type_option::*; +mod row_entities; +pub use row_entities::*; + +mod cell_entities; +pub use cell_entities::*; + mod checkbox_type_option; pub use checkbox_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/row_entities.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/row_entities.rs new file mode 100644 index 0000000000..0bcf1323c6 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/row_entities.rs @@ -0,0 +1,243 @@ +// 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 `row_entities.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; + +#[derive(PartialEq,Clone,Default)] +pub struct RowIdentifierPayload { + // message fields + pub grid_id: ::std::string::String, + pub row_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a RowIdentifierPayload { + fn default() -> &'a RowIdentifierPayload { + ::default_instance() + } +} + +impl RowIdentifierPayload { + pub fn new() -> RowIdentifierPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string row_id = 3; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for RowIdentifierPayload { + 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.grid_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.row_id); + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.row_id.is_empty() { + os.write_string(3, &self.row_id)?; + } + 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() -> RowIdentifierPayload { + RowIdentifierPayload::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>( + "grid_id", + |m: &RowIdentifierPayload| { &m.grid_id }, + |m: &mut RowIdentifierPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &RowIdentifierPayload| { &m.row_id }, + |m: &mut RowIdentifierPayload| { &mut m.row_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "RowIdentifierPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static RowIdentifierPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(RowIdentifierPayload::new) + } +} + +impl ::protobuf::Clear for RowIdentifierPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.row_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for RowIdentifierPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for RowIdentifierPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x12row_entities.proto\"F\n\x14RowIdentifierPayload\x12\x17\n\x07grid_\ + id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\ + \x05rowIdb\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/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs index 7a65da1171..ea45e6ac6e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs @@ -660,12 +660,10 @@ impl ::protobuf::reflect::ProtobufValue for SelectOption { #[derive(PartialEq,Clone,Default)] pub struct SelectOptionChangesetPayload { // message fields - pub grid_id: ::std::string::String, - pub row_id: ::std::string::String, - pub field_id: ::std::string::String, + pub cell_identifier: ::protobuf::SingularPtrField, // message oneof groups - pub one_of_insert_option_id: ::std::option::Option, - pub one_of_delete_option_id: ::std::option::Option, + pub one_of_insert_option: ::std::option::Option, + pub one_of_delete_option: ::std::option::Option, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -678,13 +676,13 @@ impl<'a> ::std::default::Default for &'a SelectOptionChangesetPayload { } #[derive(Clone,PartialEq,Debug)] -pub enum SelectOptionChangesetPayload_oneof_one_of_insert_option_id { - insert_option_id(::std::string::String), +pub enum SelectOptionChangesetPayload_oneof_one_of_insert_option { + insert_option(SelectOption), } #[derive(Clone,PartialEq,Debug)] -pub enum SelectOptionChangesetPayload_oneof_one_of_delete_option_id { - delete_option_id(::std::string::String), +pub enum SelectOptionChangesetPayload_oneof_one_of_delete_option { + delete_option(SelectOption), } impl SelectOptionChangesetPayload { @@ -692,6 +690,361 @@ impl SelectOptionChangesetPayload { ::std::default::Default::default() } + // .CellIdentifierPayload cell_identifier = 1; + + + pub fn get_cell_identifier(&self) -> &super::cell_entities::CellIdentifierPayload { + self.cell_identifier.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_cell_identifier(&mut self) { + self.cell_identifier.clear(); + } + + pub fn has_cell_identifier(&self) -> bool { + self.cell_identifier.is_some() + } + + // Param is passed by value, moved + pub fn set_cell_identifier(&mut self, v: super::cell_entities::CellIdentifierPayload) { + self.cell_identifier = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_cell_identifier(&mut self) -> &mut super::cell_entities::CellIdentifierPayload { + if self.cell_identifier.is_none() { + self.cell_identifier.set_default(); + } + self.cell_identifier.as_mut().unwrap() + } + + // Take field + pub fn take_cell_identifier(&mut self) -> super::cell_entities::CellIdentifierPayload { + self.cell_identifier.take().unwrap_or_else(|| super::cell_entities::CellIdentifierPayload::new()) + } + + // .SelectOption insert_option = 2; + + + pub fn get_insert_option(&self) -> &SelectOption { + match self.one_of_insert_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(ref v)) => v, + _ => ::default_instance(), + } + } + pub fn clear_insert_option(&mut self) { + self.one_of_insert_option = ::std::option::Option::None; + } + + pub fn has_insert_option(&self) -> bool { + match self.one_of_insert_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_insert_option(&mut self, v: SelectOption) { + self.one_of_insert_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(v)) + } + + // Mutable pointer to the field. + pub fn mut_insert_option(&mut self) -> &mut SelectOption { + if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(_)) = self.one_of_insert_option { + } else { + self.one_of_insert_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(SelectOption::new())); + } + match self.one_of_insert_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_insert_option(&mut self) -> SelectOption { + if self.has_insert_option() { + match self.one_of_insert_option.take() { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(v)) => v, + _ => panic!(), + } + } else { + SelectOption::new() + } + } + + // .SelectOption delete_option = 3; + + + pub fn get_delete_option(&self) -> &SelectOption { + match self.one_of_delete_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(ref v)) => v, + _ => ::default_instance(), + } + } + pub fn clear_delete_option(&mut self) { + self.one_of_delete_option = ::std::option::Option::None; + } + + pub fn has_delete_option(&self) -> bool { + match self.one_of_delete_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_delete_option(&mut self, v: SelectOption) { + self.one_of_delete_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(v)) + } + + // Mutable pointer to the field. + pub fn mut_delete_option(&mut self) -> &mut SelectOption { + if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(_)) = self.one_of_delete_option { + } else { + self.one_of_delete_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(SelectOption::new())); + } + match self.one_of_delete_option { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_delete_option(&mut self) -> SelectOption { + if self.has_delete_option() { + match self.one_of_delete_option.take() { + ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(v)) => v, + _ => panic!(), + } + } else { + SelectOption::new() + } + } +} + +impl ::protobuf::Message for SelectOptionChangesetPayload { + fn is_initialized(&self) -> bool { + for v in &self.cell_identifier { + if !v.is_initialized() { + return false; + } + }; + if let Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(ref v)) = self.one_of_insert_option { + if !v.is_initialized() { + return false; + } + } + if let Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(ref v)) = self.one_of_delete_option { + 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_singular_message_into(wire_type, is, &mut self.cell_identifier)?; + }, + 2 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_insert_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(is.read_message()?)); + }, + 3 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_delete_option = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(is.read_message()?)); + }, + _ => { + ::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 let Some(ref v) = self.cell_identifier.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option { + match v { + &SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(ref v) => { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option { + match v { + &SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(ref v) => { + let len = v.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<()> { + if let Some(ref v) = self.cell_identifier.as_ref() { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option { + match v { + &SelectOptionChangesetPayload_oneof_one_of_insert_option::insert_option(ref v) => { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option { + match v { + &SelectOptionChangesetPayload_oneof_one_of_delete_option::delete_option(ref v) => { + os.write_tag(3, ::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() -> SelectOptionChangesetPayload { + SelectOptionChangesetPayload::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_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "cell_identifier", + |m: &SelectOptionChangesetPayload| { &m.cell_identifier }, + |m: &mut SelectOptionChangesetPayload| { &mut m.cell_identifier }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, SelectOption>( + "insert_option", + SelectOptionChangesetPayload::has_insert_option, + SelectOptionChangesetPayload::get_insert_option, + )); + fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, SelectOption>( + "delete_option", + SelectOptionChangesetPayload::has_delete_option, + SelectOptionChangesetPayload::get_delete_option, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionChangesetPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionChangesetPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionChangesetPayload::new) + } +} + +impl ::protobuf::Clear for SelectOptionChangesetPayload { + fn clear(&mut self) { + self.cell_identifier.clear(); + self.one_of_insert_option = ::std::option::Option::None; + self.one_of_delete_option = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionChangesetPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionChangesetPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionCellChangesetPayload { + // message fields + pub grid_id: ::std::string::String, + pub row_id: ::std::string::String, + pub field_id: ::std::string::String, + // message oneof groups + pub one_of_insert_option_id: ::std::option::Option, + pub one_of_delete_option_id: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOptionCellChangesetPayload { + fn default() -> &'a SelectOptionCellChangesetPayload { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id { + insert_option_id(::std::string::String), +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id { + delete_option_id(::std::string::String), +} + +impl SelectOptionCellChangesetPayload { + pub fn new() -> SelectOptionCellChangesetPayload { + ::std::default::Default::default() + } + // string grid_id = 1; @@ -775,7 +1128,7 @@ impl SelectOptionChangesetPayload { pub fn get_insert_option_id(&self) -> &str { match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v)) => v, _ => "", } } @@ -785,24 +1138,24 @@ impl SelectOptionChangesetPayload { pub fn has_insert_option_id(&self) -> bool { match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(..)) => true, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_insert_option_id(&mut self, v: ::std::string::String) { - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) } // Mutable pointer to the field. pub fn mut_insert_option_id(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(_)) = self.one_of_insert_option_id { + if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(_)) = self.one_of_insert_option_id { } else { - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(::std::string::String::new())); + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(::std::string::String::new())); } match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref mut v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref mut v)) => v, _ => panic!(), } } @@ -811,7 +1164,7 @@ impl SelectOptionChangesetPayload { pub fn take_insert_option_id(&mut self) -> ::std::string::String { if self.has_insert_option_id() { match self.one_of_insert_option_id.take() { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) => v, _ => panic!(), } } else { @@ -824,7 +1177,7 @@ impl SelectOptionChangesetPayload { pub fn get_delete_option_id(&self) -> &str { match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v)) => v, _ => "", } } @@ -834,24 +1187,24 @@ impl SelectOptionChangesetPayload { pub fn has_delete_option_id(&self) -> bool { match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(..)) => true, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(..)) => true, _ => false, } } // Param is passed by value, moved pub fn set_delete_option_id(&mut self, v: ::std::string::String) { - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) } // Mutable pointer to the field. pub fn mut_delete_option_id(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(_)) = self.one_of_delete_option_id { + if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(_)) = self.one_of_delete_option_id { } else { - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(::std::string::String::new())); + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(::std::string::String::new())); } match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref mut v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref mut v)) => v, _ => panic!(), } } @@ -860,7 +1213,7 @@ impl SelectOptionChangesetPayload { pub fn take_delete_option_id(&mut self) -> ::std::string::String { if self.has_delete_option_id() { match self.one_of_delete_option_id.take() { - ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) => v, + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) => v, _ => panic!(), } } else { @@ -869,7 +1222,7 @@ impl SelectOptionChangesetPayload { } } -impl ::protobuf::Message for SelectOptionChangesetPayload { +impl ::protobuf::Message for SelectOptionCellChangesetPayload { fn is_initialized(&self) -> bool { true } @@ -891,13 +1244,13 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); }, 5 => { if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); } - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(is.read_string()?)); + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(is.read_string()?)); }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -922,14 +1275,14 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { } if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { match v { - &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { my_size += ::protobuf::rt::string_size(4, &v); }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { match v { - &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { my_size += ::protobuf::rt::string_size(5, &v); }, }; @@ -951,14 +1304,14 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { } if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { match v { - &SelectOptionChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { os.write_string(4, v)?; }, }; } if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { match v { - &SelectOptionChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { os.write_string(5, v)?; }, }; @@ -993,8 +1346,8 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { Self::descriptor_static() } - fn new() -> SelectOptionChangesetPayload { - SelectOptionChangesetPayload::new() + fn new() -> SelectOptionCellChangesetPayload { + SelectOptionCellChangesetPayload::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -1003,44 +1356,44 @@ impl ::protobuf::Message for SelectOptionChangesetPayload { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "grid_id", - |m: &SelectOptionChangesetPayload| { &m.grid_id }, - |m: &mut SelectOptionChangesetPayload| { &mut m.grid_id }, + |m: &SelectOptionCellChangesetPayload| { &m.grid_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.grid_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "row_id", - |m: &SelectOptionChangesetPayload| { &m.row_id }, - |m: &mut SelectOptionChangesetPayload| { &mut m.row_id }, + |m: &SelectOptionCellChangesetPayload| { &m.row_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.row_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", - |m: &SelectOptionChangesetPayload| { &m.field_id }, - |m: &mut SelectOptionChangesetPayload| { &mut m.field_id }, + |m: &SelectOptionCellChangesetPayload| { &m.field_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.field_id }, )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "insert_option_id", - SelectOptionChangesetPayload::has_insert_option_id, - SelectOptionChangesetPayload::get_insert_option_id, + SelectOptionCellChangesetPayload::has_insert_option_id, + SelectOptionCellChangesetPayload::get_insert_option_id, )); fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( "delete_option_id", - SelectOptionChangesetPayload::has_delete_option_id, - SelectOptionChangesetPayload::get_delete_option_id, + SelectOptionCellChangesetPayload::has_delete_option_id, + SelectOptionCellChangesetPayload::get_delete_option_id, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "SelectOptionChangesetPayload", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionCellChangesetPayload", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static SelectOptionChangesetPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(SelectOptionChangesetPayload::new) + fn default_instance() -> &'static SelectOptionCellChangesetPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionCellChangesetPayload::new) } } -impl ::protobuf::Clear for SelectOptionChangesetPayload { +impl ::protobuf::Clear for SelectOptionCellChangesetPayload { fn clear(&mut self) { self.grid_id.clear(); self.row_id.clear(); @@ -1051,13 +1404,13 @@ impl ::protobuf::Clear for SelectOptionChangesetPayload { } } -impl ::std::fmt::Debug for SelectOptionChangesetPayload { +impl ::std::fmt::Debug for SelectOptionCellChangesetPayload { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for SelectOptionChangesetPayload { +impl ::protobuf::reflect::ProtobufValue for SelectOptionCellChangesetPayload { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -1350,26 +1703,31 @@ impl ::protobuf::reflect::ProtobufValue for SelectOptionColor { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x1bselection_type_option.proto\"f\n\x16SingleSelectTypeOption\x12'\n\ - \x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x12#\n\rdis\ - able_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"e\n\x15MultiSelectType\ - Option\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07option\ - s\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"\\\n\x0cS\ - electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\ - \x18\x02\x20\x01(\tR\x04name\x12(\n\x05color\x18\x03\x20\x01(\x0e2\x12.S\ - electOptionColorR\x05color\"\xf7\x01\n\x1cSelectOptionChangesetPayload\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\ - \x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\ - \x07fieldId\x12*\n\x10insert_option_id\x18\x04\x20\x01(\tH\0R\x0einsertO\ - ptionId\x12*\n\x10delete_option_id\x18\x05\x20\x01(\tH\x01R\x0edeleteOpt\ - ionIdB\x19\n\x17one_of_insert_option_idB\x19\n\x17one_of_delete_option_i\ - d\"t\n\x13SelectOptionContext\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.\ - SelectOptionR\x07options\x124\n\x0eselect_options\x18\x02\x20\x03(\x0b2\ - \r.SelectOptionR\rselectOptions*y\n\x11SelectOptionColor\x12\n\n\x06Purp\ - le\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\x10\x02\x12\n\n\ - \x06Orange\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\n\x04Lime\x10\x05\ - \x12\t\n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\x12\x08\n\x04Blue\ - \x10\x08b\x06proto3\ + \n\x1bselection_type_option.proto\x1a\x13cell_entities.proto\"f\n\x16Sin\ + gleSelectTypeOption\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOpti\ + onR\x07options\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableCol\ + or\"e\n\x15MultiSelectTypeOption\x12'\n\x07options\x18\x01\x20\x03(\x0b2\ + \r.SelectOptionR\x07options\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\ + \x0cdisableColor\"\\\n\x0cSelectOption\x12\x0e\n\x02id\x18\x01\x20\x01(\ + \tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12(\n\x05color\ + \x18\x03\x20\x01(\x0e2\x12.SelectOptionColorR\x05color\"\xfb\x01\n\x1cSe\ + lectOptionChangesetPayload\x12?\n\x0fcell_identifier\x18\x01\x20\x01(\ + \x0b2\x16.CellIdentifierPayloadR\x0ecellIdentifier\x124\n\rinsert_option\ + \x18\x02\x20\x01(\x0b2\r.SelectOptionH\0R\x0cinsertOption\x124\n\rdelete\ + _option\x18\x03\x20\x01(\x0b2\r.SelectOptionH\x01R\x0cdeleteOptionB\x16\ + \n\x14one_of_insert_optionB\x16\n\x14one_of_delete_option\"\xfb\x01\n\ + \x20SelectOptionCellChangesetPayload\x12\x17\n\x07grid_id\x18\x01\x20\ + \x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\ + \x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12*\n\x10insert_optio\ + n_id\x18\x04\x20\x01(\tH\0R\x0einsertOptionId\x12*\n\x10delete_option_id\ + \x18\x05\x20\x01(\tH\x01R\x0edeleteOptionIdB\x19\n\x17one_of_insert_opti\ + on_idB\x19\n\x17one_of_delete_option_id\"t\n\x13SelectOptionContext\x12'\ + \n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x124\n\ + \x0eselect_options\x18\x02\x20\x03(\x0b2\r.SelectOptionR\rselectOptions*\ + y\n\x11SelectOptionColor\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\ + \x01\x12\r\n\tLightPink\x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yel\ + low\x10\x04\x12\x08\n\x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\ + \x04Aqua\x10\x07\x12\x08\n\x04Blue\x10\x08b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/cell_entities.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/cell_entities.proto new file mode 100644 index 0000000000..d20ec4e34c --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/cell_entities.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +message CreateSelectOptionPayload { + CellIdentifierPayload cell_identifier = 1; + string option_name = 2; +} +message CellIdentifierPayload { + string grid_id = 1; + string field_id = 2; + string row_id = 3; +} +message SelectOptionName { + string name = 1; +} 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 index 6ecb36847a..cbda705483 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -6,6 +6,6 @@ enum GridNotification { DidUpdateBlock = 20; DidUpdateRow = 30; DidUpdateCell = 31; - DidUpdateFields = 40; + DidUpdateGrid = 40; DidUpdateField = 41; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index b423fee748..caddf2de41 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -10,10 +10,11 @@ enum GridEvent { SwitchToField = 14; DuplicateField = 15; GetEditFieldContext = 16; - CreateSelectOption = 30; - GetSelectOptions = 31; + NewSelectOption = 30; + GetSelectOptionContext = 31; + ApplySelectOptionChangeset = 32; CreateRow = 50; GetRow = 51; UpdateCell = 70; - ApplySelectOptionChangeset = 71; + ApplySelectOptionCellChangeset = 71; } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/field_entities.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/field_entities.proto new file mode 100644 index 0000000000..3c670c50af --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/field_entities.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message FieldIdentifierPayload { + string field_id = 1; + string grid_id = 2; +} diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/row_entities.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/row_entities.proto new file mode 100644 index 0000000000..d09d76e960 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/row_entities.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message RowIdentifierPayload { + string grid_id = 1; + string row_id = 3; +} diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto index 3431373504..aee0adcd5e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto @@ -1,4 +1,5 @@ syntax = "proto3"; +import "cell_entities.proto"; message SingleSelectTypeOption { repeated SelectOption options = 1; @@ -14,6 +15,11 @@ message SelectOption { SelectOptionColor color = 3; } message SelectOptionChangesetPayload { + CellIdentifierPayload cell_identifier = 1; + oneof one_of_insert_option { SelectOption insert_option = 2; }; + oneof one_of_delete_option { SelectOption delete_option = 3; }; +} +message SelectOptionCellChangesetPayload { string grid_id = 1; string row_id = 2; string field_id = 3; 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 d8231dbb2e..75357a520b 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 @@ -6,8 +6,8 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - CellIdentifier, CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, - GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, Row, RowMeta, RowMetaChangeset, RowOrder, + CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, + GridBlockOrder, RepeatedCell, Row, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_revision::{ diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/cell_entities.rs b/frontend/rust-lib/flowy-grid/src/services/cell/cell_entities.rs new file mode 100644 index 0000000000..28465d21e3 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/cell/cell_entities.rs @@ -0,0 +1,69 @@ +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; + +#[derive(ProtoBuf, Default)] +pub struct CreateSelectOptionPayload { + #[pb(index = 1)] + pub cell_identifier: CellIdentifierPayload, + + #[pb(index = 2)] + pub option_name: String, +} + +pub struct CreateSelectOptionParams { + pub cell_identifier: CellIdentifier, + pub option_name: String, +} + +impl TryInto for CreateSelectOptionPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?; + let cell_identifier = self.cell_identifier.try_into()?; + Ok(CreateSelectOptionParams { + cell_identifier, + option_name: option_name.0, + }) + } +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct CellIdentifierPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub field_id: String, + + #[pb(index = 3)] + pub row_id: String, +} + +pub struct CellIdentifier { + pub grid_id: String, + pub field_id: String, + pub row_id: String, +} + +impl TryInto for CellIdentifierPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + Ok(CellIdentifier { + grid_id: grid_id.0, + field_id: field_id.0, + row_id: row_id.0, + }) + } +} + +#[derive(ProtoBuf, Default)] +pub struct SelectOptionName { + #[pb(index = 1)] + pub name: String, +} diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs b/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs new file mode 100644 index 0000000000..d2541866be --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/cell/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod cell_entities; + +pub use cell_entities::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_entities.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_entities.rs new file mode 100644 index 0000000000..b8ac13f773 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_entities.rs @@ -0,0 +1,30 @@ +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use flowy_grid_data_model::parser::NotEmptyUuid; + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct FieldIdentifierPayload { + #[pb(index = 1)] + pub field_id: String, + + #[pb(index = 2)] + pub grid_id: String, +} + +pub struct FieldIdentifier { + pub field_id: String, + pub grid_id: String, +} + +impl TryInto for FieldIdentifierPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + Ok(FieldIdentifier { + grid_id: grid_id.0, + field_id: field_id.0, + }) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs index 61b5889e68..89a1f05c57 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs @@ -1,5 +1,7 @@ mod field_builder; -mod type_options; +pub(crate) mod field_entities; +pub(crate) mod type_options; pub use field_builder::*; +pub use field_entities::*; pub use type_options::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 07bef42e5f..5dee72dec7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,4 +1,5 @@ use crate::impl_type_option; +use crate::services::cell::{CellIdentifier, CellIdentifierPayload}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellData}; use crate::services::util::*; @@ -16,6 +17,12 @@ use uuid::Uuid; pub const SELECTION_IDS_SEPARATOR: &str = ","; +pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync { + fn insert_option(&mut self, new_option: SelectOption); + fn delete_option(&mut self, delete_option: SelectOption); + fn option_context(&self, cell_meta: &Option) -> SelectOptionContext; +} + // Single select #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] pub struct SingleSelectTypeOption { @@ -27,8 +34,23 @@ pub struct SingleSelectTypeOption { } impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); -impl SingleSelectTypeOption { - pub fn select_option_context(&self, cell_meta: &Option) -> SelectOptionContext { +impl SelectOptionOperation for SingleSelectTypeOption { + fn insert_option(&mut self, new_option: SelectOption) { + if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) { + self.options.remove(index); + self.options.insert(index, new_option); + } else { + self.options.insert(0, new_option); + } + } + + fn delete_option(&mut self, delete_option: SelectOption) { + if let Some(index) = self.options.iter().position(|option| option.id == delete_option.id) { + self.options.remove(index); + } + } + + fn option_context(&self, cell_meta: &Option) -> SelectOptionContext { let select_options = make_select_context_from(cell_meta, &self.options); SelectOptionContext { options: self.options.clone(), @@ -37,22 +59,6 @@ impl SingleSelectTypeOption { } } -fn make_select_context_from(cell_meta: &Option, options: &Vec) -> Vec { - match cell_meta { - None => vec![], - Some(cell_meta) => { - if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&cell_meta.data) { - select_option_ids(type_option_cell_data.data) - .into_iter() - .flat_map(|option_id| options.iter().find(|option| option.id == option_id).cloned()) - .collect() - } else { - vec![] - } - } - } -} - impl CellDataOperation for SingleSelectTypeOption { fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { @@ -78,7 +84,7 @@ impl CellDataOperation for SingleSelectTypeOption { _cell_meta: Option, ) -> Result { let changeset = changeset.into(); - let select_option_changeset: SelectOptionChangeset = serde_json::from_str(&changeset)?; + let select_option_changeset: SelectOptionCellChangeset = serde_json::from_str(&changeset)?; let new_cell_data: String; if let Some(insert_option_id) = select_option_changeset.insert_option_id { new_cell_data = insert_option_id; @@ -123,9 +129,28 @@ pub struct MultiSelectTypeOption { } impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); -impl MultiSelectTypeOption { - pub fn select_option_context(&self, cell_meta: &Option) -> SelectOptionContext { - todo!() +impl SelectOptionOperation for MultiSelectTypeOption { + fn insert_option(&mut self, new_option: SelectOption) { + if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) { + self.options.remove(index); + self.options.insert(index, new_option); + } else { + self.options.insert(0, new_option); + } + } + + fn delete_option(&mut self, delete_option: SelectOption) { + if let Some(index) = self.options.iter().position(|option| option.id == delete_option.id) { + self.options.remove(index); + } + } + + fn option_context(&self, cell_meta: &Option) -> SelectOptionContext { + let select_options = make_select_context_from(cell_meta, &self.options); + SelectOptionContext { + options: self.options.clone(), + select_options, + } } } @@ -153,7 +178,7 @@ impl CellDataOperation for MultiSelectTypeOption { cell_meta: Option, ) -> Result { let changeset = changeset.into(); - let select_option_changeset: SelectOptionChangeset = serde_json::from_str(&changeset)?; + let select_option_changeset: SelectOptionCellChangeset = serde_json::from_str(&changeset)?; let new_cell_data: String; match cell_meta { None => { @@ -230,6 +255,37 @@ impl SelectOption { #[derive(Clone, Debug, Default, ProtoBuf)] pub struct SelectOptionChangesetPayload { + #[pb(index = 1)] + pub cell_identifier: CellIdentifierPayload, + + #[pb(index = 2, one_of)] + pub insert_option: Option, + + #[pb(index = 3, one_of)] + pub delete_option: Option, +} + +pub struct SelectOptionChangeset { + pub cell_identifier: CellIdentifier, + pub insert_option: Option, + pub delete_option: Option, +} + +impl TryInto for SelectOptionChangesetPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let cell_identifier = self.cell_identifier.try_into()?; + Ok(SelectOptionChangeset { + cell_identifier, + insert_option: self.insert_option, + delete_option: self.delete_option, + }) + } +} + +#[derive(Clone, Debug, Default, ProtoBuf)] +pub struct SelectOptionCellChangesetPayload { #[pb(index = 1)] pub grid_id: String, @@ -246,7 +302,7 @@ pub struct SelectOptionChangesetPayload { pub delete_option_id: Option, } -pub struct SelectOptionChangesetParams { +pub struct SelectOptionCellChangesetParams { pub grid_id: String, pub field_id: String, pub row_id: String, @@ -255,14 +311,34 @@ pub struct SelectOptionChangesetParams { } #[derive(Clone, Serialize, Deserialize)] -pub struct SelectOptionChangeset { +pub struct SelectOptionCellChangeset { pub insert_option_id: Option, pub delete_option_id: Option, } -impl std::convert::From for CellMetaChangeset { - fn from(params: SelectOptionChangesetParams) -> Self { - let changeset = SelectOptionChangeset { +impl SelectOptionCellChangeset { + pub fn from_insert(option_id: &str) -> Self { + SelectOptionCellChangeset { + insert_option_id: Some(option_id.to_string()), + delete_option_id: None, + } + } + + pub fn from_delete(option_id: &str) -> Self { + SelectOptionCellChangeset { + insert_option_id: None, + delete_option_id: Some(option_id.to_string()), + } + } + + pub fn cell_data(&self) -> String { + serde_json::to_string(self).unwrap() + } +} + +impl std::convert::From for CellMetaChangeset { + fn from(params: SelectOptionCellChangesetParams) -> Self { + let changeset = SelectOptionCellChangeset { insert_option_id: params.insert_option_id, delete_option_id: params.delete_option_id, }; @@ -276,10 +352,10 @@ impl std::convert::From for CellMetaChangeset { } } -impl TryInto for SelectOptionChangesetPayload { +impl TryInto for SelectOptionCellChangesetPayload { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; @@ -301,7 +377,7 @@ impl TryInto for SelectOptionChangesetPayload { ), }; - Ok(SelectOptionChangesetParams { + Ok(SelectOptionCellChangesetParams { grid_id: grid_id.0, row_id: row_id.0, field_id: field_id.0, @@ -340,6 +416,22 @@ impl std::default::Default for SelectOptionColor { } } +fn make_select_context_from(cell_meta: &Option, options: &Vec) -> Vec { + match cell_meta { + None => vec![], + Some(cell_meta) => { + if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&cell_meta.data) { + select_option_ids(type_option_cell_data.data) + .into_iter() + .flat_map(|option_id| options.iter().find(|option| option.id == option_id).cloned()) + .collect() + } else { + vec![] + } + } + } +} + #[cfg(test)] mod tests { use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; 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 1a184d51e9..32dfb43668 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -8,7 +8,7 @@ use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; -use flowy_sync::client_grid::{GridChangeset, GridMetaPad, TypeOptionDataDeserializer}; +use flowy_sync::client_grid::{GridChangeset, GridMetaPad, JsonDeserializer}; use flowy_sync::entities::revision::Revision; use flowy_sync::errors::CollaborateResult; use flowy_sync::util::make_delta_from_revisions; @@ -61,7 +61,7 @@ impl ClientGridEditor { let _ = self .modify(|grid| { if grid.contain_field(&field.id) { - let deserializer = TypeOptionChangesetDeserializer(field.field_type.clone()); + let deserializer = TypeOptionJsonDeserializer(field.field_type.clone()); let changeset = FieldChangesetParams { field_id: field.id, grid_id, @@ -82,7 +82,7 @@ impl ClientGridEditor { } }) .await?; - let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_grid().await?; Ok(()) } @@ -98,20 +98,27 @@ impl ClientGridEditor { pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let field_id = params.field_id.clone(); - let deserializer = match self.pad.read().await.get_field(params.field_id.as_str()) { + let json_deserializer = match self.pad.read().await.get_field(params.field_id.as_str()) { None => return Err(ErrorCode::FieldDoesNotExist.into()), - Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), + Some(field_meta) => TypeOptionJsonDeserializer(field_meta.field_type.clone()), }; - let _ = self.modify(|grid| Ok(grid.update_field(params, deserializer)?)).await?; - let _ = self.notify_did_update_fields().await?; + let _ = self + .modify(|grid| Ok(grid.update_field(params, json_deserializer)?)) + .await?; + let _ = self.notify_did_update_grid().await?; let _ = self.notify_did_update_field(&field_id).await?; Ok(()) } + pub async fn replace_field(&self, field_meta: FieldMeta) -> FlowyResult<()> { + let _ = self.modify(|pad| Ok(pad.replace_field(field_meta)?)).await?; + Ok(()) + } + pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?; - let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_grid().await?; Ok(()) } @@ -134,28 +141,33 @@ impl ClientGridEditor { let _ = self .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) .await?; - let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_grid().await?; let _ = self.notify_did_update_field(field_id).await?; Ok(()) } pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.duplicate_field(field_id)?)).await?; - let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_grid().await?; Ok(()) } - pub async fn get_field_metas(&self, field_orders: Option>) -> FlowyResult> + pub async fn get_field_meta(&self, field_id: &str) -> Option { + let field_meta = self.pad.read().await.get_field(field_id)?.clone(); + return Some(field_meta); + } + + pub async fn get_field_metas(&self, field_ids: Option>) -> FlowyResult> where T: Into, { - if field_orders.is_none() { + if field_ids.is_none() { let field_metas = self.pad.read().await.get_field_metas(None)?; return Ok(field_metas); } let to_field_orders = |item: Vec| item.into_iter().map(|data| data.into()).collect(); - let field_orders = field_orders.map_or(vec![], to_field_orders); + let field_orders = field_ids.map_or(vec![], to_field_orders); let expected_len = field_orders.len(); let field_metas = self.pad.read().await.get_field_metas(Some(field_orders))?; if expected_len != 0 && field_metas.len() != expected_len { @@ -382,10 +394,10 @@ impl ClientGridEditor { } } - async fn notify_did_update_fields(&self) -> FlowyResult<()> { + async fn notify_did_update_grid(&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::DidUpdateFields) + send_dart_notification(&self.grid_id, GridNotification::DidUpdateGrid) .payload(repeated_field) .send(); Ok(()) @@ -442,12 +454,10 @@ impl RevisionCompactor for GridRevisionCompactor { } } -struct TypeOptionChangesetDeserializer(FieldType); -impl TypeOptionDataDeserializer for TypeOptionChangesetDeserializer { +struct TypeOptionJsonDeserializer(FieldType); +impl JsonDeserializer for TypeOptionJsonDeserializer { fn deserialize(&self, type_option_data: Vec) -> CollaborateResult { - // The type_option_data is serialized by protobuf. But the type_option_data should be - // serialized by utf-8. So we must transform the data here. - + // The type_option_data sent from Dart is serialized by protobuf. let builder = type_option_builder_from_bytes(type_option_data, &self.0); Ok(builder.entry().json_str()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/mod.rs b/frontend/rust-lib/flowy-grid/src/services/mod.rs index 6ae3be1dca..88e7fbec10 100644 --- a/frontend/rust-lib/flowy-grid/src/services/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/mod.rs @@ -1,6 +1,7 @@ mod util; pub mod block_meta_editor; +pub mod cell; pub mod field; pub mod grid_editor; pub mod persistence; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs index 9c8a04bdc3..e34c25b488 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs @@ -90,9 +90,8 @@ impl TypeOptionCellData { } } -/// The function,apply_cell_data_changeset, will apply the cell_data_changeset. -/// -/// The cell_data_changeset will be deserialized into specific data base on the FieldType. +/// The changeset will be deserialized into specific data base on the FieldType. +/// For example, it's String on FieldType::RichText, and SelectOptionChangeset on FieldType::SingleSelect pub fn apply_cell_data_changeset>( changeset: T, cell_meta: Option, diff --git a/frontend/rust-lib/flowy-grid/src/services/row/mod.rs b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs index e2727cdf34..f9bf130e8b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs @@ -1,5 +1,6 @@ mod cell_data_operation; mod row_builder; +pub mod row_entities; mod row_loader; pub use cell_data_operation::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs new file mode 100644 index 0000000000..e88ed4ffb9 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs @@ -0,0 +1,31 @@ +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; + +#[derive(ProtoBuf, Default)] +pub struct RowIdentifierPayload { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 3)] + pub row_id: String, +} + +pub struct RowIdentifier { + pub grid_id: String, + pub row_id: String, +} + +impl TryInto for RowIdentifierPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + + Ok(RowIdentifier { + grid_id: grid_id.0, + row_id: row_id.0, + }) + } +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index c14c937f00..5ac780519b 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -59,13 +59,7 @@ async fn grid_update_field_with_empty_change() { let changeset = FieldChangesetParams { field_id: field_meta.id.clone(), grid_id: test.grid_id.clone(), - name: None, - desc: None, - field_type: None, - frozen: None, - visibility: None, - width: None, - type_option_data: None, + ..Default::default() }; let scripts = vec![ @@ -90,13 +84,10 @@ async fn grid_update_field() { let changeset = FieldChangesetParams { field_id: single_select_field.id.clone(), grid_id: test.grid_id.clone(), - name: None, - desc: None, - field_type: None, frozen: Some(true), - visibility: None, width: Some(1000), type_option_data: Some(single_select_type_option.protobuf_bytes().to_vec()), + ..Default::default() }; cloned_field.frozen = true; diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 30af0f9885..0315306871 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -103,6 +103,10 @@ pub enum ErrorCode { FieldDoesNotExist = 441, #[display(fmt = "The name of the option should not be empty")] SelectOptionNameIsEmpty = 442, + #[display(fmt = "Field not exists")] + FieldNotExists = 443, + #[display(fmt = "The operation in this field is invalid")] + FieldInvalidOperation = 444, #[display(fmt = "Field's type option data should not be empty")] TypeOptionDataIsEmpty = 450, diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs index f3d669a681..5653852147 100644 --- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs +++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs @@ -64,6 +64,8 @@ pub enum ErrorCode { FieldIdIsEmpty = 440, FieldDoesNotExist = 441, SelectOptionNameIsEmpty = 442, + FieldNotExists = 443, + FieldInvalidOperation = 444, TypeOptionDataIsEmpty = 450, InvalidData = 500, } @@ -114,6 +116,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode { 440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty), 441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist), 442 => ::std::option::Option::Some(ErrorCode::SelectOptionNameIsEmpty), + 443 => ::std::option::Option::Some(ErrorCode::FieldNotExists), + 444 => ::std::option::Option::Some(ErrorCode::FieldInvalidOperation), 450 => ::std::option::Option::Some(ErrorCode::TypeOptionDataIsEmpty), 500 => ::std::option::Option::Some(ErrorCode::InvalidData), _ => ::std::option::Option::None @@ -161,6 +165,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode { ErrorCode::FieldIdIsEmpty, ErrorCode::FieldDoesNotExist, ErrorCode::SelectOptionNameIsEmpty, + ErrorCode::FieldNotExists, + ErrorCode::FieldInvalidOperation, ErrorCode::TypeOptionDataIsEmpty, ErrorCode::InvalidData, ]; @@ -191,7 +197,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\ncode.proto*\xb4\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ + \n\ncode.proto*\xe5\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\ \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\ \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\ \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\ @@ -212,9 +218,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\ \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x14\n\x0fOptionIdIsEmpty\x10\xaf\x03\ \x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\x12\x16\n\x11FieldDoesNotExist\ - \x10\xb9\x03\x12\x1c\n\x17SelectOptionNameIsEmpty\x10\xba\x03\x12\x1a\n\ - \x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\ - \x03b\x06proto3\ + \x10\xb9\x03\x12\x1c\n\x17SelectOptionNameIsEmpty\x10\xba\x03\x12\x13\n\ + \x0eFieldNotExists\x10\xbb\x03\x12\x1a\n\x15FieldInvalidOperation\x10\ + \xbc\x03\x12\x1a\n\x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\x10\n\x0bInv\ + alidData\x10\xf4\x03b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto index 8ea2941815..aca3309526 100644 --- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto +++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto @@ -40,6 +40,8 @@ enum ErrorCode { FieldIdIsEmpty = 440; FieldDoesNotExist = 441; SelectOptionNameIsEmpty = 442; + FieldNotExists = 443; + FieldInvalidOperation = 444; TypeOptionDataIsEmpty = 450; InvalidData = 500; } 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 56c76d1925..87a35b822d 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -55,33 +55,6 @@ impl std::convert::From for Field { } } -#[derive(Debug, Clone, Default, ProtoBuf)] -pub struct FieldIdentifierPayload { - #[pb(index = 1)] - pub field_id: String, - - #[pb(index = 2)] - pub grid_id: String, -} - -pub struct FieldIdentifierParams { - pub field_id: String, - pub grid_id: String, -} - -impl TryInto for FieldIdentifierPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; - Ok(FieldIdentifierParams { - grid_id: grid_id.0, - field_id: field_id.0, - }) - } -} - #[derive(Debug, Clone, Default, ProtoBuf)] pub struct FieldOrder { #[pb(index = 1)] @@ -331,39 +304,6 @@ impl Cell { } } -#[derive(Debug, Clone, Default, ProtoBuf)] -pub struct CellIdentifierPayload { - #[pb(index = 1)] - pub grid_id: String, - - #[pb(index = 2)] - pub field_id: String, - - #[pb(index = 3)] - pub row_id: String, -} - -pub struct CellIdentifier { - pub grid_id: String, - pub field_id: String, - pub row_id: String, -} - -impl TryInto for CellIdentifierPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; - let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - Ok(CellIdentifier { - grid_id: grid_id.0, - field_id: field_id.0, - row_id: row_id.0, - }) - } -} - #[derive(Debug, Clone, Default, ProtoBuf)] pub struct CellNotificationData { #[pb(index = 1)] @@ -561,57 +501,3 @@ impl TryInto for QueryGridBlocksPayload { }) } } - -#[derive(ProtoBuf, Default)] -pub struct QueryRowPayload { - #[pb(index = 1)] - pub grid_id: String, - - #[pb(index = 3)] - pub row_id: String, -} - -pub struct QueryRowParams { - pub grid_id: String, - pub row_id: String, -} - -impl TryInto for QueryRowPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; - - Ok(QueryRowParams { - grid_id: grid_id.0, - row_id: row_id.0, - }) - } -} - -#[derive(ProtoBuf, Default)] -pub struct CreateSelectOptionPayload { - #[pb(index = 1)] - pub option_name: String, - - #[pb(index = 2)] - pub selected: bool, -} - -pub struct CreateSelectOptionParams { - pub option_name: String, - pub selected: bool, -} - -impl TryInto for CreateSelectOptionPayload { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?; - Ok(CreateSelectOptionParams { - option_name: option_name.0, - selected: self.selected, - }) - } -} 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 a64dad9191..c31a2def27 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 @@ -659,207 +659,6 @@ impl ::protobuf::reflect::ProtobufValue for Field { } } -#[derive(PartialEq,Clone,Default)] -pub struct FieldIdentifierPayload { - // message fields - pub field_id: ::std::string::String, - pub grid_id: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a FieldIdentifierPayload { - fn default() -> &'a FieldIdentifierPayload { - ::default_instance() - } -} - -impl FieldIdentifierPayload { - pub fn new() -> FieldIdentifierPayload { - ::std::default::Default::default() - } - - // string field_id = 1; - - - pub fn get_field_id(&self) -> &str { - &self.field_id - } - pub fn clear_field_id(&mut self) { - self.field_id.clear(); - } - - // Param is passed by value, moved - pub fn set_field_id(&mut self, v: ::std::string::String) { - self.field_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_field_id(&mut self) -> &mut ::std::string::String { - &mut self.field_id - } - - // Take field - pub fn take_field_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) - } - - // string grid_id = 2; - - - pub fn get_grid_id(&self) -> &str { - &self.grid_id - } - pub fn clear_grid_id(&mut self) { - self.grid_id.clear(); - } - - // Param is passed by value, moved - pub fn set_grid_id(&mut self, v: ::std::string::String) { - self.grid_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { - &mut self.grid_id - } - - // Take field - pub fn take_grid_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for FieldIdentifierPayload { - 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.field_id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; - }, - _ => { - ::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.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.field_id); - } - if !self.grid_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.grid_id); - } - 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.field_id.is_empty() { - os.write_string(1, &self.field_id)?; - } - if !self.grid_id.is_empty() { - os.write_string(2, &self.grid_id)?; - } - 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() -> FieldIdentifierPayload { - FieldIdentifierPayload::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>( - "field_id", - |m: &FieldIdentifierPayload| { &m.field_id }, - |m: &mut FieldIdentifierPayload| { &mut m.field_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "grid_id", - |m: &FieldIdentifierPayload| { &m.grid_id }, - |m: &mut FieldIdentifierPayload| { &mut m.grid_id }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "FieldIdentifierPayload", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static FieldIdentifierPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(FieldIdentifierPayload::new) - } -} - -impl ::protobuf::Clear for FieldIdentifierPayload { - fn clear(&mut self) { - self.field_id.clear(); - self.grid_id.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for FieldIdentifierPayload { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for FieldIdentifierPayload { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - #[derive(PartialEq,Clone,Default)] pub struct FieldOrder { // message fields @@ -3480,249 +3279,6 @@ impl ::protobuf::reflect::ProtobufValue for Cell { } } -#[derive(PartialEq,Clone,Default)] -pub struct CellIdentifierPayload { - // message fields - pub grid_id: ::std::string::String, - pub field_id: ::std::string::String, - pub row_id: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a CellIdentifierPayload { - fn default() -> &'a CellIdentifierPayload { - ::default_instance() - } -} - -impl CellIdentifierPayload { - pub fn new() -> CellIdentifierPayload { - ::std::default::Default::default() - } - - // string grid_id = 1; - - - pub fn get_grid_id(&self) -> &str { - &self.grid_id - } - pub fn clear_grid_id(&mut self) { - self.grid_id.clear(); - } - - // Param is passed by value, moved - pub fn set_grid_id(&mut self, v: ::std::string::String) { - self.grid_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { - &mut self.grid_id - } - - // Take field - pub fn take_grid_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) - } - - // string field_id = 2; - - - pub fn get_field_id(&self) -> &str { - &self.field_id - } - pub fn clear_field_id(&mut self) { - self.field_id.clear(); - } - - // Param is passed by value, moved - pub fn set_field_id(&mut self, v: ::std::string::String) { - self.field_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_field_id(&mut self) -> &mut ::std::string::String { - &mut self.field_id - } - - // Take field - pub fn take_field_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) - } - - // string row_id = 3; - - - pub fn get_row_id(&self) -> &str { - &self.row_id - } - pub fn clear_row_id(&mut self) { - self.row_id.clear(); - } - - // Param is passed by value, moved - pub fn set_row_id(&mut self, v: ::std::string::String) { - self.row_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_row_id(&mut self) -> &mut ::std::string::String { - &mut self.row_id - } - - // Take field - pub fn take_row_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for CellIdentifierPayload { - 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.grid_id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; - }, - 3 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; - }, - _ => { - ::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.grid_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.grid_id); - } - if !self.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.field_id); - } - if !self.row_id.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.row_id); - } - 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.grid_id.is_empty() { - os.write_string(1, &self.grid_id)?; - } - if !self.field_id.is_empty() { - os.write_string(2, &self.field_id)?; - } - if !self.row_id.is_empty() { - os.write_string(3, &self.row_id)?; - } - 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() -> CellIdentifierPayload { - CellIdentifierPayload::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>( - "grid_id", - |m: &CellIdentifierPayload| { &m.grid_id }, - |m: &mut CellIdentifierPayload| { &mut m.grid_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "field_id", - |m: &CellIdentifierPayload| { &m.field_id }, - |m: &mut CellIdentifierPayload| { &mut m.field_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "row_id", - |m: &CellIdentifierPayload| { &m.row_id }, - |m: &mut CellIdentifierPayload| { &mut m.row_id }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CellIdentifierPayload", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static CellIdentifierPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CellIdentifierPayload::new) - } -} - -impl ::protobuf::Clear for CellIdentifierPayload { - fn clear(&mut self) { - self.grid_id.clear(); - self.field_id.clear(); - self.row_id.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for CellIdentifierPayload { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for CellIdentifierPayload { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - #[derive(PartialEq,Clone,Default)] pub struct CellNotificationData { // message fields @@ -5696,401 +5252,6 @@ impl ::protobuf::reflect::ProtobufValue for QueryGridBlocksPayload { } } -#[derive(PartialEq,Clone,Default)] -pub struct QueryRowPayload { - // message fields - pub grid_id: ::std::string::String, - pub row_id: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a QueryRowPayload { - fn default() -> &'a QueryRowPayload { - ::default_instance() - } -} - -impl QueryRowPayload { - pub fn new() -> QueryRowPayload { - ::std::default::Default::default() - } - - // string grid_id = 1; - - - pub fn get_grid_id(&self) -> &str { - &self.grid_id - } - pub fn clear_grid_id(&mut self) { - self.grid_id.clear(); - } - - // Param is passed by value, moved - pub fn set_grid_id(&mut self, v: ::std::string::String) { - self.grid_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { - &mut self.grid_id - } - - // Take field - pub fn take_grid_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) - } - - // string row_id = 3; - - - pub fn get_row_id(&self) -> &str { - &self.row_id - } - pub fn clear_row_id(&mut self) { - self.row_id.clear(); - } - - // Param is passed by value, moved - pub fn set_row_id(&mut self, v: ::std::string::String) { - self.row_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_row_id(&mut self) -> &mut ::std::string::String { - &mut self.row_id - } - - // Take field - pub fn take_row_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) - } -} - -impl ::protobuf::Message for QueryRowPayload { - 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.grid_id)?; - }, - 3 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; - }, - _ => { - ::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.grid_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.grid_id); - } - if !self.row_id.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.row_id); - } - 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.grid_id.is_empty() { - os.write_string(1, &self.grid_id)?; - } - if !self.row_id.is_empty() { - os.write_string(3, &self.row_id)?; - } - 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() -> QueryRowPayload { - QueryRowPayload::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>( - "grid_id", - |m: &QueryRowPayload| { &m.grid_id }, - |m: &mut QueryRowPayload| { &mut m.grid_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "row_id", - |m: &QueryRowPayload| { &m.row_id }, - |m: &mut QueryRowPayload| { &mut m.row_id }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "QueryRowPayload", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static QueryRowPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(QueryRowPayload::new) - } -} - -impl ::protobuf::Clear for QueryRowPayload { - fn clear(&mut self) { - self.grid_id.clear(); - self.row_id.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for QueryRowPayload { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for QueryRowPayload { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct CreateSelectOptionPayload { - // message fields - pub option_name: ::std::string::String, - pub selected: bool, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a CreateSelectOptionPayload { - fn default() -> &'a CreateSelectOptionPayload { - ::default_instance() - } -} - -impl CreateSelectOptionPayload { - pub fn new() -> CreateSelectOptionPayload { - ::std::default::Default::default() - } - - // string option_name = 1; - - - pub fn get_option_name(&self) -> &str { - &self.option_name - } - pub fn clear_option_name(&mut self) { - self.option_name.clear(); - } - - // Param is passed by value, moved - pub fn set_option_name(&mut self, v: ::std::string::String) { - self.option_name = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_option_name(&mut self) -> &mut ::std::string::String { - &mut self.option_name - } - - // Take field - pub fn take_option_name(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.option_name, ::std::string::String::new()) - } - - // bool selected = 2; - - - pub fn get_selected(&self) -> bool { - self.selected - } - pub fn clear_selected(&mut self) { - self.selected = false; - } - - // Param is passed by value, moved - pub fn set_selected(&mut self, v: bool) { - self.selected = v; - } -} - -impl ::protobuf::Message for CreateSelectOptionPayload { - 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.option_name)?; - }, - 2 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_bool()?; - self.selected = tmp; - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.option_name.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.option_name); - } - if self.selected != false { - my_size += 2; - } - 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.option_name.is_empty() { - os.write_string(1, &self.option_name)?; - } - if self.selected != false { - os.write_bool(2, self.selected)?; - } - 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() -> CreateSelectOptionPayload { - CreateSelectOptionPayload::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>( - "option_name", - |m: &CreateSelectOptionPayload| { &m.option_name }, - |m: &mut CreateSelectOptionPayload| { &mut m.option_name }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( - "selected", - |m: &CreateSelectOptionPayload| { &m.selected }, - |m: &mut CreateSelectOptionPayload| { &mut m.selected }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CreateSelectOptionPayload", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static CreateSelectOptionPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CreateSelectOptionPayload::new) - } -} - -impl ::protobuf::Clear for CreateSelectOptionPayload { - fn clear(&mut self) { - self.option_name.clear(); - self.selected = false; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for CreateSelectOptionPayload { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for CreateSelectOptionPayload { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - static file_descriptor_proto_data: &'static [u8] = b"\ \n\ngrid.proto\x1a\nmeta.proto\"z\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\ \x01(\tR\x02id\x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrd\ @@ -6100,61 +5261,53 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\ \x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\ \x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\ - \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"L\n\x16FieldIdentifi\ - erPayload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\ - \x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08\ - field_id\x18\x01\x20\x01(\tR\x07fieldId\"\x90\x01\n\x1aGetEditFieldConte\ - xtPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\ - \x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\ - \x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"q\ - \n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridI\ - d\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\nfield_typ\ - e\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\ - \x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\ - \x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\ - \x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFiel\ - dOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\ - \n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\ - \n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\ - \x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\ - \x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.\ - Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\ - \x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\ - \x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.Cel\ - lR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\ - \x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05item\ - s\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\ - \x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\ - \x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\ - \x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\ - \x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07\ - content\"b\n\x15CellIdentifierPayload\x12\x17\n\x07grid_id\x18\x01\x20\ - \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ - \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"\x8f\x01\n\x14CellNot\ - ificationData\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\ - \n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\ - \x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\ - \x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05i\ - tems\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\"#\n\x0bGridBlockId\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\x0cstart_row_id\x18\ - \x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\ - \n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gri\ - dId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\ - \x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0es\ - tart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_st\ - art_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\ - \x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.Repe\ - atedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\ - \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\ - \x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"A\n\x0fQueryRowPayloa\ - d\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\ - \x18\x03\x20\x01(\tR\x05rowId\"X\n\x19CreateSelectOptionPayload\x12\x1f\ - \n\x0boption_name\x18\x01\x20\x01(\tR\noptionName\x12\x1a\n\x08selected\ - \x18\x02\x20\x01(\x08R\x08selectedb\x06proto3\ + \x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\ + \x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"\x90\x01\n\x1aGetEdit\ + FieldContextPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ + \x12\x1b\n\x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_t\ + ype\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field\ + _id\"q\n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ + \x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\n\ + field_type\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFie\ + ldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngri\ + d_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_optio\ + n_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\ + \x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\ + edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\ + ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\ + \x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\ + t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\ + \x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\ + \x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\ + \x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ + .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ + \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ + items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ + \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ + \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ + \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ + \x07content\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07\ + fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07co\ + ntent\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\ + \x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05i\ + tems\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04\ + name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"\ + #\n\x0bGridBlockId\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\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13on\ + e_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\ + \x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\ + \x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\ + \x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cst\ + artFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\ + \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\ + \x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16Qu\ + eryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ + \x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblo\ + ckOrdersb\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/model/mod.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs index d011b76000..e2e2c75a6e 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs @@ -4,5 +4,8 @@ mod grid; pub use grid::*; +mod type_option; +pub use type_option::*; + mod meta; pub use meta::*; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs new file mode 100644 index 0000000000..1cad4b09e8 --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs @@ -0,0 +1,978 @@ +// 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 `type_option.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOption { + // message fields + pub id: ::std::string::String, + pub name: ::std::string::String, + pub color: SelectOptionColor, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOption { + fn default() -> &'a SelectOption { + ::default_instance() + } +} + +impl SelectOption { + pub fn new() -> SelectOption { + ::std::default::Default::default() + } + + // string id = 1; + + + pub fn get_id(&self) -> &str { + &self.id + } + pub fn clear_id(&mut self) { + self.id.clear(); + } + + // Param is passed by value, moved + pub fn set_id(&mut self, v: ::std::string::String) { + self.id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_id(&mut self) -> &mut ::std::string::String { + &mut self.id + } + + // Take field + pub fn take_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.id, ::std::string::String::new()) + } + + // string name = 2; + + + pub fn get_name(&self) -> &str { + &self.name + } + pub fn clear_name(&mut self) { + self.name.clear(); + } + + // Param is passed by value, moved + pub fn set_name(&mut self, v: ::std::string::String) { + self.name = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_name(&mut self) -> &mut ::std::string::String { + &mut self.name + } + + // Take field + pub fn take_name(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.name, ::std::string::String::new()) + } + + // .SelectOptionColor color = 3; + + + pub fn get_color(&self) -> SelectOptionColor { + self.color + } + pub fn clear_color(&mut self) { + self.color = SelectOptionColor::Purple; + } + + // Param is passed by value, moved + pub fn set_color(&mut self, v: SelectOptionColor) { + self.color = v; + } +} + +impl ::protobuf::Message for SelectOption { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; + }, + 3 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.color, 3, &mut self.unknown_fields)? + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.id); + } + if !self.name.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.name); + } + if self.color != SelectOptionColor::Purple { + my_size += ::protobuf::rt::enum_size(3, self.color); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.id.is_empty() { + os.write_string(1, &self.id)?; + } + if !self.name.is_empty() { + os.write_string(2, &self.name)?; + } + if self.color != SelectOptionColor::Purple { + os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.color))?; + } + 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() -> SelectOption { + SelectOption::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "id", + |m: &SelectOption| { &m.id }, + |m: &mut SelectOption| { &mut m.id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "name", + |m: &SelectOption| { &m.name }, + |m: &mut SelectOption| { &mut m.name }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "color", + |m: &SelectOption| { &m.color }, + |m: &mut SelectOption| { &mut m.color }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOption", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOption { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOption::new) + } +} + +impl ::protobuf::Clear for SelectOption { + fn clear(&mut self) { + self.id.clear(); + self.name.clear(); + self.color = SelectOptionColor::Purple; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOption { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOption { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionCellChangesetPayload { + // message fields + pub grid_id: ::std::string::String, + pub row_id: ::std::string::String, + pub field_id: ::std::string::String, + // message oneof groups + pub one_of_insert_option_id: ::std::option::Option, + pub one_of_delete_option_id: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOptionCellChangesetPayload { + fn default() -> &'a SelectOptionCellChangesetPayload { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id { + insert_option_id(::std::string::String), +} + +#[derive(Clone,PartialEq,Debug)] +pub enum SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id { + delete_option_id(::std::string::String), +} + +impl SelectOptionCellChangesetPayload { + pub fn new() -> SelectOptionCellChangesetPayload { + ::std::default::Default::default() + } + + // string grid_id = 1; + + + pub fn get_grid_id(&self) -> &str { + &self.grid_id + } + pub fn clear_grid_id(&mut self) { + self.grid_id.clear(); + } + + // Param is passed by value, moved + pub fn set_grid_id(&mut self, v: ::std::string::String) { + self.grid_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { + &mut self.grid_id + } + + // Take field + pub fn take_grid_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) + } + + // string row_id = 2; + + + pub fn get_row_id(&self) -> &str { + &self.row_id + } + pub fn clear_row_id(&mut self) { + self.row_id.clear(); + } + + // Param is passed by value, moved + pub fn set_row_id(&mut self, v: ::std::string::String) { + self.row_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_row_id(&mut self) -> &mut ::std::string::String { + &mut self.row_id + } + + // Take field + pub fn take_row_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) + } + + // string field_id = 3; + + + pub fn get_field_id(&self) -> &str { + &self.field_id + } + pub fn clear_field_id(&mut self) { + self.field_id.clear(); + } + + // Param is passed by value, moved + pub fn set_field_id(&mut self, v: ::std::string::String) { + self.field_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_field_id(&mut self) -> &mut ::std::string::String { + &mut self.field_id + } + + // Take field + pub fn take_field_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + } + + // string insert_option_id = 4; + + + pub fn get_insert_option_id(&self) -> &str { + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v)) => v, + _ => "", + } + } + pub fn clear_insert_option_id(&mut self) { + self.one_of_insert_option_id = ::std::option::Option::None; + } + + pub fn has_insert_option_id(&self) -> bool { + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_insert_option_id(&mut self, v: ::std::string::String) { + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_insert_option_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(_)) = self.one_of_insert_option_id { + } else { + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(::std::string::String::new())); + } + match self.one_of_insert_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_insert_option_id(&mut self) -> ::std::string::String { + if self.has_insert_option_id() { + match self.one_of_insert_option_id.take() { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } + + // string delete_option_id = 5; + + + pub fn get_delete_option_id(&self) -> &str { + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v)) => v, + _ => "", + } + } + pub fn clear_delete_option_id(&mut self) { + self.one_of_delete_option_id = ::std::option::Option::None; + } + + pub fn has_delete_option_id(&self) -> bool { + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_delete_option_id(&mut self, v: ::std::string::String) { + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) + } + + // Mutable pointer to the field. + pub fn mut_delete_option_id(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(_)) = self.one_of_delete_option_id { + } else { + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(::std::string::String::new())); + } + match self.one_of_delete_option_id { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_delete_option_id(&mut self) -> ::std::string::String { + if self.has_delete_option_id() { + match self.one_of_delete_option_id.take() { + ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } +} + +impl ::protobuf::Message for SelectOptionCellChangesetPayload { + 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.grid_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; + }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); + }, + 5 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(is.read_string()?)); + }, + _ => { + ::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.grid_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.grid_id); + } + if !self.row_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.row_id); + } + if !self.field_id.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.field_id); + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { + match v { + &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + my_size += ::protobuf::rt::string_size(4, &v); + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { + match v { + &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + my_size += ::protobuf::rt::string_size(5, &v); + }, + }; + } + 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.grid_id.is_empty() { + os.write_string(1, &self.grid_id)?; + } + if !self.row_id.is_empty() { + os.write_string(2, &self.row_id)?; + } + if !self.field_id.is_empty() { + os.write_string(3, &self.field_id)?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { + match v { + &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { + os.write_string(4, v)?; + }, + }; + } + if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { + match v { + &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { + os.write_string(5, v)?; + }, + }; + } + 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() -> SelectOptionCellChangesetPayload { + SelectOptionCellChangesetPayload::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>( + "grid_id", + |m: &SelectOptionCellChangesetPayload| { &m.grid_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.grid_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "row_id", + |m: &SelectOptionCellChangesetPayload| { &m.row_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.row_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "field_id", + |m: &SelectOptionCellChangesetPayload| { &m.field_id }, + |m: &mut SelectOptionCellChangesetPayload| { &mut m.field_id }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "insert_option_id", + SelectOptionCellChangesetPayload::has_insert_option_id, + SelectOptionCellChangesetPayload::get_insert_option_id, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "delete_option_id", + SelectOptionCellChangesetPayload::has_delete_option_id, + SelectOptionCellChangesetPayload::get_delete_option_id, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionCellChangesetPayload", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionCellChangesetPayload { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionCellChangesetPayload::new) + } +} + +impl ::protobuf::Clear for SelectOptionCellChangesetPayload { + fn clear(&mut self) { + self.grid_id.clear(); + self.row_id.clear(); + self.field_id.clear(); + self.one_of_insert_option_id = ::std::option::Option::None; + self.one_of_delete_option_id = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionCellChangesetPayload { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionCellChangesetPayload { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct SelectOptionContext { + // message fields + pub options: ::protobuf::RepeatedField, + pub select_options: ::protobuf::RepeatedField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a SelectOptionContext { + fn default() -> &'a SelectOptionContext { + ::default_instance() + } +} + +impl SelectOptionContext { + pub fn new() -> SelectOptionContext { + ::std::default::Default::default() + } + + // repeated .SelectOption options = 1; + + + pub fn get_options(&self) -> &[SelectOption] { + &self.options + } + pub fn clear_options(&mut self) { + self.options.clear(); + } + + // Param is passed by value, moved + pub fn set_options(&mut self, v: ::protobuf::RepeatedField) { + self.options = v; + } + + // Mutable pointer to the field. + pub fn mut_options(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.options + } + + // Take field + pub fn take_options(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.options, ::protobuf::RepeatedField::new()) + } + + // repeated .SelectOption select_options = 2; + + + pub fn get_select_options(&self) -> &[SelectOption] { + &self.select_options + } + pub fn clear_select_options(&mut self) { + self.select_options.clear(); + } + + // Param is passed by value, moved + pub fn set_select_options(&mut self, v: ::protobuf::RepeatedField) { + self.select_options = v; + } + + // Mutable pointer to the field. + pub fn mut_select_options(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.select_options + } + + // Take field + pub fn take_select_options(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.select_options, ::protobuf::RepeatedField::new()) + } +} + +impl ::protobuf::Message for SelectOptionContext { + fn is_initialized(&self) -> bool { + for v in &self.options { + if !v.is_initialized() { + return false; + } + }; + for v in &self.select_options { + 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.options)?; + }, + 2 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.select_options)?; + }, + _ => { + ::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.options { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + for value in &self.select_options { + 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.options { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + for v in &self.select_options { + os.write_tag(2, ::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() -> SelectOptionContext { + SelectOptionContext::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>( + "options", + |m: &SelectOptionContext| { &m.options }, + |m: &mut SelectOptionContext| { &mut m.options }, + )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "select_options", + |m: &SelectOptionContext| { &m.select_options }, + |m: &mut SelectOptionContext| { &mut m.select_options }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "SelectOptionContext", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static SelectOptionContext { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(SelectOptionContext::new) + } +} + +impl ::protobuf::Clear for SelectOptionContext { + fn clear(&mut self) { + self.options.clear(); + self.select_options.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for SelectOptionContext { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionContext { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum SelectOptionColor { + Purple = 0, + Pink = 1, + LightPink = 2, + Orange = 3, + Yellow = 4, + Lime = 5, + Green = 6, + Aqua = 7, + Blue = 8, +} + +impl ::protobuf::ProtobufEnum for SelectOptionColor { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(SelectOptionColor::Purple), + 1 => ::std::option::Option::Some(SelectOptionColor::Pink), + 2 => ::std::option::Option::Some(SelectOptionColor::LightPink), + 3 => ::std::option::Option::Some(SelectOptionColor::Orange), + 4 => ::std::option::Option::Some(SelectOptionColor::Yellow), + 5 => ::std::option::Option::Some(SelectOptionColor::Lime), + 6 => ::std::option::Option::Some(SelectOptionColor::Green), + 7 => ::std::option::Option::Some(SelectOptionColor::Aqua), + 8 => ::std::option::Option::Some(SelectOptionColor::Blue), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [SelectOptionColor] = &[ + SelectOptionColor::Purple, + SelectOptionColor::Pink, + SelectOptionColor::LightPink, + SelectOptionColor::Orange, + SelectOptionColor::Yellow, + SelectOptionColor::Lime, + SelectOptionColor::Green, + SelectOptionColor::Aqua, + SelectOptionColor::Blue, + ]; + 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::("SelectOptionColor", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for SelectOptionColor { +} + +impl ::std::default::Default for SelectOptionColor { + fn default() -> Self { + SelectOptionColor::Purple + } +} + +impl ::protobuf::reflect::ProtobufValue for SelectOptionColor { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x11type_option.proto\"\\\n\x0cSelectOption\x12\x0e\n\x02id\x18\x01\ + \x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12(\n\ + \x05color\x18\x03\x20\x01(\x0e2\x12.SelectOptionColorR\x05color\"\xfb\ + \x01\n\x20SelectOptionCellChangesetPayload\x12\x17\n\x07grid_id\x18\x01\ + \x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\ + \x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12*\n\x10insert_o\ + ption_id\x18\x04\x20\x01(\tH\0R\x0einsertOptionId\x12*\n\x10delete_optio\ + n_id\x18\x05\x20\x01(\tH\x01R\x0edeleteOptionIdB\x19\n\x17one_of_insert_\ + option_idB\x19\n\x17one_of_delete_option_id\"t\n\x13SelectOptionContext\ + \x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x124\ + \n\x0eselect_options\x18\x02\x20\x03(\x0b2\r.SelectOptionR\rselectOption\ + s*y\n\x11SelectOptionColor\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\ + \x01\x12\r\n\tLightPink\x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yel\ + low\x10\x04\x12\x08\n\x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\ + \x04Aqua\x10\x07\x12\x08\n\x04Blue\x10\x08b\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/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index 6be5bf1a64..c1166a3ae1 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 @@ -15,10 +15,6 @@ message Field { bool visibility = 6; int32 width = 7; } -message FieldIdentifierPayload { - string field_id = 1; - string grid_id = 2; -} message FieldOrder { string field_id = 1; } @@ -70,11 +66,6 @@ message Cell { string field_id = 1; string content = 2; } -message CellIdentifierPayload { - string grid_id = 1; - string field_id = 2; - string row_id = 3; -} message CellNotificationData { string grid_id = 1; string field_id = 2; @@ -111,11 +102,3 @@ message QueryGridBlocksPayload { string grid_id = 1; repeated GridBlockOrder block_orders = 2; } -message QueryRowPayload { - string grid_id = 1; - string row_id = 3; -} -message CreateSelectOptionPayload { - string option_name = 1; - bool selected = 2; -} diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto new file mode 100644 index 0000000000..5f375f93aa --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +message SelectOption { + string id = 1; + string name = 2; + SelectOptionColor color = 3; +} +message SelectOptionCellChangesetPayload { + string grid_id = 1; + string row_id = 2; + string field_id = 3; + oneof one_of_insert_option_id { string insert_option_id = 4; }; + oneof one_of_delete_option_id { string delete_option_id = 5; }; +} +message SelectOptionContext { + repeated SelectOption options = 1; + repeated SelectOption select_options = 2; +} +enum SelectOptionColor { + Purple = 0; + Pink = 1; + LightPink = 2; + Orange = 3; + Yellow = 4; + Lime = 5; + Green = 6; + Aqua = 7; + Blue = 8; +} diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 2d2e9888f6..8329d9cc9c 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -20,7 +20,7 @@ pub struct GridMetaPad { pub(crate) delta: GridMetaDelta, } -pub trait TypeOptionDataDeserializer { +pub trait JsonDeserializer { fn deserialize(&self, type_option_data: Vec) -> CollaborateResult; } @@ -47,47 +47,55 @@ impl GridMetaPad { new_field_meta: FieldMeta, start_field_id: Option, ) -> CollaborateResult> { - self.modify_grid(|grid| { + self.modify_grid(|grid_meta| { // Check if the field exists or not - if grid.fields.iter().any(|field_meta| field_meta.id == new_field_meta.id) { + if grid_meta + .fields + .iter() + .any(|field_meta| field_meta.id == new_field_meta.id) + { tracing::error!("Duplicate grid field"); return Ok(None); } let insert_index = match start_field_id { None => None, - Some(start_field_id) => grid.fields.iter().position(|field| field.id == start_field_id), + Some(start_field_id) => grid_meta.fields.iter().position(|field| field.id == start_field_id), }; match insert_index { - None => grid.fields.push(new_field_meta), - Some(index) => grid.fields.insert(index, new_field_meta), + None => grid_meta.fields.push(new_field_meta), + Some(index) => grid_meta.fields.insert(index, new_field_meta), } Ok(Some(())) }) } 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) => { - grid.fields.remove(index); - Ok(Some(())) - } - }) + self.modify_grid( + |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) { + None => Ok(None), + Some(index) => { + grid_meta.fields.remove(index); + Ok(Some(())) + } + }, + ) } pub fn duplicate_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) => { - let mut duplicate_field_meta = grid.fields[index].clone(); - duplicate_field_meta.id = uuid(); - duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name); - grid.fields.insert(index + 1, duplicate_field_meta); - Ok(Some(())) - } - }) + self.modify_grid( + |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) { + None => Ok(None), + Some(index) => { + let mut duplicate_field_meta = grid_meta.fields[index].clone(); + duplicate_field_meta.id = uuid(); + duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name); + grid_meta.fields.insert(index + 1, duplicate_field_meta); + Ok(Some(())) + } + }, + ) } pub fn switch_to_field( @@ -99,9 +107,9 @@ impl GridMetaPad { where B: FnOnce(&FieldType) -> String, { - self.modify_grid(|grid| { + self.modify_grid(|grid_meta| { // - match grid.fields.iter_mut().find(|field_meta| field_meta.id == field_id) { + match grid_meta.fields.iter_mut().find(|field_meta| field_meta.id == field_id) { None => { tracing::warn!("Can not find the field with id: {}", field_id); Ok(None) @@ -119,7 +127,7 @@ impl GridMetaPad { }) } - pub fn update_field( + pub fn update_field( &mut self, changeset: FieldChangesetParams, deserializer: T, @@ -178,6 +186,19 @@ impl GridMetaPad { self.grid_meta.fields.iter().find(|field| field.id == field_id) } + pub fn replace_field(&mut self, field_meta: FieldMeta) -> CollaborateResult> { + self.modify_grid( + |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_meta.id) { + None => Ok(None), + Some(index) => { + grid_meta.fields.remove(index); + grid_meta.fields.insert(index, field_meta); + Ok(Some(())) + } + }, + ) + } + pub fn contain_field(&self, field_id: &str) -> bool { self.grid_meta.fields.iter().any(|field| field.id == field_id) } @@ -213,13 +234,13 @@ impl GridMetaPad { } pub fn create_block_meta(&mut self, block: GridBlockMeta) -> CollaborateResult> { - self.modify_grid(|grid| { - if grid.block_metas.iter().any(|b| b.block_id == block.block_id) { + self.modify_grid(|grid_meta| { + if grid_meta.block_metas.iter().any(|b| b.block_id == block.block_id) { tracing::warn!("Duplicate grid block"); Ok(None) } else { - match grid.block_metas.last() { - None => grid.block_metas.push(block), + match grid_meta.block_metas.last() { + None => grid_meta.block_metas.push(block), Some(last_block) => { if last_block.start_row_index > block.start_row_index && last_block.len() > block.start_row_index @@ -227,7 +248,7 @@ impl GridMetaPad { let msg = "GridBlock's start_row_index should be greater than the last_block's start_row_index and its len".to_string(); return Err(CollaborateError::internal().context(msg)) } - grid.block_metas.push(block); + grid_meta.block_metas.push(block); } } Ok(Some(())) @@ -299,28 +320,34 @@ impl GridMetaPad { where F: FnOnce(&mut GridBlockMeta) -> CollaborateResult>, { - self.modify_grid( - |grid| match grid.block_metas.iter().position(|block| block.block_id == block_id) { + self.modify_grid(|grid_meta| { + match grid_meta + .block_metas + .iter() + .position(|block| block.block_id == block_id) + { None => { tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id); Ok(None) } - Some(index) => f(&mut grid.block_metas[index]), - }, - ) + Some(index) => f(&mut grid_meta.block_metas[index]), + } + }) } pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut FieldMeta) -> CollaborateResult>, { - self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) { - None => { - tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id); - Ok(None) - } - Some(index) => f(&mut grid.fields[index]), - }) + self.modify_grid( + |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) { + None => { + tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id); + Ok(None) + } + Some(index) => f(&mut grid_meta.fields[index]), + }, + ) } } From a3770a699ccb56329cbaba2618bddeb9c0aff806 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 15:34:00 +0800 Subject: [PATCH 43/47] fix: unit test errors --- .../lib/user/presentation/splash_screen.dart | 2 +- .../application/home/home_listen_bloc.dart | 2 +- .../cell/selection_cell/selection_cell.dart | 19 +- .../flowy-folder-data-model/errors.pb.dart | 11 - .../errors.pbenum.dart | 56 - .../errors.pbjson.dart | 36 - .../errors.pbserver.dart | 9 - .../flowy-grid-data-model/protobuf.dart | 2 +- frontend/rust-lib/flowy-grid/src/macros.rs | 2 +- frontend/rust-lib/flowy-grid/src/manager.rs | 10 + .../src/services/block_meta_editor.rs | 255 +---- .../src/services/block_meta_manager.rs | 248 +++++ .../type_options/checkbox_type_option.rs | 30 +- .../field/type_options/date_type_option.rs | 4 +- .../field/type_options/number_type_option.rs | 2 +- .../type_options/selection_type_option.rs | 109 +- .../field/type_options/text_type_option.rs | 22 +- .../flowy-grid/src/services/grid_editor.rs | 6 +- .../rust-lib/flowy-grid/src/services/mod.rs | 1 + .../src/services/row/row_builder.rs | 17 + .../src/services/row/row_entities.rs | 2 +- frontend/rust-lib/flowy-grid/src/util.rs | 13 +- .../flowy-grid/tests/grid/grid_test.rs | 87 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 19 +- .../src/entities/grid.rs | 3 +- .../src/entities/meta.rs | 2 +- .../src/protobuf/model/mod.rs | 3 - .../src/protobuf/model/type_option.rs | 978 ------------------ .../src/protobuf/proto/type_option.proto | 29 - 29 files changed, 468 insertions(+), 1511 deletions(-) delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbserver.dart create mode 100644 frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs delete mode 100644 shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs delete mode 100644 shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto diff --git a/frontend/app_flowy/lib/user/presentation/splash_screen.dart b/frontend/app_flowy/lib/user/presentation/splash_screen.dart index 5fe302abd0..dd8fdcd180 100644 --- a/frontend/app_flowy/lib/user/presentation/splash_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/splash_screen.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/user/domain/auth_state.dart'; import 'package:app_flowy/user/presentation/router.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart index f3da1af678..0ebb572e17 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/user/application/user_listener.dart'; -import 'package:flowy_sdk/protobuf/flowy-folder-data-model/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 2187325c95..3e6f5b1649 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -72,13 +72,28 @@ class _MultiSelectCellState extends State { @override void initState() { - _cellBloc = getIt(param1: widget.cellData); + _cellBloc = getIt(param1: widget.cellData)..add(const SelectionCellEvent.initial()); super.initState(); } @override Widget build(BuildContext context) { - return Container(); + return BlocProvider.value( + value: _cellBloc, + child: BlocBuilder( + builder: (context, state) { + final children = state.selectedOptions.map((option) => SelectOptionTag(option: option)).toList(); + return SizedBox.expand( + child: InkWell( + onTap: () { + SelectOptionEditor.show(context, state.cellData, state.options, state.selectedOptions); + }, + child: Row(children: children), + ), + ); + }, + ), + ); } @override diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pb.dart deleted file mode 100644 index f2ec97799a..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pb.dart +++ /dev/null @@ -1,11 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.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 'errors.pbenum.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbenum.dart deleted file mode 100644 index 52eb16349e..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbenum.dart +++ /dev/null @@ -1,56 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.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 ErrorCode extends $pb.ProtobufEnum { - static const ErrorCode WorkspaceNameInvalid = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid'); - static const ErrorCode WorkspaceIdInvalid = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid'); - static const ErrorCode AppColorStyleInvalid = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid'); - static const ErrorCode WorkspaceDescTooLong = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDescTooLong'); - static const ErrorCode WorkspaceNameTooLong = ErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameTooLong'); - static const ErrorCode AppIdInvalid = ErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid'); - static const ErrorCode AppNameInvalid = ErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid'); - static const ErrorCode ViewNameInvalid = ErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid'); - static const ErrorCode ViewThumbnailInvalid = ErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailInvalid'); - static const ErrorCode ViewIdInvalid = ErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid'); - static const ErrorCode ViewDescTooLong = ErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescTooLong'); - static const ErrorCode ViewDataInvalid = ErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDataInvalid'); - static const ErrorCode ViewNameTooLong = ErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameTooLong'); - static const ErrorCode UserUnauthorized = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); - static const ErrorCode WsConnectError = ErrorCode._(200, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WsConnectError'); - static const ErrorCode InternalError = ErrorCode._(1000, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError'); - static const ErrorCode RecordNotFound = ErrorCode._(1001, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RecordNotFound'); - - static const $core.List values = [ - WorkspaceNameInvalid, - WorkspaceIdInvalid, - AppColorStyleInvalid, - WorkspaceDescTooLong, - WorkspaceNameTooLong, - AppIdInvalid, - AppNameInvalid, - ViewNameInvalid, - ViewThumbnailInvalid, - ViewIdInvalid, - ViewDescTooLong, - ViewDataInvalid, - ViewNameTooLong, - UserUnauthorized, - WsConnectError, - InternalError, - RecordNotFound, - ]; - - static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); - static ErrorCode? valueOf($core.int value) => _byValue[value]; - - const ErrorCode._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbjson.dart deleted file mode 100644 index a829c0ed5d..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbjson.dart +++ /dev/null @@ -1,36 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.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 errorCodeDescriptor instead') -const ErrorCode$json = const { - '1': 'ErrorCode', - '2': const [ - const {'1': 'WorkspaceNameInvalid', '2': 0}, - const {'1': 'WorkspaceIdInvalid', '2': 1}, - const {'1': 'AppColorStyleInvalid', '2': 2}, - const {'1': 'WorkspaceDescTooLong', '2': 3}, - const {'1': 'WorkspaceNameTooLong', '2': 4}, - const {'1': 'AppIdInvalid', '2': 10}, - const {'1': 'AppNameInvalid', '2': 11}, - const {'1': 'ViewNameInvalid', '2': 20}, - const {'1': 'ViewThumbnailInvalid', '2': 21}, - const {'1': 'ViewIdInvalid', '2': 22}, - const {'1': 'ViewDescTooLong', '2': 23}, - const {'1': 'ViewDataInvalid', '2': 24}, - const {'1': 'ViewNameTooLong', '2': 25}, - const {'1': 'UserUnauthorized', '2': 100}, - const {'1': 'WsConnectError', '2': 200}, - const {'1': 'InternalError', '2': 1000}, - const {'1': 'RecordNotFound', '2': 1001}, - ], -}; - -/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQABIWChJXb3Jrc3BhY2VJZEludmFsaWQQARIYChRBcHBDb2xvclN0eWxlSW52YWxpZBACEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEAMSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQBBIQCgxBcHBJZEludmFsaWQQChISCg5BcHBOYW1lSW52YWxpZBALEhMKD1ZpZXdOYW1lSW52YWxpZBAUEhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEBUSEQoNVmlld0lkSW52YWxpZBAWEhMKD1ZpZXdEZXNjVG9vTG9uZxAXEhMKD1ZpZXdEYXRhSW52YWxpZBAYEhMKD1ZpZXdOYW1lVG9vTG9uZxAZEhQKEFVzZXJVbmF1dGhvcml6ZWQQZBITCg5Xc0Nvbm5lY3RFcnJvchDIARISCg1JbnRlcm5hbEVycm9yEOgHEhMKDlJlY29yZE5vdEZvdW5kEOkH'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbserver.dart deleted file mode 100644 index 18b02b9216..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/errors.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.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 'errors.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart index 6cedb363ef..2c253e0494 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/protobuf.dart @@ -1,3 +1,3 @@ -// Auto-generated, do not edit +// Auto-generated, do not edit export './grid.pb.dart'; export './meta.pb.dart'; diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index 4a4994729c..e635e63790 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -52,7 +52,7 @@ macro_rules! impl_type_option { match serde_json::to_string(&self) { Ok(s) => s, Err(e) => { - tracing::error!("Field type data convert to AnyData fail, error: {:?}", e); + tracing::error!("Field type data serialize to json fail, error: {:?}", e); serde_json::to_string(&$target::default()).unwrap() } } diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index d82b2950da..d35ad334c9 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -23,6 +23,7 @@ pub struct GridManager { editor_map: Arc, grid_user: Arc, block_index_persistence: Arc, + #[allow(dead_code)] kv_persistence: Arc, } @@ -181,12 +182,21 @@ pub async fn make_grid_view_data( block_metas: vec![build_context.block_metas], }; + // Create grid let grid_meta_delta = make_grid_delta(&grid_meta); let grid_delta_data = grid_meta_delta.to_delta_bytes(); let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, view_id, grid_delta_data.clone()).into(); let _ = grid_manager.create_grid(view_id, repeated_revision).await?; + // Indexing the block's rows + build_context.block_meta_data.row_metas.iter().for_each(|row| { + let _ = grid_manager + .block_index_persistence + .insert_or_update(&row.block_id, &row.id); + }); + + // Create grid's block let grid_block_meta_delta = make_block_meta_delta(&build_context.block_meta_data); let block_meta_delta_data = grid_block_meta_delta.to_delta_bytes(); let repeated_revision: RepeatedRevision = 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 75357a520b..8518a70fb0 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,263 +1,16 @@ -use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::manager::GridUser; -use crate::services::persistence::block_index::BlockIndexPersistence; -use crate::services::row::{make_block_row_ids, make_cell_by_field_id, make_rows_from_row_metas, GridBlockSnapshot}; use bytes::Bytes; -use dashmap::DashMap; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{ - CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, - GridBlockOrder, RepeatedCell, Row, RowMeta, RowMetaChangeset, RowOrder, -}; -use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; -use flowy_revision::{ - RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence, -}; +use flowy_grid_data_model::entities::{CellMeta, RowMeta, RowMetaChangeset, RowOrder}; +use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridBlockMetaChange, GridBlockMetaPad}; use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_delta_from_revisions; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; -use std::collections::HashMap; + use std::sync::Arc; use tokio::sync::RwLock; -pub(crate) struct GridBlockMetaEditorManager { - grid_id: String, - user: Arc, - editor_map: DashMap>, - persistence: Arc, -} - -impl GridBlockMetaEditorManager { - pub(crate) async fn new( - grid_id: &str, - user: &Arc, - blocks: Vec, - persistence: Arc, - ) -> FlowyResult { - let editor_map = make_block_meta_editor_map(user, blocks).await?; - let user = user.clone(); - let grid_id = grid_id.to_owned(); - let manager = Self { - grid_id, - user, - editor_map, - persistence, - }; - Ok(manager) - } - - // #[tracing::instrument(level = "trace", skip(self))] - pub(crate) async fn get_editor(&self, block_id: &str) -> FlowyResult> { - debug_assert!(!block_id.is_empty()); - match self.editor_map.get(block_id) { - None => { - tracing::error!("The is a fatal error, block is not exist"); - let editor = Arc::new(make_block_meta_editor(&self.user, block_id).await?); - self.editor_map.insert(block_id.to_owned(), editor.clone()); - Ok(editor) - } - Some(editor) => Ok(editor.clone()), - } - } - - async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { - let block_id = self.persistence.get_block_id(row_id)?; - Ok(self.get_editor(&block_id).await?) - } - - pub(crate) async fn create_row( - &self, - block_id: &str, - row_meta: RowMeta, - start_row_id: Option, - ) -> FlowyResult { - let _ = self.persistence.insert_or_update(&row_meta.block_id, &row_meta.id)?; - let editor = self.get_editor(&row_meta.block_id).await?; - let row_count = editor.create_row(row_meta, start_row_id).await?; - self.notify_block_did_update_row(block_id).await?; - Ok(row_count) - } - - pub(crate) async fn insert_row( - &self, - rows_by_block_id: HashMap>, - ) -> FlowyResult> { - let mut changesets = vec![]; - 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 &row_metas { - let _ = self.persistence.insert_or_update(&row.block_id, &row.id)?; - row_count = editor.create_row(row.clone(), None).await?; - } - changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); - let _ = self.notify_block_did_update_row(&block_id).await?; - } - - Ok(changesets) - } - - pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { - let mut changesets = vec![]; - for block_row_ids in make_block_row_ids(&row_orders) { - let editor = self.get_editor(&block_row_ids.block_id).await?; - let row_count = editor.delete_rows(block_row_ids.row_ids).await?; - - let changeset = GridBlockMetaChangeset::from_row_count(&block_row_ids.block_id, row_count); - changesets.push(changeset); - } - - Ok(changesets) - } - - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { - let editor = self.get_editor_from_row_id(&changeset.row_id).await?; - let _ = editor.update_row(changeset.clone()).await?; - let _ = self.notify_block_did_update_row(&editor.block_id).await?; - Ok(()) - } - - pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { - let row_id = changeset.row_id.clone(); - let editor = self.get_editor_from_row_id(&row_id).await?; - let row_changeset: RowMetaChangeset = changeset.clone().into(); - let _ = editor.update_row(row_changeset).await?; - - let cell_notification_data = CellNotificationData { - grid_id: changeset.grid_id, - field_id: changeset.field_id, - row_id: changeset.row_id, - content: changeset.data, - }; - self.notify_did_update_cell(cell_notification_data).await?; - Ok(()) - } - - pub async fn get_row_meta(&self, row_id: &str) -> FlowyResult>> { - let editor = self.get_editor_from_row_id(row_id).await?; - let row_ids = vec![row_id.to_owned()]; - let mut row_metas = editor.get_row_metas(Some(row_ids)).await?; - if row_metas.is_empty() { - Ok(None) - } else { - Ok(row_metas.pop()) - } - } - - pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { - let mut snapshots = vec![]; - for block_id in block_ids { - let editor = self.get_editor(&block_id).await?; - let row_metas = editor.get_row_metas(None).await?; - - row_metas.iter().for_each(|row| { - let _ = self.persistence.insert_or_update(&row.block_id, &row.id); - }); - - snapshots.push(GridBlockSnapshot { block_id, row_metas }); - } - Ok(snapshots) - } - - // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage. - #[allow(dead_code)] - pub async fn get_cell_metas( - &self, - block_ids: Vec, - field_id: &str, - row_ids: Option>, - ) -> FlowyResult> { - let mut block_cell_metas = vec![]; - for block_id in block_ids { - let editor = self.get_editor(&block_id).await?; - let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?; - block_cell_metas.extend(cell_metas); - } - Ok(block_cell_metas) - } - - async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { - let block_order: GridBlockOrder = block_id.into(); - send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) - .payload(block_order) - .send(); - Ok(()) - } - - async fn notify_did_update_cell(&self, data: CellNotificationData) -> FlowyResult<()> { - let id = format!("{}:{}", data.row_id, data.field_id); - send_dart_notification(&id, GridNotification::DidUpdateCell) - .payload(data) - .send(); - Ok(()) - } - - async fn notify_did_update_row(&self, row_id: &str, field_metas: &[FieldMeta]) -> FlowyResult<()> { - match self.get_row_meta(row_id).await? { - None => {} - Some(row_meta) => { - let row_metas = vec![row_meta]; - if let Some(row) = make_rows_from_row_metas(&field_metas, &row_metas).pop() { - send_dart_notification(row_id, GridNotification::DidUpdateRow) - .payload(row) - .send(); - } - } - } - Ok(()) - - // - // 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_by_field_id(&field_meta_map, field_id, cell_meta) { - // None => {} - // Some((_, cell)) => cells.push(cell), - // }, - // ); - // - // if !cells.is_empty() { - // send_dart_notification(&changeset.row_id, GridNotification::DidUpdateRow) - // .payload(RepeatedCell::from(cells)) - // .send(); - // } - // Ok(()) - } -} - -async fn make_block_meta_editor_map( - user: &Arc, - blocks: Vec, -) -> FlowyResult>> { - let editor_map = DashMap::new(); - for block in blocks { - let editor = make_block_meta_editor(user, &block.block_id).await?; - editor_map.insert(block.block_id, Arc::new(editor)); - } - - Ok(editor_map) -} - -async fn make_block_meta_editor(user: &Arc, block_id: &str) -> FlowyResult { - let token = user.token()?; - let user_id = user.user_id()?; - let pool = user.db_pool()?; - - let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool)); - let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, block_id, disk_cache)); - let rev_manager = RevisionManager::new(&user_id, block_id, rev_persistence); - ClientGridBlockMetaEditor::new(&user_id, &token, block_id, rev_manager).await -} - pub struct ClientGridBlockMetaEditor { user_id: String, pub block_id: String, @@ -288,7 +41,7 @@ impl ClientGridBlockMetaEditor { }) } - async fn create_row(&self, row: RowMeta, start_row_id: Option) -> FlowyResult { + pub(crate) async fn create_row(&self, row: RowMeta, start_row_id: Option) -> FlowyResult { let mut row_count = 0; let _ = self .modify(|pad| { diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs new file mode 100644 index 0000000000..104b6fbbdb --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -0,0 +1,248 @@ +use crate::dart_notification::{send_dart_notification, GridNotification}; +use crate::manager::GridUser; +use crate::services::block_meta_editor::ClientGridBlockMetaEditor; +use crate::services::persistence::block_index::BlockIndexPersistence; +use crate::services::row::{make_block_row_ids, make_rows_from_row_metas, GridBlockSnapshot}; + +use dashmap::DashMap; +use flowy_error::FlowyResult; +use flowy_grid_data_model::entities::{ + CellMeta, CellMetaChangeset, CellNotificationData, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, + GridBlockOrder, RowMeta, RowMetaChangeset, RowOrder, +}; +use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence; +use flowy_revision::{RevisionManager, RevisionPersistence}; +use std::collections::HashMap; +use std::sync::Arc; + +pub(crate) struct GridBlockMetaEditorManager { + grid_id: String, + user: Arc, + editor_map: DashMap>, + persistence: Arc, +} + +impl GridBlockMetaEditorManager { + pub(crate) async fn new( + grid_id: &str, + user: &Arc, + blocks: Vec, + persistence: Arc, + ) -> FlowyResult { + let editor_map = make_block_meta_editor_map(user, blocks).await?; + let user = user.clone(); + let grid_id = grid_id.to_owned(); + let manager = Self { + grid_id, + user, + editor_map, + persistence, + }; + Ok(manager) + } + + // #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn get_editor(&self, block_id: &str) -> FlowyResult> { + debug_assert!(!block_id.is_empty()); + match self.editor_map.get(block_id) { + None => { + tracing::error!("The is a fatal error, block is not exist"); + let editor = Arc::new(make_block_meta_editor(&self.user, block_id).await?); + self.editor_map.insert(block_id.to_owned(), editor.clone()); + Ok(editor) + } + Some(editor) => Ok(editor.clone()), + } + } + + async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { + let block_id = self.persistence.get_block_id(row_id)?; + Ok(self.get_editor(&block_id).await?) + } + + pub(crate) async fn create_row( + &self, + block_id: &str, + row_meta: RowMeta, + start_row_id: Option, + ) -> FlowyResult { + let _ = self.persistence.insert_or_update(&row_meta.block_id, &row_meta.id)?; + let editor = self.get_editor(&row_meta.block_id).await?; + let row_count = editor.create_row(row_meta, start_row_id).await?; + self.notify_block_did_update_row(block_id).await?; + Ok(row_count) + } + + pub(crate) async fn insert_row( + &self, + rows_by_block_id: HashMap>, + ) -> FlowyResult> { + let mut changesets = vec![]; + 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 &row_metas { + let _ = self.persistence.insert_or_update(&row.block_id, &row.id)?; + row_count = editor.create_row(row.clone(), None).await?; + } + changesets.push(GridBlockMetaChangeset::from_row_count(&block_id, row_count)); + let _ = self.notify_block_did_update_row(&block_id).await?; + } + + Ok(changesets) + } + + pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { + let mut changesets = vec![]; + for block_row_ids in make_block_row_ids(&row_orders) { + let editor = self.get_editor(&block_row_ids.block_id).await?; + let row_count = editor.delete_rows(block_row_ids.row_ids).await?; + + let changeset = GridBlockMetaChangeset::from_row_count(&block_row_ids.block_id, row_count); + changesets.push(changeset); + } + + Ok(changesets) + } + + pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { + let editor = self.get_editor_from_row_id(&changeset.row_id).await?; + let _ = editor.update_row(changeset.clone()).await?; + let _ = self.notify_block_did_update_row(&editor.block_id).await?; + Ok(()) + } + + pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { + let row_id = changeset.row_id.clone(); + let editor = self.get_editor_from_row_id(&row_id).await?; + let row_changeset: RowMetaChangeset = changeset.clone().into(); + let _ = editor.update_row(row_changeset).await?; + + let cell_notification_data = CellNotificationData { + grid_id: changeset.grid_id, + field_id: changeset.field_id, + row_id: changeset.row_id, + content: changeset.data, + }; + self.notify_did_update_cell(cell_notification_data).await?; + Ok(()) + } + + pub async fn get_row_meta(&self, row_id: &str) -> FlowyResult>> { + let editor = self.get_editor_from_row_id(row_id).await?; + let row_ids = vec![row_id.to_owned()]; + let mut row_metas = editor.get_row_metas(Some(row_ids)).await?; + if row_metas.is_empty() { + Ok(None) + } else { + Ok(row_metas.pop()) + } + } + + pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { + let mut snapshots = vec![]; + for block_id in block_ids { + let editor = self.get_editor(&block_id).await?; + let row_metas = editor.get_row_metas(None).await?; + snapshots.push(GridBlockSnapshot { block_id, row_metas }); + } + Ok(snapshots) + } + + // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage. + #[allow(dead_code)] + pub async fn get_cell_metas( + &self, + block_ids: Vec, + field_id: &str, + row_ids: Option>, + ) -> FlowyResult> { + let mut block_cell_metas = vec![]; + for block_id in block_ids { + let editor = self.get_editor(&block_id).await?; + let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?; + block_cell_metas.extend(cell_metas); + } + Ok(block_cell_metas) + } + + async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { + let block_order: GridBlockOrder = block_id.into(); + send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) + .payload(block_order) + .send(); + Ok(()) + } + + async fn notify_did_update_cell(&self, data: CellNotificationData) -> FlowyResult<()> { + let id = format!("{}:{}", data.row_id, data.field_id); + send_dart_notification(&id, GridNotification::DidUpdateCell) + .payload(data) + .send(); + Ok(()) + } + + #[allow(dead_code)] + async fn notify_did_update_row(&self, row_id: &str, field_metas: &[FieldMeta]) -> FlowyResult<()> { + match self.get_row_meta(row_id).await? { + None => {} + Some(row_meta) => { + let row_metas = vec![row_meta]; + if let Some(row) = make_rows_from_row_metas(field_metas, &row_metas).pop() { + send_dart_notification(row_id, GridNotification::DidUpdateRow) + .payload(row) + .send(); + } + } + } + Ok(()) + + // + // 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_by_field_id(&field_meta_map, field_id, cell_meta) { + // None => {} + // Some((_, cell)) => cells.push(cell), + // }, + // ); + // + // if !cells.is_empty() { + // send_dart_notification(&changeset.row_id, GridNotification::DidUpdateRow) + // .payload(RepeatedCell::from(cells)) + // .send(); + // } + // Ok(()) + } +} + +async fn make_block_meta_editor_map( + user: &Arc, + blocks: Vec, +) -> FlowyResult>> { + let editor_map = DashMap::new(); + for block in blocks { + let editor = make_block_meta_editor(user, &block.block_id).await?; + editor_map.insert(block.block_id, Arc::new(editor)); + } + + Ok(editor_map) +} + +async fn make_block_meta_editor(user: &Arc, block_id: &str) -> FlowyResult { + let token = user.token()?; + let user_id = user.user_id()?; + let pool = user.db_pool()?; + + let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool)); + let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, block_id, disk_cache)); + let rev_manager = RevisionManager::new(&user_id, block_id, rev_persistence); + ClientGridBlockMetaEditor::new(&user_id, &token, block_id, rev_manager).await +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index 2afdadb2f4..b3e1eb37f9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -43,7 +43,7 @@ const NO: &str = "No"; impl CellDataOperation for CheckboxTypeOption { fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> String { if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { - if !type_option_cell_data.is_text() || !type_option_cell_data.is_checkbox() { + if !type_option_cell_data.is_checkbox() { return String::new(); } let cell_data = type_option_cell_data.data; @@ -58,7 +58,7 @@ impl CellDataOperation for CheckboxTypeOption { fn apply_changeset>( &self, changeset: T, - cell_meta: Option, + _cell_meta: Option, ) -> Result { let changeset = changeset.into(); let s = match string_to_bool(&changeset) { @@ -84,6 +84,7 @@ fn string_to_bool(bool_str: &str) -> bool { #[cfg(test)] mod tests { + use crate::services::field::type_options::checkbox_type_option::{NO, YES}; use crate::services::field::CheckboxTypeOption; use crate::services::field::FieldBuilder; use crate::services::row::CellDataOperation; @@ -94,17 +95,22 @@ mod tests { let type_option = CheckboxTypeOption::default(); let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); - assert_eq!(type_option.apply_changeset("true").unwrap(), "1".to_owned()); - assert_eq!(type_option.apply_changeset("1").unwrap(), "1".to_owned()); - assert_eq!(type_option.apply_changeset("yes").unwrap(), "1".to_owned()); + let data = type_option.apply_changeset("true", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), YES); - assert_eq!(type_option.apply_changeset("false").unwrap(), "0".to_owned()); - assert_eq!(type_option.apply_changeset("no").unwrap(), "0".to_owned()); - assert_eq!(type_option.apply_changeset("123").unwrap(), "0".to_owned()); + let data = type_option.apply_changeset("1", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), YES); - assert_eq!( - type_option.decode_cell_data("1".to_owned(), &field_meta), - "1".to_owned() - ); + let data = type_option.apply_changeset("yes", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), YES); + + let data = type_option.apply_changeset("false", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), NO); + + let data = type_option.apply_changeset("no", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), NO); + + let data = type_option.apply_changeset("123", None).unwrap(); + assert_eq!(type_option.decode_cell_data(data, &field_meta), NO); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index 6472b91bb7..b89431add8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -66,7 +66,7 @@ impl CellDataOperation for DateTypeOption { fn apply_changeset>( &self, changeset: T, - cell_meta: Option, + _cell_meta: Option, ) -> Result { let changeset = changeset.into(); if let Err(e) = changeset.parse::() { @@ -282,7 +282,7 @@ mod tests { #[should_panic] fn date_description_invalid_data_test() { let type_option = DateTypeOption::default(); - type_option.apply_changeset("he").unwrap(); + type_option.apply_changeset("he", None).unwrap(); } fn data(s: &str) -> String { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index b0b5967a9d..7b03adfc74 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -104,7 +104,7 @@ impl CellDataOperation for NumberTypeOption { fn apply_changeset>( &self, changeset: T, - cell_meta: Option, + _cell_meta: Option, ) -> Result { let changeset = changeset.into(); let data = self.strip_symbol(changeset); diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 5dee72dec7..ad95fe6a54 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -5,15 +5,13 @@ use crate::services::row::{CellDataChangeset, CellDataOperation, TypeOptionCellD use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_error::{ErrorCode, FlowyError, FlowyResult}; +use flowy_error::{ErrorCode, FlowyError}; use flowy_grid_data_model::entities::{ CellMeta, CellMetaChangeset, FieldMeta, FieldType, TypeOptionDataEntity, TypeOptionDataEntry, }; -use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use flowy_grid_data_model::parser::NotEmptyUuid; use serde::{Deserialize, Serialize}; use std::str::FromStr; -use uuid::Uuid; pub const SELECTION_IDS_SEPARATOR: &str = ","; @@ -66,9 +64,9 @@ impl CellDataOperation for SingleSelectTypeOption { return String::new(); } - match select_option_ids(type_option_cell_data.data).pop() { + match select_option_ids(type_option_cell_data.data).first() { None => String::new(), - Some(option_id) => match self.options.iter().find(|option| option.id == option_id) { + Some(option_id) => match self.options.iter().find(|option| &option.id == option_id) { None => String::new(), Some(option) => option.name.clone(), }, @@ -92,7 +90,7 @@ impl CellDataOperation for SingleSelectTypeOption { new_cell_data = "".to_string() } - return Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()); + Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()) } } @@ -416,7 +414,7 @@ impl std::default::Default for SelectOptionColor { } } -fn make_select_context_from(cell_meta: &Option, options: &Vec) -> Vec { +fn make_select_context_from(cell_meta: &Option, options: &[SelectOption]) -> Vec { match cell_meta { None => vec![], Some(cell_meta) => { @@ -434,16 +432,97 @@ fn make_select_context_from(cell_meta: &Option, options: &Vec>( &self, changeset: T, - cell_meta: Option, + _cell_meta: Option, ) -> Result { let data = changeset.into(); if data.len() > 10000 { @@ -85,29 +85,25 @@ mod tests { let done_option_id = done_option.id.clone(); let single_select = SingleSelectTypeOptionBuilder::default().option(done_option); let single_select_field_meta = FieldBuilder::new(single_select).build(); - let data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); + let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); assert_eq!( - type_option.decode_cell_data(data, &single_select_field_meta), + type_option.decode_cell_data(cell_data, &single_select_field_meta), "Done".to_owned() ); // Multiple select let google_option = SelectOption::new("Google"); - let google_option_id = google_option.id.clone(); let facebook_option = SelectOption::new("Facebook"); - let face_option_id = facebook_option.id.clone(); + let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); + let cell_data_changeset = SelectOptionCellChangeset::from_insert(&ids).cell_data(); let multi_select = MultiSelectTypeOptionBuilder::default() .option(google_option) - .option(facebook_option) - .option(SelectOption::new("Twitter")); + .option(facebook_option); let multi_select_field_meta = FieldBuilder::new(multi_select).build(); - let data = TypeOptionCellData::new( - &vec![google_option_id, face_option_id].join(SELECTION_IDS_SEPARATOR), - FieldType::SingleSelect, - ) - .json(); + let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta); + let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap(); assert_eq!( - type_option.decode_cell_data(data, &multi_select_field_meta), + type_option.decode_cell_data(cell_data, &multi_select_field_meta), "Google,Facebook".to_owned() ); 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 32dfb43668..cddafd3fdd 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,6 +1,6 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; -use crate::services::block_meta_editor::GridBlockMetaEditorManager; +use crate::services::block_meta_manager::GridBlockMetaEditorManager; use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::persistence::block_index::BlockIndexPersistence; use crate::services::row::*; @@ -154,7 +154,7 @@ impl ClientGridEditor { pub async fn get_field_meta(&self, field_id: &str) -> Option { let field_meta = self.pad.read().await.get_field(field_id)?.clone(); - return Some(field_meta); + Some(field_meta) } pub async fn get_field_metas(&self, field_ids: Option>) -> FlowyResult> @@ -285,7 +285,7 @@ impl ClientGridEditor { match self.pad.read().await.get_field(&changeset.field_id) { None => { let msg = format!("Field not found with id: {}", &changeset.field_id); - return Err(FlowyError::internal().context(msg)); + Err(FlowyError::internal().context(msg)) } Some(field_meta) => { // Update the changeset.data property with the return value. diff --git a/frontend/rust-lib/flowy-grid/src/services/mod.rs b/frontend/rust-lib/flowy-grid/src/services/mod.rs index 88e7fbec10..d6ca2d5c45 100644 --- a/frontend/rust-lib/flowy-grid/src/services/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/mod.rs @@ -1,6 +1,7 @@ mod util; pub mod block_meta_editor; +mod block_meta_manager; pub mod cell; pub mod field; pub mod grid_editor; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index 22fc0f14ae..0a0da4df57 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -1,5 +1,6 @@ use crate::services::row::apply_cell_data_changeset; +use crate::services::field::SelectOptionCellChangeset; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{CellMeta, FieldMeta, RowMeta, DEFAULT_ROW_HEIGHT}; use std::collections::HashMap; @@ -44,6 +45,22 @@ impl<'a> CreateRowMetaBuilder<'a> { } } + pub fn add_select_option_cell(&mut self, field_id: &str, data: String) -> FlowyResult<()> { + match self.field_meta_map.get(&field_id.to_owned()) { + None => { + let msg = format!("Invalid field_id: {}", field_id); + Err(FlowyError::internal().context(msg)) + } + Some(field_meta) => { + let cell_data = SelectOptionCellChangeset::from_insert(&data).cell_data(); + let data = apply_cell_data_changeset(&cell_data, None, field_meta)?; + let cell = CellMeta::new(field_id, data); + self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); + Ok(()) + } + } + } + #[allow(dead_code)] pub fn height(mut self, height: i32) -> Self { self.payload.height = height; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs index e88ed4ffb9..38a081f6e7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs @@ -1,6 +1,6 @@ use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; -use flowy_grid_data_model::parser::{NotEmptyStr, NotEmptyUuid}; +use flowy_grid_data_model::parser::NotEmptyUuid; #[derive(ProtoBuf, Default)] pub struct RowIdentifierPayload { diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 9cc8e078e0..9af437a40f 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -8,16 +8,27 @@ pub fn make_default_grid() -> BuildGridContext { .visibility(true) .build(); + // single select let single_select = SingleSelectTypeOptionBuilder::default() .option(SelectOption::new("Done")) .option(SelectOption::new("Unknown")) .option(SelectOption::new("Progress")); - let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build(); + //multiple select + let multi_select = MultiSelectTypeOptionBuilder::default() + .option(SelectOption::new("A")) + .option(SelectOption::new("B")) + .option(SelectOption::new("C")); + let multi_select_field = FieldBuilder::new(multi_select) + .name("Alphabet") + .visibility(true) + .build(); + GridBuilder::default() .add_field(text_field) .add_field(single_select_field) + .add_field(multi_select_field) .add_empty_row() .add_empty_row() .add_empty_row() diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 5ac780519b..f031c00743 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -2,7 +2,7 @@ use crate::grid::script::EditorScript::*; use crate::grid::script::*; use chrono::NaiveDateTime; use flowy_grid::services::field::{ - MultiSelectTypeOption, SelectOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, + MultiSelectTypeOption, SelectOption, SelectOptionCellChangeset, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, }; use flowy_grid::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ @@ -233,37 +233,31 @@ async fn grid_row_add_cells_test() { for field in &test.field_metas { match field.field_type { FieldType::RichText => { - let data = apply_cell_data_changeset("hello world", field).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + builder.add_cell(&field.id, "hello world".to_owned()).unwrap(); } FieldType::Number => { - let data = apply_cell_data_changeset("Â¥18,443", field).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + builder.add_cell(&field.id, "18,443".to_owned()).unwrap(); } FieldType::DateTime => { - let data = apply_cell_data_changeset("1647251762", field).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + builder.add_cell(&field.id, "1647251762".to_owned()).unwrap(); } FieldType::SingleSelect => { let type_option = SingleSelectTypeOption::from(field); - let options = type_option.options.first().unwrap(); - let data = type_option.apply_changeset(&options.id).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + let option = type_option.options.first().unwrap(); + builder.add_select_option_cell(&field.id, option.id.clone()).unwrap(); } FieldType::MultiSelect => { let type_option = MultiSelectTypeOption::from(field); - let options = type_option + let ops_ids = type_option .options .iter() .map(|option| option.id.clone()) .collect::>() .join(SELECTION_IDS_SEPARATOR); - let data = type_option.apply_changeset(&options).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + builder.add_select_option_cell(&field.id, ops_ids).unwrap(); } FieldType::Checkbox => { - let data = apply_cell_data_changeset("false", field).unwrap(); - builder.add_cell(&field.id, data).unwrap(); + builder.add_cell(&field.id, "false".to_string()).unwrap(); } } } @@ -272,61 +266,6 @@ async fn grid_row_add_cells_test() { test.run_scripts(scripts).await; } -#[tokio::test] -async fn grid_row_add_selection_cell_test() { - let mut test = GridEditorTest::new().await; - let mut builder = CreateRowMetaBuilder::new(&test.field_metas); - let uuid = uuid::Uuid::new_v4().to_string(); - let mut single_select_field_id = "".to_string(); - let mut multi_select_field_id = "".to_string(); - for field in &test.field_metas { - match field.field_type { - FieldType::SingleSelect => { - single_select_field_id = field.id.clone(); - // The element must be parsed as uuid - assert!(builder.add_cell(&field.id, "data".to_owned()).is_err()); - // // The data should not be empty - assert!(builder.add_cell(&field.id, "".to_owned()).is_err()); - // The element must be parsed as uuid - assert!(builder.add_cell(&field.id, "1,2,3".to_owned()).is_err(),); - // The separator must be comma - assert!(builder.add_cell(&field.id, format!("{}. {}", &uuid, &uuid),).is_err()); - // - - assert!(builder.add_cell(&field.id, uuid.clone()).is_ok()); - assert!(builder.add_cell(&field.id, format!("{}, {}", &uuid, &uuid)).is_ok()); - } - FieldType::MultiSelect => { - multi_select_field_id = field.id.clone(); - assert!(builder.add_cell(&field.id, format!("{}, {}", &uuid, &uuid)).is_ok()); - } - _ => {} - } - } - let context = builder.build(); - assert_eq!( - &context - .cell_by_field_id - .get(&single_select_field_id) - .as_ref() - .unwrap() - .data, - &uuid - ); - assert_eq!( - context - .cell_by_field_id - .get(&multi_select_field_id) - .as_ref() - .unwrap() - .data, - format!("{},{}", &uuid, &uuid) - ); - - let scripts = vec![CreateRow { context }]; - test.run_scripts(scripts).await; -} - #[tokio::test] async fn grid_row_add_date_cell_test() { let mut test = GridEditorTest::new().await; @@ -375,11 +314,11 @@ async fn grid_cell_update() { FieldType::DateTime => "123".to_string(), FieldType::SingleSelect => { let type_option = SingleSelectTypeOption::from(field_meta); - type_option.options.first().unwrap().id.clone() + SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).cell_data() } FieldType::MultiSelect => { let type_option = MultiSelectTypeOption::from(field_meta); - type_option.options.first().unwrap().id.clone() + SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).cell_data() } FieldType::Checkbox => "1".to_string(), }; @@ -400,8 +339,8 @@ async fn grid_cell_update() { FieldType::RichText => ("1".to_string().repeat(10001), true), FieldType::Number => ("abc".to_string(), true), FieldType::DateTime => ("abc".to_string(), true), - FieldType::SingleSelect => ("abc".to_string(), true), - FieldType::MultiSelect => ("abc".to_string(), true), + FieldType::SingleSelect => (SelectOptionCellChangeset::from_insert("abc").cell_data(), false), + FieldType::MultiSelect => (SelectOptionCellChangeset::from_insert("abc").cell_data(), false), FieldType::Checkbox => ("2".to_string(), false), }; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 858e9826cf..9c3cfd53d7 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -3,8 +3,8 @@ use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangesetParams, FieldMeta, FieldType, - GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, TypeOptionDataEntry, + BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangesetParams, FieldMeta, FieldOrder, + FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, TypeOptionDataEntry, }; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; @@ -89,7 +89,7 @@ impl GridEditorTest { let view_data: Bytes = build_context.try_into().unwrap(); let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await; let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap(); - let field_metas = editor.get_field_metas(None).await.unwrap(); + let field_metas = editor.get_field_metas::(None).await.unwrap(); let grid_blocks = editor.get_block_metas().await.unwrap(); let row_metas = get_row_metas(&editor).await; @@ -125,12 +125,12 @@ impl GridEditorTest { } self.editor.create_field(params).await.unwrap(); - self.field_metas = self.editor.get_field_metas(None).await.unwrap(); + self.field_metas = self.editor.get_field_metas::(None).await.unwrap(); assert_eq!(self.field_count, self.field_metas.len()); } EditorScript::UpdateField { changeset: change } => { self.editor.update_field(change).await.unwrap(); - self.field_metas = self.editor.get_field_metas(None).await.unwrap(); + self.field_metas = self.editor.get_field_metas::(None).await.unwrap(); } EditorScript::DeleteField { field_meta } => { if self.editor.contain_field(&field_meta.id).await { @@ -138,17 +138,20 @@ impl GridEditorTest { } self.editor.delete_field(&field_meta.id).await.unwrap(); - self.field_metas = self.editor.get_field_metas(None).await.unwrap(); + self.field_metas = self.editor.get_field_metas::(None).await.unwrap(); assert_eq!(self.field_count, self.field_metas.len()); } EditorScript::AssertFieldCount(count) => { - assert_eq!(self.editor.get_field_metas(None).await.unwrap().len(), count); + assert_eq!( + self.editor.get_field_metas::(None).await.unwrap().len(), + count + ); } EditorScript::AssertFieldEqual { field_index, field_meta, } => { - let field_metas = self.editor.get_field_metas(None).await.unwrap(); + let field_metas = self.editor.get_field_metas::(None).await.unwrap(); assert_eq!(field_metas[field_index].clone(), field_meta); } EditorScript::CreateBlock { block } => { 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 87a35b822d..d3cb9f7f69 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -1,5 +1,5 @@ use crate::entities::{FieldMeta, FieldType, RowMeta}; -use crate::parser::{NotEmptyStr, NotEmptyUuid}; +use crate::parser::NotEmptyUuid; use flowy_derive::ProtoBuf; use flowy_error_code::ErrorCode; use std::collections::HashMap; @@ -422,6 +422,7 @@ pub struct CreateFieldPayload { pub start_field_id: Option, } +#[derive(Clone)] pub struct CreateFieldParams { pub grid_id: String, pub field: Field, diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index de8ac320f3..cf48a70823 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -396,7 +396,7 @@ impl std::convert::From for RowMetaChangeset { let field_id = changeset.field_id; let cell_meta = CellMeta { field_id: field_id.clone(), - data: changeset.data.unwrap_or("".to_owned()), + data: changeset.data.unwrap_or_else(|| "".to_owned()), }; cell_by_field_id.insert(field_id, cell_meta); diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs index e2e2c75a6e..d011b76000 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/mod.rs @@ -4,8 +4,5 @@ mod grid; pub use grid::*; -mod type_option; -pub use type_option::*; - mod meta; pub use meta::*; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs deleted file mode 100644 index 1cad4b09e8..0000000000 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/type_option.rs +++ /dev/null @@ -1,978 +0,0 @@ -// 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 `type_option.proto` - -/// Generated files are compatible only with the same version -/// of protobuf runtime. -// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2; - -#[derive(PartialEq,Clone,Default)] -pub struct SelectOption { - // message fields - pub id: ::std::string::String, - pub name: ::std::string::String, - pub color: SelectOptionColor, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a SelectOption { - fn default() -> &'a SelectOption { - ::default_instance() - } -} - -impl SelectOption { - pub fn new() -> SelectOption { - ::std::default::Default::default() - } - - // string id = 1; - - - pub fn get_id(&self) -> &str { - &self.id - } - pub fn clear_id(&mut self) { - self.id.clear(); - } - - // Param is passed by value, moved - pub fn set_id(&mut self, v: ::std::string::String) { - self.id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_id(&mut self) -> &mut ::std::string::String { - &mut self.id - } - - // Take field - pub fn take_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.id, ::std::string::String::new()) - } - - // string name = 2; - - - pub fn get_name(&self) -> &str { - &self.name - } - pub fn clear_name(&mut self) { - self.name.clear(); - } - - // Param is passed by value, moved - pub fn set_name(&mut self, v: ::std::string::String) { - self.name = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_name(&mut self) -> &mut ::std::string::String { - &mut self.name - } - - // Take field - pub fn take_name(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.name, ::std::string::String::new()) - } - - // .SelectOptionColor color = 3; - - - pub fn get_color(&self) -> SelectOptionColor { - self.color - } - pub fn clear_color(&mut self) { - self.color = SelectOptionColor::Purple; - } - - // Param is passed by value, moved - pub fn set_color(&mut self, v: SelectOptionColor) { - self.color = v; - } -} - -impl ::protobuf::Message for SelectOption { - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { - while !is.eof()? { - let (field_number, wire_type) = is.read_tag_unpack()?; - match field_number { - 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; - }, - 3 => { - ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.color, 3, &mut self.unknown_fields)? - }, - _ => { - ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u32 { - let mut my_size = 0; - if !self.id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.id); - } - if !self.name.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.name); - } - if self.color != SelectOptionColor::Purple { - my_size += ::protobuf::rt::enum_size(3, self.color); - } - my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); - self.cached_size.set(my_size); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.id.is_empty() { - os.write_string(1, &self.id)?; - } - if !self.name.is_empty() { - os.write_string(2, &self.name)?; - } - if self.color != SelectOptionColor::Purple { - os.write_enum(3, ::protobuf::ProtobufEnum::value(&self.color))?; - } - 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() -> SelectOption { - SelectOption::new() - } - - fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { - static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; - descriptor.get(|| { - let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "id", - |m: &SelectOption| { &m.id }, - |m: &mut SelectOption| { &mut m.id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "name", - |m: &SelectOption| { &m.name }, - |m: &mut SelectOption| { &mut m.name }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( - "color", - |m: &SelectOption| { &m.color }, - |m: &mut SelectOption| { &mut m.color }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "SelectOption", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static SelectOption { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(SelectOption::new) - } -} - -impl ::protobuf::Clear for SelectOption { - fn clear(&mut self) { - self.id.clear(); - self.name.clear(); - self.color = SelectOptionColor::Purple; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for SelectOption { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for SelectOption { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct SelectOptionCellChangesetPayload { - // message fields - pub grid_id: ::std::string::String, - pub row_id: ::std::string::String, - pub field_id: ::std::string::String, - // message oneof groups - pub one_of_insert_option_id: ::std::option::Option, - pub one_of_delete_option_id: ::std::option::Option, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a SelectOptionCellChangesetPayload { - fn default() -> &'a SelectOptionCellChangesetPayload { - ::default_instance() - } -} - -#[derive(Clone,PartialEq,Debug)] -pub enum SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id { - insert_option_id(::std::string::String), -} - -#[derive(Clone,PartialEq,Debug)] -pub enum SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id { - delete_option_id(::std::string::String), -} - -impl SelectOptionCellChangesetPayload { - pub fn new() -> SelectOptionCellChangesetPayload { - ::std::default::Default::default() - } - - // string grid_id = 1; - - - pub fn get_grid_id(&self) -> &str { - &self.grid_id - } - pub fn clear_grid_id(&mut self) { - self.grid_id.clear(); - } - - // Param is passed by value, moved - pub fn set_grid_id(&mut self, v: ::std::string::String) { - self.grid_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_grid_id(&mut self) -> &mut ::std::string::String { - &mut self.grid_id - } - - // Take field - pub fn take_grid_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) - } - - // string row_id = 2; - - - pub fn get_row_id(&self) -> &str { - &self.row_id - } - pub fn clear_row_id(&mut self) { - self.row_id.clear(); - } - - // Param is passed by value, moved - pub fn set_row_id(&mut self, v: ::std::string::String) { - self.row_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_row_id(&mut self) -> &mut ::std::string::String { - &mut self.row_id - } - - // Take field - pub fn take_row_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) - } - - // string field_id = 3; - - - pub fn get_field_id(&self) -> &str { - &self.field_id - } - pub fn clear_field_id(&mut self) { - self.field_id.clear(); - } - - // Param is passed by value, moved - pub fn set_field_id(&mut self, v: ::std::string::String) { - self.field_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_field_id(&mut self) -> &mut ::std::string::String { - &mut self.field_id - } - - // Take field - pub fn take_field_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) - } - - // string insert_option_id = 4; - - - pub fn get_insert_option_id(&self) -> &str { - match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v)) => v, - _ => "", - } - } - pub fn clear_insert_option_id(&mut self) { - self.one_of_insert_option_id = ::std::option::Option::None; - } - - pub fn has_insert_option_id(&self) -> bool { - match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_insert_option_id(&mut self, v: ::std::string::String) { - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) - } - - // Mutable pointer to the field. - pub fn mut_insert_option_id(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(_)) = self.one_of_insert_option_id { - } else { - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(::std::string::String::new())); - } - match self.one_of_insert_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_insert_option_id(&mut self) -> ::std::string::String { - if self.has_insert_option_id() { - match self.one_of_insert_option_id.take() { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(v)) => v, - _ => panic!(), - } - } else { - ::std::string::String::new() - } - } - - // string delete_option_id = 5; - - - pub fn get_delete_option_id(&self) -> &str { - match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v)) => v, - _ => "", - } - } - pub fn clear_delete_option_id(&mut self) { - self.one_of_delete_option_id = ::std::option::Option::None; - } - - pub fn has_delete_option_id(&self) -> bool { - match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_delete_option_id(&mut self, v: ::std::string::String) { - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) - } - - // Mutable pointer to the field. - pub fn mut_delete_option_id(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(_)) = self.one_of_delete_option_id { - } else { - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(::std::string::String::new())); - } - match self.one_of_delete_option_id { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_delete_option_id(&mut self) -> ::std::string::String { - if self.has_delete_option_id() { - match self.one_of_delete_option_id.take() { - ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(v)) => v, - _ => panic!(), - } - } else { - ::std::string::String::new() - } - } -} - -impl ::protobuf::Message for SelectOptionCellChangesetPayload { - 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.grid_id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; - }, - 3 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; - }, - 4 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_insert_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(is.read_string()?)); - }, - 5 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_delete_option_id = ::std::option::Option::Some(SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(is.read_string()?)); - }, - _ => { - ::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.grid_id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.grid_id); - } - if !self.row_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.row_id); - } - if !self.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.field_id); - } - if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { - match v { - &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { - my_size += ::protobuf::rt::string_size(4, &v); - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { - match v { - &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { - my_size += ::protobuf::rt::string_size(5, &v); - }, - }; - } - 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.grid_id.is_empty() { - os.write_string(1, &self.grid_id)?; - } - if !self.row_id.is_empty() { - os.write_string(2, &self.row_id)?; - } - if !self.field_id.is_empty() { - os.write_string(3, &self.field_id)?; - } - if let ::std::option::Option::Some(ref v) = self.one_of_insert_option_id { - match v { - &SelectOptionCellChangesetPayload_oneof_one_of_insert_option_id::insert_option_id(ref v) => { - os.write_string(4, v)?; - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_delete_option_id { - match v { - &SelectOptionCellChangesetPayload_oneof_one_of_delete_option_id::delete_option_id(ref v) => { - os.write_string(5, v)?; - }, - }; - } - 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() -> SelectOptionCellChangesetPayload { - SelectOptionCellChangesetPayload::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>( - "grid_id", - |m: &SelectOptionCellChangesetPayload| { &m.grid_id }, - |m: &mut SelectOptionCellChangesetPayload| { &mut m.grid_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "row_id", - |m: &SelectOptionCellChangesetPayload| { &m.row_id }, - |m: &mut SelectOptionCellChangesetPayload| { &mut m.row_id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "field_id", - |m: &SelectOptionCellChangesetPayload| { &m.field_id }, - |m: &mut SelectOptionCellChangesetPayload| { &mut m.field_id }, - )); - fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( - "insert_option_id", - SelectOptionCellChangesetPayload::has_insert_option_id, - SelectOptionCellChangesetPayload::get_insert_option_id, - )); - fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( - "delete_option_id", - SelectOptionCellChangesetPayload::has_delete_option_id, - SelectOptionCellChangesetPayload::get_delete_option_id, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "SelectOptionCellChangesetPayload", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static SelectOptionCellChangesetPayload { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(SelectOptionCellChangesetPayload::new) - } -} - -impl ::protobuf::Clear for SelectOptionCellChangesetPayload { - fn clear(&mut self) { - self.grid_id.clear(); - self.row_id.clear(); - self.field_id.clear(); - self.one_of_insert_option_id = ::std::option::Option::None; - self.one_of_delete_option_id = ::std::option::Option::None; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for SelectOptionCellChangesetPayload { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for SelectOptionCellChangesetPayload { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct SelectOptionContext { - // message fields - pub options: ::protobuf::RepeatedField, - pub select_options: ::protobuf::RepeatedField, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a SelectOptionContext { - fn default() -> &'a SelectOptionContext { - ::default_instance() - } -} - -impl SelectOptionContext { - pub fn new() -> SelectOptionContext { - ::std::default::Default::default() - } - - // repeated .SelectOption options = 1; - - - pub fn get_options(&self) -> &[SelectOption] { - &self.options - } - pub fn clear_options(&mut self) { - self.options.clear(); - } - - // Param is passed by value, moved - pub fn set_options(&mut self, v: ::protobuf::RepeatedField) { - self.options = v; - } - - // Mutable pointer to the field. - pub fn mut_options(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.options - } - - // Take field - pub fn take_options(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.options, ::protobuf::RepeatedField::new()) - } - - // repeated .SelectOption select_options = 2; - - - pub fn get_select_options(&self) -> &[SelectOption] { - &self.select_options - } - pub fn clear_select_options(&mut self) { - self.select_options.clear(); - } - - // Param is passed by value, moved - pub fn set_select_options(&mut self, v: ::protobuf::RepeatedField) { - self.select_options = v; - } - - // Mutable pointer to the field. - pub fn mut_select_options(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.select_options - } - - // Take field - pub fn take_select_options(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.select_options, ::protobuf::RepeatedField::new()) - } -} - -impl ::protobuf::Message for SelectOptionContext { - fn is_initialized(&self) -> bool { - for v in &self.options { - if !v.is_initialized() { - return false; - } - }; - for v in &self.select_options { - 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.options)?; - }, - 2 => { - ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.select_options)?; - }, - _ => { - ::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.options { - let len = value.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - }; - for value in &self.select_options { - 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.options { - os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - }; - for v in &self.select_options { - os.write_tag(2, ::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() -> SelectOptionContext { - SelectOptionContext::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>( - "options", - |m: &SelectOptionContext| { &m.options }, - |m: &mut SelectOptionContext| { &mut m.options }, - )); - fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "select_options", - |m: &SelectOptionContext| { &m.select_options }, - |m: &mut SelectOptionContext| { &mut m.select_options }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "SelectOptionContext", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static SelectOptionContext { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(SelectOptionContext::new) - } -} - -impl ::protobuf::Clear for SelectOptionContext { - fn clear(&mut self) { - self.options.clear(); - self.select_options.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for SelectOptionContext { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for SelectOptionContext { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -#[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum SelectOptionColor { - Purple = 0, - Pink = 1, - LightPink = 2, - Orange = 3, - Yellow = 4, - Lime = 5, - Green = 6, - Aqua = 7, - Blue = 8, -} - -impl ::protobuf::ProtobufEnum for SelectOptionColor { - fn value(&self) -> i32 { - *self as i32 - } - - fn from_i32(value: i32) -> ::std::option::Option { - match value { - 0 => ::std::option::Option::Some(SelectOptionColor::Purple), - 1 => ::std::option::Option::Some(SelectOptionColor::Pink), - 2 => ::std::option::Option::Some(SelectOptionColor::LightPink), - 3 => ::std::option::Option::Some(SelectOptionColor::Orange), - 4 => ::std::option::Option::Some(SelectOptionColor::Yellow), - 5 => ::std::option::Option::Some(SelectOptionColor::Lime), - 6 => ::std::option::Option::Some(SelectOptionColor::Green), - 7 => ::std::option::Option::Some(SelectOptionColor::Aqua), - 8 => ::std::option::Option::Some(SelectOptionColor::Blue), - _ => ::std::option::Option::None - } - } - - fn values() -> &'static [Self] { - static values: &'static [SelectOptionColor] = &[ - SelectOptionColor::Purple, - SelectOptionColor::Pink, - SelectOptionColor::LightPink, - SelectOptionColor::Orange, - SelectOptionColor::Yellow, - SelectOptionColor::Lime, - SelectOptionColor::Green, - SelectOptionColor::Aqua, - SelectOptionColor::Blue, - ]; - 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::("SelectOptionColor", file_descriptor_proto()) - }) - } -} - -impl ::std::marker::Copy for SelectOptionColor { -} - -impl ::std::default::Default for SelectOptionColor { - fn default() -> Self { - SelectOptionColor::Purple - } -} - -impl ::protobuf::reflect::ProtobufValue for SelectOptionColor { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x11type_option.proto\"\\\n\x0cSelectOption\x12\x0e\n\x02id\x18\x01\ - \x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12(\n\ - \x05color\x18\x03\x20\x01(\x0e2\x12.SelectOptionColorR\x05color\"\xfb\ - \x01\n\x20SelectOptionCellChangesetPayload\x12\x17\n\x07grid_id\x18\x01\ - \x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\ - \x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12*\n\x10insert_o\ - ption_id\x18\x04\x20\x01(\tH\0R\x0einsertOptionId\x12*\n\x10delete_optio\ - n_id\x18\x05\x20\x01(\tH\x01R\x0edeleteOptionIdB\x19\n\x17one_of_insert_\ - option_idB\x19\n\x17one_of_delete_option_id\"t\n\x13SelectOptionContext\ - \x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x124\ - \n\x0eselect_options\x18\x02\x20\x03(\x0b2\r.SelectOptionR\rselectOption\ - s*y\n\x11SelectOptionColor\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\ - \x01\x12\r\n\tLightPink\x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yel\ - low\x10\x04\x12\x08\n\x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\ - \x04Aqua\x10\x07\x12\x08\n\x04Blue\x10\x08b\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/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto deleted file mode 100644 index 5f375f93aa..0000000000 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/type_option.proto +++ /dev/null @@ -1,29 +0,0 @@ -syntax = "proto3"; - -message SelectOption { - string id = 1; - string name = 2; - SelectOptionColor color = 3; -} -message SelectOptionCellChangesetPayload { - string grid_id = 1; - string row_id = 2; - string field_id = 3; - oneof one_of_insert_option_id { string insert_option_id = 4; }; - oneof one_of_delete_option_id { string delete_option_id = 5; }; -} -message SelectOptionContext { - repeated SelectOption options = 1; - repeated SelectOption select_options = 2; -} -enum SelectOptionColor { - Purple = 0; - Pink = 1; - LightPink = 2; - Orange = 3; - Yellow = 4; - Lime = 5; - Green = 6; - Aqua = 7; - Blue = 8; -} From bf8a752b4df9324a5067ef45d81e5bf90d73df28 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 16:36:59 +0800 Subject: [PATCH 44/47] fix: update row after field was changed --- .../app_flowy/lib/startup/deps_resolver.dart | 2 +- .../grid/field/field_editor_bloc.dart | 4 +-- .../application/grid/field/field_service.dart | 23 +++++++++++++--- .../grid/field/field_switch_bloc.dart | 18 ++++--------- .../grid/field/grid_header_bloc.dart | 10 +++---- .../application/grid/row/row_bloc.dart | 8 +++--- .../grid/src/widgets/header/field_editor.dart | 23 ++++++++-------- .../src/widgets/header/field_switcher.dart | 26 ++++++++++++++++--- .../grid/src/widgets/row/grid_row.dart | 8 +++--- 9 files changed, 75 insertions(+), 47 deletions(-) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 58ad1cf9cc..2b37642f39 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -172,7 +172,7 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (gridId, fieldLoader) => FieldEditorBloc( service: FieldService(gridId: gridId), fieldLoader: fieldLoader, diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart index dd27f66070..c38713862e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart @@ -11,11 +11,11 @@ part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { final FieldService service; - final FieldContextLoader _loader; + final EditFieldContextLoader _loader; FieldEditorBloc({ required this.service, - required FieldContextLoader fieldLoader, + required EditFieldContextLoader fieldLoader, }) : _loader = fieldLoader, super(FieldEditorState.initial(service.gridId)) { on( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index 3ea1c46062..2336c4f340 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -112,11 +112,13 @@ class GridFieldCellContext extends Equatable { List get props => [field.id]; } -abstract class FieldContextLoader { +abstract class EditFieldContextLoader { Future> load(); + + Future> switchToField(String fieldId, FieldType fieldType); } -class NewFieldContextLoader extends FieldContextLoader { +class NewFieldContextLoader extends EditFieldContextLoader { final String gridId; NewFieldContextLoader({ required this.gridId, @@ -130,9 +132,18 @@ class NewFieldContextLoader extends FieldContextLoader { return GridEventGetEditFieldContext(payload).send(); } + + @override + Future> switchToField(String fieldId, FieldType fieldType) { + final payload = GetEditFieldContextPayload.create() + ..gridId = gridId + ..fieldType = fieldType; + + return GridEventGetEditFieldContext(payload).send(); + } } -class FieldContextLoaderAdaptor extends FieldContextLoader { +class FieldContextLoaderAdaptor extends EditFieldContextLoader { final String gridId; final Field field; @@ -150,4 +161,10 @@ class FieldContextLoaderAdaptor extends FieldContextLoader { return GridEventGetEditFieldContext(payload).send(); } + + @override + Future> switchToField(String fieldId, FieldType fieldType) async { + final fieldService = FieldService(gridId: gridId); + return fieldService.switchToField(fieldId, fieldType); + } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart index 802b39d95a..082c0decf4 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart @@ -1,11 +1,8 @@ import 'dart:typed_data'; -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'field_service.dart'; part 'field_switch_bloc.freezed.dart'; @@ -15,15 +12,10 @@ class FieldSwitcherBloc extends Bloc { (event, emit) async { await event.map( toFieldType: (_ToFieldType value) async { - final fieldService = FieldService(gridId: state.gridId); - final result = await fieldService.switchToField(state.field.id, value.fieldType); - result.fold( - (newEditContext) { - final typeOptionData = Uint8List.fromList(newEditContext.typeOptionData); - emit(state.copyWith(field: newEditContext.gridField, typeOptionData: typeOptionData)); - }, - (err) => Log.error(err), - ); + emit(state.copyWith( + field: value.field, + typeOptionData: Uint8List.fromList(value.typeOptionData), + )); }, didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) { emit(state.copyWith(typeOptionData: value.typeOptionData)); @@ -41,7 +33,7 @@ class FieldSwitcherBloc extends Bloc { @freezed class FieldSwitchEvent with _$FieldSwitchEvent { - const factory FieldSwitchEvent.toFieldType(FieldType fieldType) = _ToFieldType; + const factory FieldSwitchEvent.toFieldType(Field field, List typeOptionData) = _ToFieldType; const factory FieldSwitchEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData; } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart index ae10505bc7..4145e23804 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/grid_header_bloc.dart @@ -11,12 +11,12 @@ part 'grid_header_bloc.freezed.dart'; class GridHeaderBloc extends Bloc { final FieldService service; - final GridFieldsListener fieldListener; + final GridFieldsListener _fieldListener; GridHeaderBloc({ required GridHeaderData data, required this.service, - }) : fieldListener = GridFieldsListener(gridId: data.gridId), + }) : _fieldListener = GridFieldsListener(gridId: data.gridId), super(GridHeaderState.initial(data.fields)) { on( (event, emit) async { @@ -36,19 +36,19 @@ class GridHeaderBloc extends Bloc { } Future _startListening() async { - fieldListener.updateFieldsNotifier.addPublishListener((result) { + _fieldListener.updateFieldsNotifier.addPublishListener((result) { result.fold( (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)), (err) => Log.error(err), ); }); - fieldListener.start(); + _fieldListener.start(); } @override Future close() async { - await fieldListener.stop(); + await _fieldListener.stop(); return super.close(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 3c29d82d46..418cb23e88 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -52,7 +52,7 @@ class RowBloc extends Bloc { } void _handleRowUpdate(_DidUpdateRow value, Emitter emit) { - final CellDataMap cellDataMap = _makeCellDatas(value.row); + final CellDataMap cellDataMap = _makeCellDatas(value.row, state.fields); emit(state.copyWith( row: Future(() => Some(value.row)), cellDataMap: Some(cellDataMap), @@ -63,7 +63,7 @@ class RowBloc extends Bloc { final optionRow = await state.row; final CellDataMap cellDataMap = optionRow.fold( () => CellDataMap.identity(), - (row) => _makeCellDatas(row), + (row) => _makeCellDatas(row, value.fields), ); emit(state.copyWith( @@ -107,9 +107,9 @@ class RowBloc extends Bloc { }); } - CellDataMap _makeCellDatas(Row row) { + CellDataMap _makeCellDatas(Row row, List fields) { var map = CellDataMap.new(); - for (final field in state.fields) { + for (final field in fields) { if (field.visibility) { map[field.id] = CellData( rowId: row.id, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index d568829558..3a41ee938b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -5,6 +5,7 @@ import 'package:app_flowy/workspace/application/grid/field/field_switch_bloc.dar import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_name_input.dart'; @@ -13,7 +14,7 @@ import 'field_switcher.dart'; class FieldEditor extends FlowyOverlayDelegate { final String gridId; final FieldEditorBloc _fieldEditorBloc; - final FieldContextLoader? fieldContextLoader; + final EditFieldContextLoader fieldContextLoader; FieldEditor({ required this.gridId, required this.fieldContextLoader, @@ -29,7 +30,7 @@ class FieldEditor extends FlowyOverlayDelegate { FlowyOverlay.of(context).remove(identifier()); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: _FieldEditorWidget(_fieldEditorBloc), + child: _FieldEditorWidget(_fieldEditorBloc, fieldContextLoader), constraints: BoxConstraints.loose(const Size(220, 400)), ), identifier: identifier(), @@ -55,7 +56,8 @@ class FieldEditor extends FlowyOverlayDelegate { class _FieldEditorWidget extends StatelessWidget { final FieldEditorBloc editorBloc; - const _FieldEditorWidget(this.editorBloc, {Key? key}) : super(key: key); + final EditFieldContextLoader fieldContextLoader; + const _FieldEditorWidget(this.editorBloc, this.fieldContextLoader, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -72,7 +74,7 @@ class _FieldEditorWidget extends StatelessWidget { const VSpace(10), const _FieldNameTextField(), const VSpace(10), - _FieldSwitcher(SwitchFieldContext(state.gridId, field, state.typeOptionData)), + _renderSwitchButton(context, field, state), ], ), ); @@ -80,16 +82,13 @@ class _FieldEditorWidget extends StatelessWidget { ), ); } -} -class _FieldSwitcher extends StatelessWidget { - final SwitchFieldContext switchContext; - const _FieldSwitcher(this.switchContext, {Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { + Widget _renderSwitchButton(BuildContext context, Field field, FieldEditorState state) { return FieldSwitcher( - switchContext: switchContext, + switchContext: SwitchFieldContext(state.gridId, field, state.typeOptionData), + onSwitchToField: (fieldId, fieldType) { + return fieldContextLoader.switchToField(fieldId, fieldType); + }, onUpdated: (field, typeOptionData) { context.read().add(FieldEditorEvent.switchField(field, typeOptionData)); }, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart index 63816c7d74..decaaec611 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart @@ -7,6 +7,8 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart'; @@ -17,20 +19,26 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; import 'field_type_extension.dart'; - +import 'package:dartz/dartz.dart' show Either; import 'type_option/multi_select.dart'; import 'type_option/number.dart'; import 'type_option/single_select.dart'; typedef UpdateFieldCallback = void Function(Field, Uint8List); +typedef SwitchToFieldCallback = Future> Function( + String fieldId, + FieldType fieldType, +); class FieldSwitcher extends StatefulWidget { final SwitchFieldContext switchContext; final UpdateFieldCallback onUpdated; + final SwitchToFieldCallback onSwitchToField; const FieldSwitcher({ required this.switchContext, required this.onUpdated, + required this.onSwitchToField, Key? key, }) : super(key: key); @@ -79,8 +87,20 @@ class _FieldSwitcherState extends State { padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), hoverColor: theme.hover, onTap: () { - final list = FieldTypeList(onSelectField: (fieldType) { - context.read().add(FieldSwitchEvent.toFieldType(fieldType)); + final list = FieldTypeList(onSelectField: (newFieldType) { + widget.onSwitchToField(field.id, newFieldType).then((result) { + result.fold( + (editFieldContext) { + context.read().add( + FieldSwitchEvent.toFieldType( + editFieldContext.gridField, + editFieldContext.typeOptionData, + ), + ); + }, + (err) => Log.error(err), + ); + }); }); _showOverlay(context, list); }, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index d3ac6d8ce3..08d68f197a 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -19,12 +19,12 @@ class GridRowWidget extends StatefulWidget { class _GridRowWidgetState extends State { late RowBloc _rowBloc; - late RowRegionStateNotifier _rowStateNotifier; + late _RegionStateNotifier _rowStateNotifier; @override void initState() { _rowBloc = getIt(param1: widget.data)..add(const RowEvent.initial()); - _rowStateNotifier = RowRegionStateNotifier(); + _rowStateNotifier = _RegionStateNotifier(); super.initState(); } @@ -72,7 +72,7 @@ class _RowLeading extends StatelessWidget { @override Widget build(BuildContext context) { - return Consumer( + return Consumer<_RegionStateNotifier>( builder: (context, state, _) { return SizedBox(width: GridSize.leadingHeaderPadding, child: state.onEnter ? _activeWidget() : null); }, @@ -140,7 +140,7 @@ class _RowCells extends StatelessWidget { } } -class RowRegionStateNotifier extends ChangeNotifier { +class _RegionStateNotifier extends ChangeNotifier { bool _onEnter = false; set onEnter(bool value) { From c82c6d9c6e9f9ed9068b096221dea2173e7207f5 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 17:07:46 +0800 Subject: [PATCH 45/47] fix: deserialize multiple select cell data issues --- .../grid/cell_bloc/cell_service.dart | 2 -- .../grid/cell_bloc/selection_editor_bloc.dart | 30 ++++++++++++------- .../grid/setting/setting_bloc.dart | 1 - .../header/type_option/multi_select.dart | 2 +- .../lib/src/flowy_overlay/flowy_overlay.dart | 2 +- .../lib/src/flowy_overlay/list_overlay.dart | 3 -- .../type_options/selection_type_option.rs | 23 ++++++++++++-- 7 files changed, 42 insertions(+), 21 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index b36727adcc..e1af022d95 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -1,9 +1,7 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; class CellService { CellService(); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart index c6396138a9..e7f471dece 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -15,6 +15,7 @@ class SelectOptionEditorBloc extends Bloc close() async { + _delayOperation?.cancel(); await _fieldListener.stop(); await _cellListener.stop(); return super.close(); @@ -106,18 +108,24 @@ class SelectOptionEditorBloc extends Bloc add(SelectOptionEditorEvent.didReceiveOptions( - selectOptionContext.options, - selectOptionContext.selectOptions, - )), - (err) => Log.error(err), + result.fold( + (selectOptionContext) => add(SelectOptionEditorEvent.didReceiveOptions( + selectOptionContext.options, + selectOptionContext.selectOptions, + )), + (err) => Log.error(err), + ); + }, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart index 38071155af..bea2b87da6 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/setting/setting_bloc.dart @@ -1,4 +1,3 @@ -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index 99728aeffb..11d2c866ce 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'option_pannel.dart'; class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { - MultiSelectTypeOptionWidget _widget; + final MultiSelectTypeOptionWidget _widget; MultiSelectTypeOptionBuilder( String fieldId, diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 0290cf18b3..1229745381 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -122,7 +122,7 @@ class OverlayItem { } class FlowyOverlayState extends State { - List _overlayList = []; + final List _overlayList = []; FlowyOverlayStyle style = FlowyOverlayStyle(); /// Insert a overlay widget which frame is set by the widget, not the component. diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart index 6c0a4019d1..16d3b55f47 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart @@ -1,8 +1,5 @@ import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flutter/material.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:provider/provider.dart'; class ListOverlayFooter { Widget widget; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index ad95fe6a54..786cd2ce0d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -85,8 +85,10 @@ impl CellDataOperation for SingleSelectTypeOption { let select_option_changeset: SelectOptionCellChangeset = serde_json::from_str(&changeset)?; let new_cell_data: String; if let Some(insert_option_id) = select_option_changeset.insert_option_id { + tracing::trace!("Insert single select option: {}", &insert_option_id); new_cell_data = insert_option_id; } else { + tracing::trace!("Delete single select option"); new_cell_data = "".to_string() } @@ -127,6 +129,15 @@ pub struct MultiSelectTypeOption { } impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl MultiSelectTypeOption { + pub fn get_cell_data(&self, cell_meta: &CellMeta) -> String { + match TypeOptionCellData::from_str(&cell_meta.data) { + Ok(type_option) => type_option.data, + Err(_) => String::new(), + } + } +} + impl SelectOptionOperation for MultiSelectTypeOption { fn insert_option(&mut self, new_option: SelectOption) { if let Some(index) = self.options.iter().position(|option| option.id == new_option.id) { @@ -185,16 +196,24 @@ impl CellDataOperation for MultiSelectTypeOption { .unwrap_or_else(|| "".to_owned()); } Some(cell_meta) => { - let mut selected_options = select_option_ids(cell_meta.data); + let cell_data = self.get_cell_data(&cell_meta); + let mut selected_options = select_option_ids(cell_data); if let Some(insert_option_id) = select_option_changeset.insert_option_id { - selected_options.push(insert_option_id); + tracing::trace!("Insert multi select option: {}", &insert_option_id); + if selected_options.contains(&insert_option_id) { + selected_options.retain(|id| id != &insert_option_id); + } else { + selected_options.push(insert_option_id); + } } if let Some(delete_option_id) = select_option_changeset.delete_option_id { + tracing::trace!("Delete multi select option: {}", &delete_option_id); selected_options.retain(|id| id != &delete_option_id); } new_cell_data = selected_options.join(SELECTION_IDS_SEPARATOR); + tracing::trace!("Multi select cell data: {}", &new_cell_data); } } From e15d335fed477813c7bec40f1f93b8c9254e26f4 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 20:15:00 +0800 Subject: [PATCH 46/47] chore: config checkbox ui --- .../grid/cell_bloc/cell_service.dart | 14 ++++ .../grid/cell_bloc/checkbox_cell_bloc.dart | 65 ++++++++++++++++--- .../grid/src/widgets/cell/checkbox_cell.dart | 15 ++++- .../dart_event/flowy-grid/dart_event.dart | 17 +++++ .../protobuf/flowy-grid/event_map.pbenum.dart | 6 +- .../protobuf/flowy-grid/event_map.pbjson.dart | 7 +- .../rust-lib/flowy-grid/src/event_handler.rs | 13 ++++ frontend/rust-lib/flowy-grid/src/event_map.rs | 8 ++- .../src/protobuf/model/event_map.rs | 17 +++-- .../src/protobuf/proto/event_map.proto | 5 +- .../flowy-grid/src/services/grid_editor.rs | 7 ++ frontend/rust-lib/flowy-grid/src/util.rs | 8 ++- 12 files changed, 154 insertions(+), 28 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart index e1af022d95..9bdd48c259 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/cell_service.dart @@ -1,7 +1,9 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; class CellService { CellService(); @@ -19,4 +21,16 @@ class CellService { ..data = data; return GridEventUpdateCell(payload).send(); } + + Future> getCell({ + required String gridId, + required String fieldId, + required String rowId, + }) { + final payload = CellIdentifierPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..rowId = rowId; + return GridEventGetCell(payload).send(); + } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index f5bc7e7c18..ae69176fd9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -1,5 +1,7 @@ +import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -8,17 +10,32 @@ import 'cell_service.dart'; part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { - final CellService service; - // final CellData cellData; + final CellService _service; + final CellListener _listener; CheckboxCellBloc({ - required this.service, + required CellService service, required CellData cellData, - }) : super(CheckboxCellState.initial()) { + }) : _service = service, + _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), + super(CheckboxCellState.initial(cellData)) { on( (event, emit) async { await event.map( - initial: (_InitialCell value) async {}, + initial: (_Initial value) { + _startListening(); + }, + select: (_Selected value) async { + service.updateCell( + gridId: state.cellData.gridId, + fieldId: state.cellData.field.id, + rowId: state.cellData.rowId, + data: !state.isSelected ? "Yes" : "No", + ); + }, + didReceiveCellUpdate: (_DidReceiveCellUpdate value) { + emit(state.copyWith(isSelected: isSelected(value.cell))); + }, ); }, ); @@ -28,18 +45,48 @@ class CheckboxCellBloc extends Bloc { Future close() async { return super.close(); } + + void _startListening() { + _listener.updateCellNotifier.addPublishListener((result) { + result.fold( + (notificationData) async { + final result = await _service.getCell( + gridId: state.cellData.gridId, + fieldId: state.cellData.field.id, + rowId: state.cellData.rowId, + ); + result.fold( + (cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)), + (err) => Log.error(err), + ); + }, + (err) => Log.error(err), + ); + }); + _listener.start(); + } } @freezed class CheckboxCellEvent with _$CheckboxCellEvent { - const factory CheckboxCellEvent.initial() = _InitialCell; + const factory CheckboxCellEvent.initial() = _Initial; + const factory CheckboxCellEvent.select() = _Selected; + const factory CheckboxCellEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate; } @freezed class CheckboxCellState with _$CheckboxCellState { const factory CheckboxCellState({ - required Cell? cell, + required CellData cellData, + required bool isSelected, }) = _CheckboxCellState; - factory CheckboxCellState.initial() => const CheckboxCellState(cell: null); + factory CheckboxCellState.initial(CellData cellData) { + return CheckboxCellState(cellData: cellData, isSelected: isSelected(cellData.cell)); + } +} + +bool isSelected(Cell? cell) { + final content = cell?.content ?? ""; + return content == "Yes"; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 7e1fdf166a..b4095c71d9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -1,5 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -20,7 +22,7 @@ class _CheckboxCellState extends State { @override void initState() { - _cellBloc = getIt(param1: widget.cellData); + _cellBloc = getIt(param1: widget.cellData)..add(const CheckboxCellEvent.initial()); super.initState(); } @@ -30,7 +32,16 @@ class _CheckboxCellState extends State { value: _cellBloc, child: BlocBuilder( builder: (context, state) { - return Container(); + final icon = state.isSelected ? svgWidget('editor/editor_check') : svgWidget('editor/editor_uncheck'); + return Align( + alignment: Alignment.centerLeft, + child: FlowyIconButton( + onPressed: () => context.read().add(const CheckboxCellEvent.select()), + iconPadding: EdgeInsets.zero, + icon: icon, + width: 23, + ), + ); }, ), ); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart index 3003b4c6f8..a4871a6bef 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart @@ -239,6 +239,23 @@ class GridEventGetRow { } } +class GridEventGetCell { + CellIdentifierPayload request; + GridEventGetCell(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.GetCell.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(Cell.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventUpdateCell { CellMetaChangeset request; GridEventUpdateCell(this.request); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart index 7c190dcd98..37032ec41b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart @@ -24,8 +24,9 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent ApplySelectOptionChangeset = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset'); static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow'); static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow'); - static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); - static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset'); + static const GridEvent GetCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCell'); + static const GridEvent UpdateCell = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell'); + static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(72, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset'); static const $core.List values = [ GetGridData, @@ -42,6 +43,7 @@ class GridEvent extends $pb.ProtobufEnum { ApplySelectOptionChangeset, CreateRow, GetRow, + GetCell, UpdateCell, ApplySelectOptionCellChangeset, ]; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart index 1c07877726..bc4b838bca 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart @@ -26,10 +26,11 @@ const GridEvent$json = const { const {'1': 'ApplySelectOptionChangeset', '2': 32}, const {'1': 'CreateRow', '2': 50}, const {'1': 'GetRow', '2': 51}, - const {'1': 'UpdateCell', '2': 70}, - const {'1': 'ApplySelectOptionCellChangeset', '2': 71}, + const {'1': 'GetCell', '2': 70}, + const {'1': 'UpdateCell', '2': 71}, + const {'1': 'ApplySelectOptionCellChangeset', '2': 72}, ], }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg4KClVwZGF0ZUNlbGwQRhIiCh5BcHBseVNlbGVjdE9wdGlvbkNlbGxDaGFuZ2VzZXQQRw=='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 3d46349240..ec6dc9659e 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -190,6 +190,19 @@ pub(crate) async fn create_row_handler( Ok(()) } +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_cell_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: CellIdentifier = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + match editor.get_cell(¶ms).await { + None => data_result(Cell::new(¶ms.field_id, "".to_owned())), + Some(cell) => data_result(cell), + } +} + #[tracing::instrument(level = "debug", skip_all, err)] pub(crate) async fn update_cell_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 711ad46255..8a4c68e468 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -21,6 +21,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) // Cell + .event(GridEvent::GetCell, get_cell_handler) .event(GridEvent::UpdateCell, update_cell_handler) // SelectOption .event(GridEvent::NewSelectOption, new_select_option_handler) @@ -80,9 +81,12 @@ pub enum GridEvent { #[event(input = "RowIdentifierPayload", output = "Row")] GetRow = 51, + #[event(input = "CellIdentifierPayload", output = "Cell")] + GetCell = 70, + #[event(input = "CellMetaChangeset")] - UpdateCell = 70, + UpdateCell = 71, #[event(input = "SelectOptionCellChangesetPayload")] - ApplySelectOptionCellChangeset = 71, + ApplySelectOptionCellChangeset = 72, } diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs index ef26608bf1..d9cfbac578 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs @@ -39,8 +39,9 @@ pub enum GridEvent { ApplySelectOptionChangeset = 32, CreateRow = 50, GetRow = 51, - UpdateCell = 70, - ApplySelectOptionCellChangeset = 71, + GetCell = 70, + UpdateCell = 71, + ApplySelectOptionCellChangeset = 72, } impl ::protobuf::ProtobufEnum for GridEvent { @@ -64,8 +65,9 @@ impl ::protobuf::ProtobufEnum for GridEvent { 32 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset), 50 => ::std::option::Option::Some(GridEvent::CreateRow), 51 => ::std::option::Option::Some(GridEvent::GetRow), - 70 => ::std::option::Option::Some(GridEvent::UpdateCell), - 71 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset), + 70 => ::std::option::Option::Some(GridEvent::GetCell), + 71 => ::std::option::Option::Some(GridEvent::UpdateCell), + 72 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset), _ => ::std::option::Option::None } } @@ -86,6 +88,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::ApplySelectOptionChangeset, GridEvent::CreateRow, GridEvent::GetRow, + GridEvent::GetCell, GridEvent::UpdateCell, GridEvent::ApplySelectOptionCellChangeset, ]; @@ -116,15 +119,15 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xd1\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xde\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\ \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\ leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\ ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x13\n\x0fNewSe\ lectOption\x10\x1e\x12\x1a\n\x16GetSelectOptionContext\x10\x1f\x12\x1e\n\ \x1aApplySelectOptionChangeset\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\ - \x06GetRow\x103\x12\x0e\n\nUpdateCell\x10F\x12\"\n\x1eApplySelectOptionC\ - ellChangeset\x10Gb\x06proto3\ + \x06GetRow\x103\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\ + \"\n\x1eApplySelectOptionCellChangeset\x10Hb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto index caddf2de41..1201bd759e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto @@ -15,6 +15,7 @@ enum GridEvent { ApplySelectOptionChangeset = 32; CreateRow = 50; GetRow = 51; - UpdateCell = 70; - ApplySelectOptionCellChangeset = 71; + GetCell = 70; + UpdateCell = 71; + ApplySelectOptionCellChangeset = 72; } 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 cddafd3fdd..a91f0bb606 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,6 +1,7 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_manager::GridBlockMetaEditorManager; +use crate::services::cell::CellIdentifier; use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::persistence::block_index::BlockIndexPersistence; use crate::services::row::*; @@ -264,6 +265,12 @@ impl ClientGridEditor { } } + pub async fn get_cell(&self, params: &CellIdentifier) -> Option { + let field_meta = self.get_field_meta(¶ms.field_id).await?; + let row_meta = self.block_meta_manager.get_row_meta(¶ms.row_id).await.ok()??; + make_cell(¶ms.field_id, &field_meta, &row_meta) + } + pub async fn get_cell_meta(&self, row_id: &str, field_id: &str) -> FlowyResult> { let row_meta = self.block_meta_manager.get_row_meta(row_id).await?; match row_meta { diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 9af437a40f..bbc2d1b642 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -1,5 +1,5 @@ use crate::services::field::*; -use flowy_grid_data_model::entities::BuildGridContext; +use flowy_grid_data_model::entities::{BuildGridContext, FieldType}; use flowy_sync::client_grid::GridBuilder; pub fn make_default_grid() -> BuildGridContext { @@ -25,10 +25,16 @@ pub fn make_default_grid() -> BuildGridContext { .visibility(true) .build(); + let checkbox_field = FieldBuilder::from_field_type(&FieldType::Checkbox) + .name("isReady") + .visibility(true) + .build(); + GridBuilder::default() .add_field(text_field) .add_field(single_select_field) .add_field(multi_select_field) + .add_field(checkbox_field) .add_empty_row() .add_empty_row() .add_empty_row() From 11627269bee2cdbcc9b64adfca5fdfe01411937d Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 7 Apr 2022 20:54:22 +0800 Subject: [PATCH 47/47] chore: config number ui --- .../app_flowy/lib/startup/deps_resolver.dart | 1 - .../grid/cell_bloc/checkbox_cell_bloc.dart | 3 +- .../grid/cell_bloc/number_cell_bloc.dart | 66 +++++++++++++++++-- .../grid/src/widgets/cell/number_cell.dart | 44 ++++++++++++- .../grid/src/widgets/cell/text_cell.dart | 3 +- .../src/widgets/header/field_type_list.dart | 2 +- 6 files changed, 106 insertions(+), 13 deletions(-) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 2b37642f39..a0af57f580 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -194,7 +194,6 @@ void _resolveGridDeps(GetIt getIt) { getIt.registerFactoryParam( (cellData, _) => NumberCellBloc( - service: CellService(), cellData: cellData, ), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart index ae69176fd9..a2b888a295 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/checkbox_cell_bloc.dart @@ -26,7 +26,7 @@ class CheckboxCellBloc extends Bloc { _startListening(); }, select: (_Selected value) async { - service.updateCell( + _service.updateCell( gridId: state.cellData.gridId, fieldId: state.cellData.field.id, rowId: state.cellData.rowId, @@ -43,6 +43,7 @@ class CheckboxCellBloc extends Bloc { @override Future close() async { + await _listener.stop(); return super.close(); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart index 83d2eff57d..fe5c6befeb 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/number_cell_bloc.dart @@ -1,4 +1,6 @@ +import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -8,37 +10,87 @@ import 'cell_service.dart'; part 'number_cell_bloc.freezed.dart'; class NumberCellBloc extends Bloc { - final CellService service; + final CellService _service; + final CellListener _listener; NumberCellBloc({ - required this.service, required CellData cellData, - }) : super(NumberCellState.initial()) { + }) : _service = CellService(), + _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id), + super(NumberCellState.initial(cellData)) { on( (event, emit) async { await event.map( - initial: (_InitialCell value) async {}, + initial: (_Initial value) async { + _startListening(); + }, + didReceiveCellUpdate: (_DidReceiveCellUpdate value) { + emit(state.copyWith(content: value.cell.content)); + }, + updateCell: (_UpdateCell value) { + _updateCellValue(value, emit); + }, ); }, ); } + void _updateCellValue(_UpdateCell value, Emitter emit) { + final number = num.tryParse(value.text); + if (number == null) { + emit(state.copyWith(content: "")); + } else { + _service.updateCell( + gridId: state.cellData.gridId, + fieldId: state.cellData.field.id, + rowId: state.cellData.rowId, + data: value.text, + ); + } + } + @override Future close() async { + await _listener.stop(); return super.close(); } + + void _startListening() { + _listener.updateCellNotifier.addPublishListener((result) { + result.fold( + (notificationData) async { + final result = await _service.getCell( + gridId: state.cellData.gridId, + fieldId: state.cellData.field.id, + rowId: state.cellData.rowId, + ); + result.fold( + (cell) => add(NumberCellEvent.didReceiveCellUpdate(cell)), + (err) => Log.error(err), + ); + }, + (err) => Log.error(err), + ); + }); + _listener.start(); + } } @freezed class NumberCellEvent with _$NumberCellEvent { - const factory NumberCellEvent.initial() = _InitialCell; + const factory NumberCellEvent.initial() = _Initial; + const factory NumberCellEvent.updateCell(String text) = _UpdateCell; + const factory NumberCellEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate; } @freezed class NumberCellState with _$NumberCellState { const factory NumberCellState({ - Cell? cell, + required CellData cellData, + required String content, }) = _NumberCellState; - factory NumberCellState.initial() => const NumberCellState(); + factory NumberCellState.initial(CellData cellData) { + return NumberCellState(cellData: cellData, content: cellData.cell?.content ?? ""); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 41b8cf6ee5..ba9d75ed1b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -1,5 +1,8 @@ +import 'dart:async'; + import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -17,20 +20,44 @@ class NumberCell extends StatefulWidget { class _NumberCellState extends State { late NumberCellBloc _cellBloc; + late TextEditingController _controller; + late CellFocusNode _focusNode; + Timer? _delayOperation; @override void initState() { _cellBloc = getIt(param1: widget.cellData); + _controller = TextEditingController(text: _cellBloc.state.content); + _focusNode = CellFocusNode(); super.initState(); } @override Widget build(BuildContext context) { + _focusNode.addCallback(context, focusChanged); + return BlocProvider.value( value: _cellBloc, - child: BlocBuilder( + child: BlocConsumer( + listener: (context, state) { + if (_controller.text != state.content) { + _controller.text = state.content; + } + }, builder: (context, state) { - return Container(); + return TextField( + controller: _controller, + focusNode: _focusNode, + onChanged: (value) => focusChanged(), + onEditingComplete: () => _focusNode.unfocus(), + maxLines: 1, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + decoration: const InputDecoration( + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + isDense: true, + ), + ); }, ), ); @@ -38,7 +65,20 @@ class _NumberCellState extends State { @override Future dispose() async { + _delayOperation?.cancel(); _cellBloc.close(); + _focusNode.dispose(); super.dispose(); } + + Future focusChanged() async { + if (mounted) { + _delayOperation?.cancel(); + _delayOperation = Timer(const Duration(milliseconds: 300), () { + if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) { + _cellBloc.add(NumberCellEvent.updateCell(_controller.text)); + } + }); + } + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index c7b4219bab..543a337b9b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -63,6 +63,7 @@ class _GridTextCellState extends State { @override Future dispose() async { + _delayOperation?.cancel(); _cellBloc.close(); _focusNode.dispose(); super.dispose(); @@ -72,7 +73,7 @@ class _GridTextCellState extends State { if (mounted) { _delayOperation?.cancel(); _delayOperation = Timer(const Duration(milliseconds: 300), () { - if (_cellBloc.isClosed == false) { + if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) { _cellBloc.add(TextCellEvent.updateText(_controller.text)); } }); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart index 2965556f60..dfeacf4d17 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart @@ -19,7 +19,7 @@ class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate { @override Widget build(BuildContext context) { - final cells = FieldType.values.map((fieldType) { + final cells = FieldType.values.where((ty) => ty != FieldType.DateTime).map((fieldType) { return FieldTypeCell( fieldType: fieldType, onSelectField: (fieldType) {