From 467e0093b23ff4a9ba8ed2390dee529f915584c9 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 15 May 2022 17:13:01 +0800 Subject: [PATCH 1/8] refactor: rename files --- .../app_flowy/lib/startup/deps_resolver.dart | 4 +- ...bloc.dart => select_option_cell_bloc.dart} | 28 ++++---- ...oc.dart => select_option_editor_bloc.dart} | 6 +- .../workspace/application/grid/prelude.dart | 2 +- .../grid/src/widgets/cell/cell_builder.dart | 2 +- .../src/widgets/cell/date_cell/date_cell.dart | 4 +- .../{calendar.dart => date_editor.dart} | 21 ++---- .../grid/src/widgets/cell/prelude.dart | 2 +- .../extension.dart | 0 .../select_option_cell.dart} | 14 ++-- .../select_option_editor.dart} | 26 +++---- .../text_field.dart | 0 .../header/type_option/multi_select.dart | 10 +-- ..._option_pannel.dart => select_option.dart} | 70 ++++++++++--------- ..._pannel.dart => select_option_editor.dart} | 6 +- .../header/type_option/single_select.dart | 10 +-- 16 files changed, 101 insertions(+), 104 deletions(-) rename frontend/app_flowy/lib/workspace/application/grid/cell/{selection_cell_bloc.dart => select_option_cell_bloc.dart} (69%) rename frontend/app_flowy/lib/workspace/application/grid/cell/{selection_editor_bloc.dart => select_option_editor_bloc.dart} (97%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/{calendar.dart => date_editor.dart} (95%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/{selection_cell => select_option_cell}/extension.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/{selection_cell/selection_cell.dart => select_option_cell/select_option_cell.dart} (90%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/{selection_cell/selection_editor.dart => select_option_cell/select_option_editor.dart} (89%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/{selection_cell => select_option_cell}/text_field.dart (100%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/{field_option_pannel.dart => select_option.dart} (82%) rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/{edit_option_pannel.dart => select_option_editor.dart} (97%) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 8bc5d4dd41..1f7f3524fa 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -170,8 +170,8 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => SelectionCellBloc( + getIt.registerFactoryParam( + (context, _) => SelectOptionCellBloc( cellContext: context, ), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart similarity index 69% rename from frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart index 794ccd3002..056b65e556 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart @@ -4,16 +4,16 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; -part 'selection_cell_bloc.freezed.dart'; +part 'select_option_cell_bloc.freezed.dart'; -class SelectionCellBloc extends Bloc { +class SelectOptionCellBloc extends Bloc { final GridSelectOptionCellContext cellContext; void Function()? _onCellChangedFn; - SelectionCellBloc({ + SelectOptionCellBloc({ required this.cellContext, - }) : super(SelectionCellState.initial(cellContext)) { - on( + }) : super(SelectOptionCellState.initial(cellContext)) { + on( (event, emit) async { await event.map( initial: (_InitialCell value) async { @@ -44,7 +44,7 @@ class SelectionCellBloc extends Bloc { _onCellChangedFn = cellContext.startListening( onCellChanged: ((selectOptionContext) { if (!isClosed) { - add(SelectionCellEvent.didReceiveOptions( + add(SelectOptionCellEvent.didReceiveOptions( selectOptionContext.options, selectOptionContext.selectOptions, )); @@ -55,25 +55,25 @@ class SelectionCellBloc extends Bloc { } @freezed -class SelectionCellEvent with _$SelectionCellEvent { - const factory SelectionCellEvent.initial() = _InitialCell; - const factory SelectionCellEvent.didReceiveOptions( +class SelectOptionCellEvent with _$SelectOptionCellEvent { + const factory SelectOptionCellEvent.initial() = _InitialCell; + const factory SelectOptionCellEvent.didReceiveOptions( List options, List selectedOptions, ) = _DidReceiveOptions; } @freezed -class SelectionCellState with _$SelectionCellState { - const factory SelectionCellState({ +class SelectOptionCellState with _$SelectOptionCellState { + const factory SelectOptionCellState({ required List options, required List selectedOptions, - }) = _SelectionCellState; + }) = _SelectOptionCellState; - factory SelectionCellState.initial(GridSelectOptionCellContext context) { + factory SelectOptionCellState.initial(GridSelectOptionCellContext context) { final data = context.getCellData(); - return SelectionCellState( + return SelectOptionCellState( options: data?.options ?? [], selectedOptions: data?.selectOptions ?? [], ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart similarity index 97% rename from frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart index cc7af58531..2702e6006f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart @@ -7,14 +7,14 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; import 'select_option_service.dart'; -part 'selection_editor_bloc.freezed.dart'; +part 'select_option_editor_bloc.freezed.dart'; -class SelectOptionEditorBloc extends Bloc { +class SelectOptionCellEditorBloc extends Bloc { final SelectOptionService _selectOptionService; final GridSelectOptionCellContext cellContext; void Function()? _onCellChangedFn; - SelectOptionEditorBloc({ + SelectOptionCellEditorBloc({ required this.cellContext, }) : _selectOptionService = SelectOptionService(gridCell: cellContext.gridCell), super(SelectOptionEditorState.initial(cellContext)) { diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index e06f5d9da8..3a0ebc5112 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -18,7 +18,7 @@ export 'field/type_option/single_select_bloc.dart'; // Cell export 'cell/text_cell_bloc.dart'; export 'cell/number_cell_bloc.dart'; -export 'cell/selection_cell_bloc.dart'; +export 'cell/select_option_cell_bloc.dart'; export 'cell/date_cell_bloc.dart'; export 'cell/checkbox_cell_bloc.dart'; export 'cell/cell_service/cell_service.dart'; 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 7d21cb7e9a..eab2903857 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 @@ -11,7 +11,7 @@ import 'package:styled_widget/styled_widget.dart'; import 'checkbox_cell.dart'; import 'date_cell/date_cell.dart'; import 'number_cell.dart'; -import 'selection_cell/selection_cell.dart'; +import 'select_option_cell/select_option_cell.dart'; import 'text_cell.dart'; GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, {GridCellStyle? style}) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index d1d15ea4b3..5f0ccbc834 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -5,7 +5,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import '../cell_builder.dart'; -import 'calendar.dart'; +import 'date_editor.dart'; class DateCellStyle extends GridCellStyle { Alignment alignment; @@ -77,7 +77,7 @@ class _DateCellState extends State { void _showCalendar(BuildContext context) { final bloc = context.read(); widget.onFocus.value = true; - final calendar = CellCalendar(onDismissed: () => widget.onFocus.value = false); + final calendar = DateCellEditor(onDismissed: () => widget.onFocus.value = false); calendar.show( context, cellContext: bloc.cellContext.clone(), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart similarity index 95% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart index c19e8c3001..abf8288c45 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart @@ -22,10 +22,10 @@ final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day); final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day); const kMargin = EdgeInsets.symmetric(horizontal: 6, vertical: 10); -class CellCalendar with FlowyOverlayDelegate { +class DateCellEditor with FlowyOverlayDelegate { final VoidCallback onDismissed; - const CellCalendar({ + const DateCellEditor({ required this.onDismissed, }); @@ -33,23 +33,14 @@ class CellCalendar with FlowyOverlayDelegate { BuildContext context, { required GridDateCellContext cellContext, }) async { - CellCalendar.remove(context); + DateCellEditor.remove(context); final result = await cellContext.getTypeOptionData(); result.fold( (data) { - final typeOptionData = DateTypeOption.fromBuffer(data); - // DateTime? selectedDay; - // final cellData = cellContext.getCellData(); - - // if (cellData != null) { - // final timestamp = $fixnum.Int64.parseInt(cellData).toInt(); - // selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000); - // } - final calendar = _CellCalendarWidget( cellContext: cellContext, - dateTypeOption: typeOptionData, + dateTypeOption: DateTypeOption.fromBuffer(data), ); FlowyOverlay.of(context).insertWithAnchor( @@ -57,7 +48,7 @@ class CellCalendar with FlowyOverlayDelegate { child: calendar, constraints: BoxConstraints.loose(const Size(320, 500)), ), - identifier: CellCalendar.identifier(), + identifier: DateCellEditor.identifier(), anchorContext: context, anchorDirection: AnchorDirection.leftWithCenterAligned, style: FlowyOverlayStyle(blur: false), @@ -73,7 +64,7 @@ class CellCalendar with FlowyOverlayDelegate { } static String identifier() { - return (CellCalendar).toString(); + return (DateCellEditor).toString(); } @override 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 index 3c7e43ecc0..792e58810f 100644 --- 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 @@ -3,4 +3,4 @@ export 'text_cell.dart'; export 'number_cell.dart'; export 'date_cell/date_cell.dart'; export 'checkbox_cell.dart'; -export 'selection_cell/selection_cell.dart'; +export 'select_option_cell/select_option_cell.dart'; 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/select_option_cell/extension.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.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/select_option_cell/select_option_cell.dart similarity index 90% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart index 0c754b0297..12415c816d 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/select_option_cell/select_option_cell.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'extension.dart'; -import 'selection_editor.dart'; +import 'select_option_editor.dart'; class SelectOptionCellStyle extends GridCellStyle { String placeholder; @@ -41,12 +41,12 @@ class SingleSelectCell extends GridCellWidget { } class _SingleSelectCellState extends State { - late SelectionCellBloc _cellBloc; + late SelectOptionCellBloc _cellBloc; @override void initState() { final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; - _cellBloc = getIt(param1: cellContext)..add(const SelectionCellEvent.initial()); + _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -54,7 +54,7 @@ class _SingleSelectCellState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _cellBloc, - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { return _SelectOptionCell( selectOptions: state.selectedOptions, @@ -95,12 +95,12 @@ class MultiSelectCell extends GridCellWidget { } class _MultiSelectCellState extends State { - late SelectionCellBloc _cellBloc; + late SelectOptionCellBloc _cellBloc; @override void initState() { final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; - _cellBloc = getIt(param1: cellContext)..add(const SelectionCellEvent.initial()); + _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -108,7 +108,7 @@ class _MultiSelectCellState extends State { Widget build(BuildContext context) { return BlocProvider.value( value: _cellBloc, - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { return _SelectOptionCell( selectOptions: state.selectedOptions, 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/select_option_cell/select_option_editor.dart similarity index 89% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index 6e96fccbfb..2effe120c2 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/select_option_cell/select_option_editor.dart @@ -1,8 +1,8 @@ import 'dart:collection'; import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/workspace/application/grid/cell/selection_editor_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/cell/select_option_editor_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/edit_option_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option_editor.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -37,10 +37,10 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => SelectOptionEditorBloc( + create: (context) => SelectOptionCellEditorBloc( cellContext: cellContext, )..add(const SelectOptionEditorEvent.initial()), - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { return CustomScrollView( shrinkWrap: true, @@ -102,7 +102,7 @@ class _OptionList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { List cells = []; cells.addAll(state.options.map((option) { @@ -145,7 +145,7 @@ class _TextField extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { final optionMap = LinkedHashMap.fromIterable(state.selectedOptions, key: (option) => option.name, value: (option) => option); @@ -158,10 +158,10 @@ class _TextField extends StatelessWidget { distanceToText: _editorPannelWidth * 0.7, tagController: _tagController, newText: (text) { - context.read().add(SelectOptionEditorEvent.filterOption(text)); + context.read().add(SelectOptionEditorEvent.filterOption(text)); }, onNewTag: (tagName) { - context.read().add(SelectOptionEditorEvent.newOption(tagName)); + context.read().add(SelectOptionEditorEvent.newOption(tagName)); }, ), ); @@ -230,7 +230,7 @@ class _SelectOptionCell extends StatelessWidget { _body(theme, context), InkWell( onTap: () { - context.read().add(SelectOptionEditorEvent.selectOption(option.id)); + context.read().add(SelectOptionEditorEvent.selectOption(option.id)); }, ), ], @@ -270,17 +270,17 @@ class _SelectOptionCell extends StatelessWidget { } void _showEditPannel(BuildContext context) { - final pannel = EditSelectOptionPannel( + final pannel = SelectOptionTypeOptionEditor( option: option, onDeleted: () { - context.read().add(SelectOptionEditorEvent.deleteOption(option)); + context.read().add(SelectOptionEditorEvent.deleteOption(option)); }, onUpdated: (updatedOption) { - context.read().add(SelectOptionEditorEvent.updateOption(updatedOption)); + context.read().add(SelectOptionEditorEvent.updateOption(updatedOption)); }, key: ValueKey(option.id), // Use ValueKey to refresh the UI, otherwise, it will remain the old value. ); - final overlayIdentifier = (EditSelectOptionPannel).toString(); + final overlayIdentifier = (SelectOptionTypeOptionEditor).toString(); FlowyOverlay.of(context).remove(overlayIdentifier); FlowyOverlay.of(context).insertWithAnchor( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/text_field.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/text_field.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 b5b3ece1a8..397c5e054d 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 @@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'field_option_pannel.dart'; +import 'select_option.dart'; class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { final MultiSelectTypeOptionWidget _widget; @@ -43,18 +43,18 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); }, builder: (context, state) { - return FieldSelectOptionPannel( + return SelectOptionTypeOptionWidget( options: state.typeOption.options, beginEdit: () { overlayDelegate.hideOverlay(context); }, - createOptionCallback: (name) { + createSelectOptionCallback: (name) { context.read().add(MultiSelectTypeOptionEvent.createOption(name)); }, - updateOptionCallback: (updateOption) { + updateSelectOptionCallback: (updateOption) { context.read().add(MultiSelectTypeOptionEvent.updateOption(updateOption)); }, - deleteOptionCallback: (deleteOption) { + deleteSelectOptionCallback: (deleteOption) { context.read().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption)); }, overlayDelegate: overlayDelegate, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart similarity index 82% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index ce6c69d2cd..c00a473b38 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -13,22 +13,22 @@ 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 'select_option_editor.dart'; -class FieldSelectOptionPannel extends StatelessWidget { +class SelectOptionTypeOptionWidget extends StatelessWidget { final List options; final VoidCallback beginEdit; - final Function(String optionName) createOptionCallback; - final Function(SelectOption) updateOptionCallback; - final Function(SelectOption) deleteOptionCallback; + final Function(String optionName) createSelectOptionCallback; + final Function(SelectOption) updateSelectOptionCallback; + final Function(SelectOption) deleteSelectOptionCallback; final TypeOptionOverlayDelegate overlayDelegate; - const FieldSelectOptionPannel({ + const SelectOptionTypeOptionWidget({ required this.options, required this.beginEdit, - required this.createOptionCallback, - required this.updateOptionCallback, - required this.deleteOptionCallback, + required this.createSelectOptionCallback, + required this.updateSelectOptionCallback, + required this.deleteSelectOptionCallback, required this.overlayDelegate, Key? key, }) : super(key: key); @@ -44,17 +44,17 @@ class FieldSelectOptionPannel extends StatelessWidget { } state.newOptionName.fold( () => null, - (optionName) => createOptionCallback(optionName), + (optionName) => createSelectOptionCallback(optionName), ); state.updateOption.fold( () => null, - (updateOption) => updateOptionCallback(updateOption), + (updateOption) => updateSelectOptionCallback(updateOption), ); state.deleteOption.fold( () => null, - (deleteOption) => deleteOptionCallback(deleteOption), + (deleteOption) => deleteSelectOptionCallback(deleteOption), ); }, builder: (context, state) { @@ -86,30 +86,12 @@ class OptionTitle extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = context.watch(); - return BlocBuilder( builder: (context, state) { List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; 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 FieldOptionPannelEvent.beginAddingOption()); - }, - ), - ), - ); + children.add(const _OptionTitleAddOptionButton()); } return SizedBox( @@ -121,6 +103,30 @@ class OptionTitle extends StatelessWidget { } } +class _OptionTitleAddOptionButton extends StatelessWidget { + const _OptionTitleAddOptionButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return 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 FieldOptionPannelEvent.beginAddingOption()); + }, + ), + ); + } +} + class _OptionList extends StatelessWidget { final TypeOptionOverlayDelegate delegate; const _OptionList(this.delegate, {Key? key}) : super(key: key); @@ -155,7 +161,7 @@ class _OptionList extends StatelessWidget { return _OptionCell( option: option, onEdited: (option) { - final pannel = EditSelectOptionPannel( + final pannel = SelectOptionTypeOptionEditor( option: option, onDeleted: () { delegate.hideOverlay(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/select_option_editor.dart similarity index 97% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option_editor.dart index 62c4eca7e5..dada59b41c 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/select_option_editor.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/edit_select_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/extension.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -14,11 +14,11 @@ 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 { +class SelectOptionTypeOptionEditor extends StatelessWidget { final SelectOption option; final VoidCallback onDeleted; final Function(SelectOption) onUpdated; - const EditSelectOptionPannel({ + const SelectOptionTypeOptionEditor({ required this.option, required this.onDeleted, required this.onUpdated, 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 f8cc2293f6..3b84eec495 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 @@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/type_opti import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'field_option_pannel.dart'; +import 'select_option.dart'; class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { final SingleSelectTypeOptionWidget _widget; @@ -42,18 +42,18 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); }, builder: (context, state) { - return FieldSelectOptionPannel( + return SelectOptionTypeOptionWidget( options: state.typeOption.options, beginEdit: () { overlayDelegate.hideOverlay(context); }, - createOptionCallback: (name) { + createSelectOptionCallback: (name) { context.read().add(SingleSelectTypeOptionEvent.createOption(name)); }, - updateOptionCallback: (updateOption) { + updateSelectOptionCallback: (updateOption) { context.read().add(SingleSelectTypeOptionEvent.updateOption(updateOption)); }, - deleteOptionCallback: (deleteOption) { + deleteSelectOptionCallback: (deleteOption) { context.read().add(SingleSelectTypeOptionEvent.deleteOption(deleteOption)); }, overlayDelegate: overlayDelegate, From a59a0af05b37ecee0dc50821f91758f780a8165b Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 17 May 2022 16:57:37 +0800 Subject: [PATCH 2/8] refactor: remove FieldTypeOptionContext --- .../app_flowy/lib/startup/deps_resolver.dart | 6 +- .../cell/cell_service/context_builder.dart | 4 +- .../grid/field/field_action_sheet_bloc.dart | 10 +- .../grid/field/field_cell_bloc.dart | 12 +- .../grid/field/field_editor_bloc.dart | 47 +++--- .../grid/field/field_editor_pannel_bloc.dart | 10 +- .../application/grid/field/field_service.dart | 41 ++--- ...rt => select_option_type_option_bloc.dart} | 33 ++-- .../type_option/type_option_service.dart | 48 +++++- .../widgets/cell/date_cell/date_editor.dart | 2 +- .../grid/src/widgets/header/field_cell.dart | 8 +- .../grid/src/widgets/header/field_editor.dart | 27 ++-- .../widgets/header/field_editor_pannel.dart | 14 +- .../grid/src/widgets/header/grid_header.dart | 2 +- .../header/type_option/multi_select.dart | 2 +- .../header/type_option/select_option.dart | 54 +++---- .../header/type_option/single_select.dart | 2 +- .../grid/src/widgets/row/row_detail.dart | 2 +- .../src/widgets/toolbar/grid_property.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 21 +-- .../flowy-grid-data-model/grid.pb.dart | 68 ++++---- .../flowy-grid-data-model/grid.pbjson.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 | 35 ++--- frontend/rust-lib/flowy-grid/src/event_map.rs | 10 +- .../src/protobuf/model/event_map.rs | 29 ++-- .../src/protobuf/proto/event_map.proto | 5 +- .../src/entities/grid.rs | 7 +- .../src/protobuf/model/grid.rs | 145 ++++++++++++------ .../src/protobuf/proto/grid.proto | 7 +- shared-lib/lib-infra/Cargo.toml | 1 + .../src/code_gen/protobuf_file/mod.rs | 37 ++++- 33 files changed, 401 insertions(+), 320 deletions(-) rename frontend/app_flowy/lib/workspace/application/grid/field/type_option/{field_option_pannel_bloc.dart => select_option_type_option_bloc.dart} (52%) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 1f7f3524fa..7e65130fa8 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -15,7 +15,7 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/home/menu/menu.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' show EditFieldContext; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldTypeOptionData; 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'; @@ -157,7 +157,7 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (gridId, fieldLoader) => FieldEditorBloc( gridId: gridId, fieldLoader: fieldLoader, @@ -195,7 +195,7 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => FieldEditorPannelBloc(context), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart index c7faff5311..4f81e119fc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart @@ -150,8 +150,8 @@ class _GridCellContext extends Equatable { return data; } - Future, FlowyError>> getTypeOptionData() { - return _fieldService.getTypeOptionData(fieldType: fieldType); + Future> getTypeOptionData() { + return _fieldService.getFieldTypeOptionData(fieldType: fieldType); } Future> saveCellData(D data) { diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart index 6513fe85c3..25c9cbfc0d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_action_sheet_bloc.dart @@ -11,7 +11,7 @@ class FieldActionSheetBloc extends Bloc( (event, emit) async { await event.map( @@ -67,14 +67,14 @@ class FieldActionSheetEvent with _$FieldActionSheetEvent { @freezed class FieldActionSheetState with _$FieldActionSheetState { const factory FieldActionSheetState({ - required EditFieldContext editContext, + required FieldTypeOptionData fieldTypeOptionData, required String errorText, required String fieldName, }) = _FieldActionSheetState; - factory FieldActionSheetState.initial(EditFieldContext editContext) => FieldActionSheetState( - editContext: editContext, + factory FieldActionSheetState.initial(FieldTypeOptionData data) => FieldActionSheetState( + fieldTypeOptionData: data, errorText: '', - fieldName: editContext.gridField.name, + fieldName: data.field_2.name, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart index f5fc41e57f..06a95ae89b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart @@ -19,16 +19,16 @@ class FieldCellBloc extends Bloc { super(FieldCellState.initial(cellContext)) { on( (event, emit) async { - await event.map( - initial: (_InitialCell value) async { + event.when( + initial: () { _startListening(); }, - didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(field: value.field)); + didReceiveFieldUpdate: (field) { + emit(state.copyWith(field: field)); }, - updateWidth: (_UpdateWidth value) { + updateWidth: (offset) { final defaultWidth = state.field.width.toDouble(); - final width = defaultWidth + value.offset; + final width = defaultWidth + offset; if (width > defaultWidth && width < 300) { _fieldService.updateField(width: width); } 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 d52fb8c312..db84425f86 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 @@ -12,27 +12,26 @@ part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { final String gridId; - final EditFieldContextLoader _loader; + final FieldContextLoader _loader; FieldEditorBloc({ required this.gridId, - required EditFieldContextLoader fieldLoader, + required FieldContextLoader fieldLoader, }) : _loader = fieldLoader, super(FieldEditorState.initial(gridId)) { on( (event, emit) async { await event.map( initial: (_InitialField value) async { - await _getEditFieldContext(emit); + await _getFieldTypeOptionContext(emit); }, updateName: (_UpdateName value) { final newContext = _updateEditContext(name: value.name); - emit(state.copyWith(editFieldContext: newContext)); + emit(state.copyWith(fieldTypeOptionData: newContext)); }, updateField: (_UpdateField value) { - final newContext = _updateEditContext(field: value.field, typeOptionData: value.typeOptionData); - - emit(state.copyWith(editFieldContext: newContext)); + final data = _updateEditContext(field: value.field, typeOptionData: value.typeOptionData); + emit(state.copyWith(fieldTypeOptionData: data)); }, done: (_Done value) async { await _saveField(emit); @@ -47,26 +46,26 @@ class FieldEditorBloc extends Bloc { return super.close(); } - Option _updateEditContext({ + Option _updateEditContext({ String? name, Field? field, List? typeOptionData, }) { - return state.editFieldContext.fold( + return state.fieldTypeOptionData.fold( () => none(), (context) { context.freeze(); - final newContext = context.rebuild((newContext) { - newContext.gridField.rebuild((newField) { + final newFieldTypeOptionData = context.rebuild((newContext) { + newContext.field_2.rebuild((newField) { if (name != null) { newField.name = name; } - newContext.gridField = newField; + newContext.field_2 = newField; }); if (field != null) { - newContext.gridField = field; + newContext.field_2 = field; } if (typeOptionData != null) { @@ -76,35 +75,35 @@ class FieldEditorBloc extends Bloc { FieldService.insertField( gridId: gridId, - field: newContext.gridField, - typeOptionData: newContext.typeOptionData, + field: newFieldTypeOptionData.field_2, + typeOptionData: newFieldTypeOptionData.typeOptionData, ); - return Some(newContext); + return Some(newFieldTypeOptionData); }, ); } Future _saveField(Emitter emit) async { - await state.editFieldContext.fold( + await state.fieldTypeOptionData.fold( () async => null, - (context) async { + (data) async { final result = await FieldService.insertField( gridId: gridId, - field: context.gridField, - typeOptionData: context.typeOptionData, + field: data.field_2, + typeOptionData: data.typeOptionData, ); result.fold((l) => null, (r) => null); }, ); } - Future _getEditFieldContext(Emitter emit) async { + Future _getFieldTypeOptionContext(Emitter emit) async { final result = await _loader.load(); result.fold( (context) { emit(state.copyWith( - editFieldContext: Some(context), + fieldTypeOptionData: Some(context), )); }, (err) => Log.error(err), @@ -125,12 +124,12 @@ class FieldEditorState with _$FieldEditorState { const factory FieldEditorState({ required String gridId, required String errorText, - required Option editFieldContext, + required Option fieldTypeOptionData, }) = _FieldEditorState; factory FieldEditorState.initial(String gridId) => FieldEditorState( gridId: gridId, - editFieldContext: none(), + fieldTypeOptionData: none(), errorText: '', ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart index 09d0268d63..ea10e4222f 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart @@ -7,7 +7,7 @@ import 'dart:async'; part 'field_editor_pannel_bloc.freezed.dart'; class FieldEditorPannelBloc extends Bloc { - FieldEditorPannelBloc(EditFieldContext editContext) : super(FieldEditorPannelState.initial(editContext)) { + FieldEditorPannelBloc(FieldTypeOptionData editContext) : super(FieldEditorPannelState.initial(editContext)) { on( (event, emit) async { await event.map( @@ -45,9 +45,9 @@ class FieldEditorPannelState with _$FieldEditorPannelState { required Uint8List typeOptionData, }) = _FieldEditorPannelState; - factory FieldEditorPannelState.initial(EditFieldContext context) => FieldEditorPannelState( - gridId: context.gridId, - field: context.gridField, - typeOptionData: Uint8List.fromList(context.typeOptionData), + factory FieldEditorPannelState.initial(FieldTypeOptionData data) => FieldEditorPannelState( + gridId: data.gridId, + field: data.field_2, + typeOptionData: Uint8List.fromList(data.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 70c6caf9f8..a760f13176 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,7 +12,7 @@ class FieldService { FieldService({required this.gridId, required this.fieldId}); - Future> switchToField(FieldType fieldType) { + Future> switchToField(FieldType fieldType) { final payload = EditFieldPayload.create() ..gridId = gridId ..fieldId = fieldId @@ -21,15 +21,6 @@ class FieldService { return GridEventSwitchToField(payload).send(); } - Future> getEditFieldContext(FieldType fieldType) { - final payload = EditFieldPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..fieldType = fieldType; - - return GridEventGetEditFieldContext(payload).send(); - } - Future> moveField(int fromIndex, int toIndex) { final payload = MoveItemPayload.create() ..gridId = gridId @@ -128,7 +119,7 @@ class FieldService { return GridEventDuplicateField(payload).send(); } - Future, FlowyError>> getTypeOptionData({ + Future> getFieldTypeOptionData({ required FieldType fieldType, }) { final payload = EditFieldPayload.create() @@ -137,7 +128,7 @@ class FieldService { ..fieldType = fieldType; return GridEventGetFieldTypeOption(payload).send().then((result) { return result.fold( - (data) => left(data.typeOptionData), + (data) => left(data), (err) => right(err), ); }); @@ -152,58 +143,58 @@ class GridFieldCellContext with _$GridFieldCellContext { }) = _GridFieldCellContext; } -abstract class EditFieldContextLoader { - Future> load(); +abstract class FieldContextLoader { + Future> load(); - Future> switchToField(String fieldId, FieldType fieldType); + Future> switchToField(String fieldId, FieldType fieldType); } -class NewFieldContextLoader extends EditFieldContextLoader { +class NewFieldContextLoader extends FieldContextLoader { final String gridId; NewFieldContextLoader({ required this.gridId, }); @override - Future> load() { + Future> load() { final payload = EditFieldPayload.create() ..gridId = gridId ..fieldType = FieldType.RichText; - return GridEventGetEditFieldContext(payload).send(); + return GridEventGetFieldTypeOption(payload).send(); } @override - Future> switchToField(String fieldId, FieldType fieldType) { + Future> switchToField(String fieldId, FieldType fieldType) { final payload = EditFieldPayload.create() ..gridId = gridId ..fieldType = fieldType; - return GridEventGetEditFieldContext(payload).send(); + return GridEventGetFieldTypeOption(payload).send(); } } -class FieldContextLoaderAdaptor extends EditFieldContextLoader { +class DefaultFieldContextLoader extends FieldContextLoader { final String gridId; final Field field; - FieldContextLoaderAdaptor({ + DefaultFieldContextLoader({ required this.gridId, required this.field, }); @override - Future> load() { + Future> load() { final payload = EditFieldPayload.create() ..gridId = gridId ..fieldId = field.id ..fieldType = field.fieldType; - return GridEventGetEditFieldContext(payload).send(); + return GridEventGetFieldTypeOption(payload).send(); } @override - Future> switchToField(String fieldId, FieldType fieldType) async { + Future> switchToField(String fieldId, FieldType fieldType) async { final fieldService = FieldService(gridId: gridId, fieldId: fieldId); return fieldService.switchToField(fieldType); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart similarity index 52% rename from frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart index 04ae02309d..7e1bf9a0d9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart @@ -3,17 +3,18 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; -part 'field_option_pannel_bloc.freezed.dart'; +part 'select_option_type_option_bloc.freezed.dart'; -class FieldOptionPannelBloc extends Bloc { - FieldOptionPannelBloc({required List options}) : super(FieldOptionPannelState.initial(options)) { - on( +class SelectOptionTypeOptionBloc extends Bloc { + SelectOptionTypeOptionBloc({required List options}) + : super(SelectOptionTyepOptionState.initial(options)) { + on( (event, emit) async { await event.map( createOption: (_CreateOption value) async { - emit(state.copyWith(isEditingOption: false, newOptionName: Some(value.optionName))); + emit(state.copyWith(isEditingOption: true, newOptionName: Some(value.optionName))); }, - beginAddingOption: (_BeginAddingOption value) { + addingOption: (_AddingOption value) { emit(state.copyWith(isEditingOption: true, newOptionName: none())); }, endAddingOption: (_EndAddingOption value) { @@ -37,25 +38,25 @@ class FieldOptionPannelBloc extends Bloc options, required bool isEditingOption, required Option newOptionName, required Option updateOption, required Option deleteOption, - }) = _FieldOptionPannelState; + }) = _SelectOptionTyepOptionState; - factory FieldOptionPannelState.initial(List options) => FieldOptionPannelState( + factory SelectOptionTyepOptionState.initial(List options) => SelectOptionTyepOptionState( options: options, isEditingOption: false, newOptionName: none(), 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 92f2263c5d..c762f14c1d 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 @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; @@ -32,13 +33,58 @@ class TypeOptionService { } } +abstract class TypeOptionDataBuilder { + T fromBuffer(List buffer); +} + class TypeOptionContext { final String gridId; final Field field; final Uint8List data; - const TypeOptionContext({ + + TypeOptionContext({ required this.gridId, required this.field, required this.data, }); } + +abstract class TypeOptionFieldDelegate { + void onFieldChanged(void Function(String) callback); + void dispose(); +} + +class TypeOptionContext2 { + final String gridId; + final Field field; + final FieldService _fieldService; + T? _data; + final TypeOptionDataBuilder dataBuilder; + + TypeOptionContext2({ + required this.gridId, + required this.field, + required this.dataBuilder, + Uint8List? data, + }) : _fieldService = FieldService(gridId: gridId, fieldId: field.id) { + if (data != null) { + _data = dataBuilder.fromBuffer(data); + } + } + + Future> typeOptionData() { + if (_data != null) { + return Future(() => left(_data!)); + } + + return _fieldService.getFieldTypeOptionData(fieldType: field.fieldType).then((result) { + return result.fold( + (data) { + _data = dataBuilder.fromBuffer(data.typeOptionData); + return left(_data!); + }, + (err) => right(err), + ); + }); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart index abf8288c45..016eb00e85 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart @@ -40,7 +40,7 @@ class DateCellEditor with FlowyOverlayDelegate { (data) { final calendar = _CellCalendarWidget( cellContext: cellContext, - dateTypeOption: DateTypeOption.fromBuffer(data), + dateTypeOption: DateTypeOption.fromBuffer(data.typeOptionData), ); FlowyOverlay.of(context).insertWithAnchor( 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 eb264e6664..1e67f4c70b 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 @@ -37,7 +37,7 @@ class GridFieldCell extends StatelessWidget { child: _DragToExpandLine(), ); - return _CellContainer( + return _GridHeaderCellContainer( width: state.field.width.toDouble(), child: Stack( alignment: Alignment.centerRight, @@ -63,7 +63,7 @@ class GridFieldCell extends StatelessWidget { FieldEditor( gridId: state.gridId, - fieldContextLoader: FieldContextLoaderAdaptor( + contextLoader: DefaultFieldContextLoader( gridId: state.gridId, field: state.field, ), @@ -71,10 +71,10 @@ class GridFieldCell extends StatelessWidget { } } -class _CellContainer extends StatelessWidget { +class _GridHeaderCellContainer extends StatelessWidget { final Widget child; final double width; - const _CellContainer({ + const _GridHeaderCellContainer({ required this.child, required this.width, Key? key, 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 11e55e0e06..cc3a12930c 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 @@ -14,12 +14,12 @@ import 'field_editor_pannel.dart'; class FieldEditor extends FlowyOverlayDelegate { final String gridId; final FieldEditorBloc _fieldEditorBloc; - final EditFieldContextLoader fieldContextLoader; + final FieldContextLoader contextLoader; FieldEditor({ required this.gridId, - required this.fieldContextLoader, + required this.contextLoader, Key? key, - }) : _fieldEditorBloc = getIt(param1: gridId, param2: fieldContextLoader) { + }) : _fieldEditorBloc = getIt(param1: gridId, param2: contextLoader) { _fieldEditorBloc.add(const FieldEditorEvent.initial()); } @@ -28,9 +28,10 @@ class FieldEditor extends FlowyOverlayDelegate { AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned, }) { FlowyOverlay.of(context).remove(identifier()); + final child = _FieldEditorPage(_fieldEditorBloc, contextLoader); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: _FieldEditorWidget(_fieldEditorBloc, fieldContextLoader), + child: child, constraints: BoxConstraints.loose(const Size(280, 400)), ), identifier: identifier(), @@ -54,10 +55,10 @@ class FieldEditor extends FlowyOverlayDelegate { bool asBarrier() => true; } -class _FieldEditorWidget extends StatelessWidget { +class _FieldEditorPage extends StatelessWidget { final FieldEditorBloc editorBloc; - final EditFieldContextLoader fieldContextLoader; - const _FieldEditorWidget(this.editorBloc, this.fieldContextLoader, {Key? key}) : super(key: key); + final FieldContextLoader contextLoader; + const _FieldEditorPage(this.editorBloc, this.contextLoader, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -65,9 +66,9 @@ class _FieldEditorWidget extends StatelessWidget { value: editorBloc, child: BlocBuilder( builder: (context, state) { - return state.editFieldContext.fold( + return state.fieldTypeOptionData.fold( () => const SizedBox(), - (editFieldContext) => ListView( + (fieldTypeOptionContext) => ListView( shrinkWrap: true, children: [ FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), @@ -75,9 +76,9 @@ class _FieldEditorWidget extends StatelessWidget { const _FieldNameTextField(), const VSpace(10), FieldEditorPannel( - editFieldContext: editFieldContext, + fieldTypeOptionData: fieldTypeOptionContext, onSwitchToField: (fieldId, fieldType) { - return fieldContextLoader.switchToField(fieldId, fieldType); + return contextLoader.switchToField(fieldId, fieldType); }, onUpdated: (field, typeOptionData) { context.read().add(FieldEditorEvent.updateField(field, typeOptionData)); @@ -99,9 +100,9 @@ class _FieldNameTextField extends StatelessWidget { Widget build(BuildContext context) { return BlocSelector( selector: (state) { - return state.editFieldContext.fold( + return state.fieldTypeOptionData.fold( () => "", - (editFieldContext) => editFieldContext.gridField.name, + (fieldTypeOptionContext) => fieldTypeOptionContext.field_2.name, ); }, builder: (context, name) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index b64cd4ad50..5d96f92655 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -25,18 +25,18 @@ import 'type_option/number.dart'; import 'type_option/single_select.dart'; typedef UpdateFieldCallback = void Function(Field, Uint8List); -typedef SwitchToFieldCallback = Future> Function( +typedef SwitchToFieldCallback = Future> Function( String fieldId, FieldType fieldType, ); class FieldEditorPannel extends StatefulWidget { - final EditFieldContext editFieldContext; + final FieldTypeOptionData fieldTypeOptionData; final UpdateFieldCallback onUpdated; final SwitchToFieldCallback onSwitchToField; const FieldEditorPannel({ - required this.editFieldContext, + required this.fieldTypeOptionData, required this.onUpdated, required this.onSwitchToField, Key? key, @@ -52,7 +52,7 @@ class _FieldEditorPannelState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: widget.editFieldContext), + create: (context) => getIt(param1: widget.fieldTypeOptionData), child: BlocConsumer( listener: (context, state) { widget.onUpdated(state.field, state.typeOptionData); @@ -86,11 +86,11 @@ class _FieldEditorPannelState extends State { final list = FieldTypeList(onSelectField: (newFieldType) { widget.onSwitchToField(field.id, newFieldType).then((result) { result.fold( - (editFieldContext) { + (fieldTypeOptionContext) { context.read().add( FieldEditorPannelEvent.toFieldType( - editFieldContext.gridField, - editFieldContext.typeOptionData, + fieldTypeOptionContext.field_2, + fieldTypeOptionContext.typeOptionData, ), ); }, 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 63a397710c..d7b24b4d8c 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 @@ -150,7 +150,7 @@ class CreateFieldButton extends StatelessWidget { hoverColor: theme.hover, onTap: () => FieldEditor( gridId: gridId, - fieldContextLoader: NewFieldContextLoader(gridId: gridId), + contextLoader: NewFieldContextLoader(gridId: gridId), ).show(context), leftIcon: svgWidget("home/add"), ); 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 397c5e054d..cd2997738c 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 @@ -58,7 +58,7 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { context.read().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption)); }, overlayDelegate: overlayDelegate, - key: ValueKey(state.typeOption.hashCode), + // key: ValueKey(state.typeOption.hashCode), ); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index c00a473b38..a6a76673b3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/select_option_type_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/common/text_field.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; @@ -36,8 +36,8 @@ class SelectOptionTypeOptionWidget extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => FieldOptionPannelBloc(options: options), - child: BlocConsumer( + create: (context) => SelectOptionTypeOptionBloc(options: options), + child: BlocConsumer( listener: (context, state) { if (state.isEditingOption) { beginEdit(); @@ -61,18 +61,10 @@ class SelectOptionTypeOptionWidget extends StatelessWidget { List children = [ const TypeOptionSeparator(), const OptionTitle(), + if (state.isEditingOption) const _CreateOptionTextField(), + if (state.options.isEmpty && !state.isEditingOption) const _AddOptionButton(), + _OptionList(overlayDelegate) ]; - if (state.isEditingOption) { - children.add(const _OptionNameTextField()); - } - - if (state.options.isEmpty && !state.isEditingOption) { - children.add(const _AddOptionButton()); - } - - if (state.options.isNotEmpty) { - children.add(_OptionList(overlayDelegate)); - } return Column(children: children); }, @@ -86,12 +78,12 @@ class OptionTitle extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; if (state.options.isNotEmpty) { children.add(const Spacer()); - children.add(const _OptionTitleAddOptionButton()); + children.add(const _OptionTitleButton()); } return SizedBox( @@ -103,8 +95,8 @@ class OptionTitle extends StatelessWidget { } } -class _OptionTitleAddOptionButton extends StatelessWidget { - const _OptionTitleAddOptionButton({Key? key}) : super(key: key); +class _OptionTitleButton extends StatelessWidget { + const _OptionTitleButton({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -120,7 +112,7 @@ class _OptionTitleAddOptionButton extends StatelessWidget { ), hoverColor: theme.hover, onTap: () { - context.read().add(const FieldOptionPannelEvent.beginAddingOption()); + context.read().add(const SelectOptionTypeOptionEvent.addingOption()); }, ), ); @@ -133,7 +125,7 @@ class _OptionList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( buildWhen: (previous, current) { return previous.options != current.options; }, @@ -160,16 +152,16 @@ class _OptionList extends StatelessWidget { _OptionCell _makeOptionCell(BuildContext context, SelectOption option) { return _OptionCell( option: option, - onEdited: (option) { + onSelected: (option) { final pannel = SelectOptionTypeOptionEditor( option: option, onDeleted: () { delegate.hideOverlay(context); - context.read().add(FieldOptionPannelEvent.deleteOption(option)); + context.read().add(SelectOptionTypeOptionEvent.deleteOption(option)); }, onUpdated: (updatedOption) { delegate.hideOverlay(context); - context.read().add(FieldOptionPannelEvent.updateOption(updatedOption)); + context.read().add(SelectOptionTypeOptionEvent.updateOption(updatedOption)); }, key: ValueKey(option.id), ); @@ -181,10 +173,10 @@ class _OptionList extends StatelessWidget { class _OptionCell extends StatelessWidget { final SelectOption option; - final Function(SelectOption) onEdited; + final Function(SelectOption) onSelected; const _OptionCell({ required this.option, - required this.onEdited, + required this.onSelected, Key? key, }) : super(key: key); @@ -196,7 +188,7 @@ class _OptionCell extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(option.name, fontSize: 12), hoverColor: theme.hover, - onTap: () => onEdited(option), + onTap: () => onSelected(option), rightIcon: svgWidget("grid/details", color: theme.iconColor), ), ); @@ -215,7 +207,7 @@ class _AddOptionButton extends StatelessWidget { text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr(), fontSize: 12), hoverColor: theme.hover, onTap: () { - context.read().add(const FieldOptionPannelEvent.beginAddingOption()); + context.read().add(const SelectOptionTypeOptionEvent.addingOption()); }, leftIcon: svgWidget("home/add", color: theme.iconColor), ), @@ -223,18 +215,18 @@ class _AddOptionButton extends StatelessWidget { } } -class _OptionNameTextField extends StatelessWidget { - const _OptionNameTextField({Key? key}) : super(key: key); +class _CreateOptionTextField extends StatelessWidget { + const _CreateOptionTextField({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return InputTextField( text: "", onCanceled: () { - context.read().add(const FieldOptionPannelEvent.endAddingOption()); + context.read().add(const SelectOptionTypeOptionEvent.endAddingOption()); }, onDone: (optionName) { - context.read().add(FieldOptionPannelEvent.createOption(optionName)); + context.read().add(SelectOptionTypeOptionEvent.createOption(optionName)); }, ); } 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 3b84eec495..11793fbb43 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 @@ -57,7 +57,7 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { context.read().add(SingleSelectTypeOptionEvent.deleteOption(deleteOption)); }, overlayDelegate: overlayDelegate, - key: ValueKey(state.typeOption.hashCode), + // key: ValueKey(state.typeOption.hashCode), ); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index a6f86cafee..474a21773d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -178,7 +178,7 @@ class _RowDetailCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: gridCell.gridId, - fieldContextLoader: FieldContextLoaderAdaptor( + contextLoader: DefaultFieldContextLoader( gridId: gridCell.gridId, field: gridCell.field, ), 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 aa8f88ab5d..151afc1e3f 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 @@ -115,7 +115,7 @@ class _GridPropertyCell extends StatelessWidget { onTap: () { FieldEditor( gridId: gridId, - fieldContextLoader: FieldContextLoaderAdaptor(gridId: gridId, field: field), + contextLoader: DefaultFieldContextLoader(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ); 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 a1208075f5..95c17f46cf 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 @@ -124,14 +124,14 @@ class GridEventSwitchToField { EditFieldPayload request; GridEventSwitchToField(this.request); - Future> send() { + 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)), + (okBytes) => left(FieldTypeOptionData.fromBuffer(okBytes)), (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } @@ -154,23 +154,6 @@ class GridEventDuplicateField { } } -class GridEventGetEditFieldContext { - EditFieldPayload request; - GridEventGetEditFieldContext(this.request); - - Future> send() { - final request = FFIRequest.create() - ..event = GridEvent.GetEditFieldContext.toString() - ..payload = requestToBytes(this.request); - - return Dispatch.asyncRequest(request) - .then((bytesResult) => bytesResult.fold( - (okBytes) => left(EditFieldContext.fromBuffer(okBytes)), - (errBytes) => right(FlowyError.fromBuffer(errBytes)), - )); - } -} - class GridEventMoveItem { MoveItemPayload request; GridEventMoveItem(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 4c18294dae..ae450b2e6d 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 @@ -578,16 +578,16 @@ class EditFieldPayload extends $pb.GeneratedMessage { 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) +class FieldTypeOptionContext extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldTypeOptionContext', 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({ + FieldTypeOptionContext._() : super(); + factory FieldTypeOptionContext({ $core.String? gridId, Field? gridField, $core.List<$core.int>? typeOptionData, @@ -604,26 +604,26 @@ class EditFieldContext extends $pb.GeneratedMessage { } 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); + factory FieldTypeOptionContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FieldTypeOptionContext.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); + FieldTypeOptionContext clone() => FieldTypeOptionContext()..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 + FieldTypeOptionContext copyWith(void Function(FieldTypeOptionContext) updates) => super.copyWith((message) => updates(message as FieldTypeOptionContext)) as FieldTypeOptionContext; // 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(); + static FieldTypeOptionContext create() => FieldTypeOptionContext._(); + FieldTypeOptionContext createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static EditFieldContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static EditFieldContext? _defaultInstance; + static FieldTypeOptionContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FieldTypeOptionContext? _defaultInstance; @$pb.TagNumber(1) $core.String get gridId => $_getSZ(0); @@ -657,19 +657,24 @@ class EditFieldContext extends $pb.GeneratedMessage { class FieldTypeOptionData extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldTypeOptionData', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY) + ..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) ..hasRequiredFields = false ; FieldTypeOptionData._() : super(); factory FieldTypeOptionData({ - $core.String? fieldId, + $core.String? gridId, + Field? field_2, $core.List<$core.int>? typeOptionData, }) { final _result = create(); - if (fieldId != null) { - _result.fieldId = fieldId; + if (gridId != null) { + _result.gridId = gridId; + } + if (field_2 != null) { + _result.field_2 = field_2; } if (typeOptionData != null) { _result.typeOptionData = typeOptionData; @@ -698,22 +703,33 @@ class FieldTypeOptionData extends $pb.GeneratedMessage { static FieldTypeOptionData? _defaultInstance; @$pb.TagNumber(1) - $core.String get fieldId => $_getSZ(0); + $core.String get gridId => $_getSZ(0); @$pb.TagNumber(1) - set fieldId($core.String v) { $_setString(0, v); } + set gridId($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasFieldId() => $_has(0); + $core.bool hasGridId() => $_has(0); @$pb.TagNumber(1) - void clearFieldId() => clearField(1); + void clearGridId() => clearField(1); @$pb.TagNumber(2) - $core.List<$core.int> get typeOptionData => $_getN(1); + Field get field_2 => $_getN(1); @$pb.TagNumber(2) - set typeOptionData($core.List<$core.int> v) { $_setBytes(1, v); } + set field_2(Field v) { setField(2, v); } @$pb.TagNumber(2) - $core.bool hasTypeOptionData() => $_has(1); + $core.bool hasField_2() => $_has(1); @$pb.TagNumber(2) - void clearTypeOptionData() => clearField(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); } class RepeatedField 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 3155b79a2e..78e834edb7 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 @@ -127,9 +127,9 @@ const EditFieldPayload$json = const { /// Descriptor for `EditFieldPayload`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List editFieldPayloadDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIbCghmaWVsZF9pZBgCIAEoCUgAUgdmaWVsZElkEikKCmZpZWxkX3R5cGUYAyABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZUIRCg9vbmVfb2ZfZmllbGRfaWQ='); -@$core.Deprecated('Use editFieldContextDescriptor instead') -const EditFieldContext$json = const { - '1': 'EditFieldContext', +@$core.Deprecated('Use fieldTypeOptionContextDescriptor instead') +const FieldTypeOptionContext$json = const { + '1': 'FieldTypeOptionContext', '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'}, @@ -137,19 +137,20 @@ const EditFieldContext$json = const { ], }; -/// Descriptor for `EditFieldContext`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List editFieldContextDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRDb250ZXh0EhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIlCgpncmlkX2ZpZWxkGAIgASgLMgYuRmllbGRSCWdyaWRGaWVsZBIoChB0eXBlX29wdGlvbl9kYXRhGAMgASgMUg50eXBlT3B0aW9uRGF0YQ=='); +/// Descriptor for `FieldTypeOptionContext`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List fieldTypeOptionContextDescriptor = $convert.base64Decode('ChZGaWVsZFR5cGVPcHRpb25Db250ZXh0EhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIlCgpncmlkX2ZpZWxkGAIgASgLMgYuRmllbGRSCWdyaWRGaWVsZBIoChB0eXBlX29wdGlvbl9kYXRhGAMgASgMUg50eXBlT3B0aW9uRGF0YQ=='); @$core.Deprecated('Use fieldTypeOptionDataDescriptor instead') const FieldTypeOptionData$json = const { '1': 'FieldTypeOptionData', '2': const [ - const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'type_option_data', '3': 2, '4': 1, '5': 12, '10': 'typeOptionData'}, + 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'}, ], }; /// Descriptor for `FieldTypeOptionData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldTypeOptionDataDescriptor = $convert.base64Decode('ChNGaWVsZFR5cGVPcHRpb25EYXRhEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEigKEHR5cGVfb3B0aW9uX2RhdGEYAiABKAxSDnR5cGVPcHRpb25EYXRh'); +final $typed_data.Uint8List fieldTypeOptionDataDescriptor = $convert.base64Decode('ChNGaWVsZFR5cGVPcHRpb25EYXRhEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIcCgVmaWVsZBgCIAEoCzIGLkZpZWxkUgVmaWVsZBIoChB0eXBlX29wdGlvbl9kYXRhGAMgASgMUg50eXBlT3B0aW9uRGF0YQ=='); @$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 0035c0f24d..f9945ab604 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,9 +19,8 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent DeleteField = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField'); static const GridEvent SwitchToField = GridEvent._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SwitchToField'); static const GridEvent DuplicateField = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); - static const GridEvent GetEditFieldContext = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetEditFieldContext'); - static const GridEvent MoveItem = GridEvent._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MoveItem'); - static const GridEvent GetFieldTypeOption = GridEvent._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFieldTypeOption'); + static const GridEvent MoveItem = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MoveItem'); + static const GridEvent GetFieldTypeOption = GridEvent._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFieldTypeOption'); static const GridEvent NewSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewSelectOption'); static const GridEvent GetSelectOptionCellData = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptionCellData'); static const GridEvent UpdateSelectOption = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateSelectOption'); @@ -45,7 +44,6 @@ class GridEvent extends $pb.ProtobufEnum { DeleteField, SwitchToField, DuplicateField, - GetEditFieldContext, MoveItem, GetFieldTypeOption, NewSelectOption, 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 5088625002..89842a54d0 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,9 +21,8 @@ const GridEvent$json = const { const {'1': 'DeleteField', '2': 14}, const {'1': 'SwitchToField', '2': 20}, const {'1': 'DuplicateField', '2': 21}, - const {'1': 'GetEditFieldContext', '2': 22}, - const {'1': 'MoveItem', '2': 23}, - const {'1': 'GetFieldTypeOption', '2': 24}, + const {'1': 'MoveItem', '2': 22}, + const {'1': 'GetFieldTypeOption', '2': 23}, const {'1': 'NewSelectOption', '2': 30}, const {'1': 'GetSelectOptionCellData', '2': 31}, const {'1': 'UpdateSelectOption', '2': 32}, @@ -40,4 +39,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAWEgwKCE1vdmVJdGVtEBcSFgoSR2V0RmllbGRUeXBlT3B0aW9uEBgSEwoPTmV3U2VsZWN0T3B0aW9uEB4SGwoXR2V0U2VsZWN0T3B0aW9uQ2VsbERhdGEQHxIWChJVcGRhdGVTZWxlY3RPcHRpb24QIBINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxINCglEZWxldGVSb3cQNBIQCgxEdXBsaWNhdGVSb3cQNRILCgdHZXRDZWxsEEYSDgoKVXBkYXRlQ2VsbBBHEhoKFlVwZGF0ZVNlbGVjdE9wdGlvbkNlbGwQSBISCg5VcGRhdGVEYXRlQ2VsbBBQEhMKD0dldERhdGVDZWxsRGF0YRBa'); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSDAoITW92ZUl0ZW0QFhIWChJHZXRGaWVsZFR5cGVPcHRpb24QFxITCg9OZXdTZWxlY3RPcHRpb24QHhIbChdHZXRTZWxlY3RPcHRpb25DZWxsRGF0YRAfEhYKElVwZGF0ZVNlbGVjdE9wdGlvbhAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSGgoWVXBkYXRlU2VsZWN0T3B0aW9uQ2VsbBBIEhIKDlVwZGF0ZURhdGVDZWxsEFASEwoPR2V0RGF0ZUNlbGxEYXRhEFo='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 6e34361961..a8c8b99e68 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -98,7 +98,7 @@ pub(crate) async fn delete_field_handler( pub(crate) async fn switch_to_field_handler( data: Data, manager: AppData>, -) -> DataResult { +) -> DataResult { let params: EditFieldParams = data.into_inner().try_into()?; if params.field_id.is_none() { return Err(ErrorCode::FieldIdIsEmpty.into()); @@ -107,9 +107,9 @@ pub(crate) async fn switch_to_field_handler( let editor = manager.get_grid_editor(¶ms.grid_id)?; editor.switch_to_field_type(&field_id, ¶ms.field_type).await?; let field_meta = editor.get_field_meta(&field_id).await; - let edit_context = - make_edit_field_context(¶ms.grid_id, Some(field_id), params.field_type, editor, field_meta).await?; - data_result(edit_context) + let data = + make_field_type_option_data(¶ms.grid_id, Some(field_id), params.field_type, editor, field_meta).await?; + data_result(data) } #[tracing::instrument(level = "debug", skip(data, manager), err)] @@ -123,19 +123,6 @@ pub(crate) async fn duplicate_field_handler( Ok(()) } -#[tracing::instrument(level = "debug", skip(data, manager), err)] -pub(crate) async fn get_field_context_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 = - make_edit_field_context(¶ms.grid_id, params.field_id, params.field_type, editor, None).await?; - - data_result(edit_context) -} - #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_field_type_option_data_handler( data: Data, @@ -147,7 +134,8 @@ pub(crate) async fn get_field_type_option_data_handler( let type_option_data = get_type_option_data(&field_meta, &field_meta.field_type).await?; data_result(FieldTypeOptionData { - field_id: field_meta.id.clone(), + grid_id: params.grid_id, + field: field_meta.into(), type_option_data, }) } @@ -163,23 +151,24 @@ pub(crate) async fn move_item_handler( Ok(()) } -async fn make_edit_field_context( +async fn make_field_type_option_data( grid_id: &str, field_id: Option, field_type: FieldType, editor: Arc, field_meta: Option, -) -> FlowyResult { +) -> FlowyResult { let field_meta = field_meta.unwrap_or(get_or_create_field_meta(field_id, &field_type, editor).await?); let type_option_data = get_type_option_data(&field_meta, &field_type).await?; - let field: Field = field_meta.into(); - Ok(EditFieldContext { + + Ok(FieldTypeOptionData { grid_id: grid_id.to_string(), - grid_field: field, + field: field_meta.into(), type_option_data, }) } +/// The FieldMeta contains multiple data, each of them belongs to a specific FieldType. async fn get_type_option_data(field_meta: &FieldMeta, field_type: &FieldType) -> FlowyResult> { let s = field_meta .get_type_option_str(field_type) diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 2d29d7f096..fe749262ef 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -18,7 +18,6 @@ pub fn create(grid_manager: Arc) -> Module { .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::MoveItem, move_item_handler) .event(GridEvent::GetFieldTypeOption, get_field_type_option_data_handler) // Row @@ -65,20 +64,17 @@ pub enum GridEvent { #[event(input = "FieldIdentifierPayload")] DeleteField = 14, - #[event(input = "EditFieldPayload", output = "EditFieldContext")] + #[event(input = "EditFieldPayload", output = "FieldTypeOptionData")] SwitchToField = 20, #[event(input = "FieldIdentifierPayload")] DuplicateField = 21, - #[event(input = "EditFieldPayload", output = "EditFieldContext")] - GetEditFieldContext = 22, - #[event(input = "MoveItemPayload")] - MoveItem = 23, + MoveItem = 22, #[event(input = "EditFieldPayload", output = "FieldTypeOptionData")] - GetFieldTypeOption = 24, + GetFieldTypeOption = 23, #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] NewSelectOption = 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 bb7494ec3e..f6c4861c29 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,9 +34,8 @@ pub enum GridEvent { DeleteField = 14, SwitchToField = 20, DuplicateField = 21, - GetEditFieldContext = 22, - MoveItem = 23, - GetFieldTypeOption = 24, + MoveItem = 22, + GetFieldTypeOption = 23, NewSelectOption = 30, GetSelectOptionCellData = 31, UpdateSelectOption = 32, @@ -67,9 +66,8 @@ impl ::protobuf::ProtobufEnum for GridEvent { 14 => ::std::option::Option::Some(GridEvent::DeleteField), 20 => ::std::option::Option::Some(GridEvent::SwitchToField), 21 => ::std::option::Option::Some(GridEvent::DuplicateField), - 22 => ::std::option::Option::Some(GridEvent::GetEditFieldContext), - 23 => ::std::option::Option::Some(GridEvent::MoveItem), - 24 => ::std::option::Option::Some(GridEvent::GetFieldTypeOption), + 22 => ::std::option::Option::Some(GridEvent::MoveItem), + 23 => ::std::option::Option::Some(GridEvent::GetFieldTypeOption), 30 => ::std::option::Option::Some(GridEvent::NewSelectOption), 31 => ::std::option::Option::Some(GridEvent::GetSelectOptionCellData), 32 => ::std::option::Option::Some(GridEvent::UpdateSelectOption), @@ -97,7 +95,6 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::DeleteField, GridEvent::SwitchToField, GridEvent::DuplicateField, - GridEvent::GetEditFieldContext, GridEvent::MoveItem, GridEvent::GetFieldTypeOption, GridEvent::NewSelectOption, @@ -140,18 +137,18 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xda\x03\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xc1\x03\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\x19\n\x15UpdateFieldTypeOption\x10\x0c\x12\ \x0f\n\x0bInsertField\x10\r\x12\x0f\n\x0bDeleteField\x10\x0e\x12\x11\n\r\ - SwitchToField\x10\x14\x12\x12\n\x0eDuplicateField\x10\x15\x12\x17\n\x13G\ - etEditFieldContext\x10\x16\x12\x0c\n\x08MoveItem\x10\x17\x12\x16\n\x12Ge\ - tFieldTypeOption\x10\x18\x12\x13\n\x0fNewSelectOption\x10\x1e\x12\x1b\n\ - \x17GetSelectOptionCellData\x10\x1f\x12\x16\n\x12UpdateSelectOption\x10\ - \x20\x12\r\n\tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\r\n\tDeleteRow\ - \x104\x12\x10\n\x0cDuplicateRow\x105\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\ - \nUpdateCell\x10G\x12\x1a\n\x16UpdateSelectOptionCell\x10H\x12\x12\n\x0e\ - UpdateDateCell\x10P\x12\x13\n\x0fGetDateCellData\x10Zb\x06proto3\ + SwitchToField\x10\x14\x12\x12\n\x0eDuplicateField\x10\x15\x12\x0c\n\x08M\ + oveItem\x10\x16\x12\x16\n\x12GetFieldTypeOption\x10\x17\x12\x13\n\x0fNew\ + SelectOption\x10\x1e\x12\x1b\n\x17GetSelectOptionCellData\x10\x1f\x12\ + \x16\n\x12UpdateSelectOption\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\x06\ + GetRow\x103\x12\r\n\tDeleteRow\x104\x12\x10\n\x0cDuplicateRow\x105\x12\ + \x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\x1a\n\x16UpdateSel\ + ectOptionCell\x10H\x12\x12\n\x0eUpdateDateCell\x10P\x12\x13\n\x0fGetDate\ + CellData\x10Zb\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 02f621b29e..a0c88a7187 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,9 +10,8 @@ enum GridEvent { DeleteField = 14; SwitchToField = 20; DuplicateField = 21; - GetEditFieldContext = 22; - MoveItem = 23; - GetFieldTypeOption = 24; + MoveItem = 22; + GetFieldTypeOption = 23; NewSelectOption = 30; GetSelectOptionCellData = 31; UpdateSelectOption = 32; 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 0dae40658c..ccbaff82e9 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -195,7 +195,7 @@ impl TryInto for EditFieldPayload { } #[derive(Debug, Default, ProtoBuf)] -pub struct EditFieldContext { +pub struct FieldTypeOptionContext { #[pb(index = 1)] pub grid_id: String, @@ -209,9 +209,12 @@ pub struct EditFieldContext { #[derive(Debug, Default, ProtoBuf)] pub struct FieldTypeOptionData { #[pb(index = 1)] - pub field_id: String, + pub grid_id: String, #[pb(index = 2)] + pub field_id: String, + + #[pb(index = 3)] pub type_option_data: Vec, } 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 614d0e8b21..c0c03f65a7 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 @@ -1913,7 +1913,7 @@ impl ::protobuf::reflect::ProtobufValue for EditFieldPayload { } #[derive(PartialEq,Clone,Default)] -pub struct EditFieldContext { +pub struct FieldTypeOptionContext { // message fields pub grid_id: ::std::string::String, pub grid_field: ::protobuf::SingularPtrField, @@ -1923,14 +1923,14 @@ pub struct EditFieldContext { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a EditFieldContext { - fn default() -> &'a EditFieldContext { - ::default_instance() +impl<'a> ::std::default::Default for &'a FieldTypeOptionContext { + fn default() -> &'a FieldTypeOptionContext { + ::default_instance() } } -impl EditFieldContext { - pub fn new() -> EditFieldContext { +impl FieldTypeOptionContext { + pub fn new() -> FieldTypeOptionContext { ::std::default::Default::default() } @@ -2020,7 +2020,7 @@ impl EditFieldContext { } } -impl ::protobuf::Message for EditFieldContext { +impl ::protobuf::Message for FieldTypeOptionContext { fn is_initialized(&self) -> bool { for v in &self.grid_field { if !v.is_initialized() { @@ -2112,8 +2112,8 @@ impl ::protobuf::Message for EditFieldContext { Self::descriptor_static() } - fn new() -> EditFieldContext { - EditFieldContext::new() + fn new() -> FieldTypeOptionContext { + FieldTypeOptionContext::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -2122,34 +2122,34 @@ impl ::protobuf::Message for EditFieldContext { 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 }, + |m: &FieldTypeOptionContext| { &m.grid_id }, + |m: &mut FieldTypeOptionContext| { &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 }, + |m: &FieldTypeOptionContext| { &m.grid_field }, + |m: &mut FieldTypeOptionContext| { &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 }, + |m: &FieldTypeOptionContext| { &m.type_option_data }, + |m: &mut FieldTypeOptionContext| { &mut m.type_option_data }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "EditFieldContext", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FieldTypeOptionContext", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static EditFieldContext { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(EditFieldContext::new) + fn default_instance() -> &'static FieldTypeOptionContext { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FieldTypeOptionContext::new) } } -impl ::protobuf::Clear for EditFieldContext { +impl ::protobuf::Clear for FieldTypeOptionContext { fn clear(&mut self) { self.grid_id.clear(); self.grid_field.clear(); @@ -2158,13 +2158,13 @@ impl ::protobuf::Clear for EditFieldContext { } } -impl ::std::fmt::Debug for EditFieldContext { +impl ::std::fmt::Debug for FieldTypeOptionContext { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for EditFieldContext { +impl ::protobuf::reflect::ProtobufValue for FieldTypeOptionContext { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -2173,6 +2173,7 @@ impl ::protobuf::reflect::ProtobufValue for EditFieldContext { #[derive(PartialEq,Clone,Default)] pub struct FieldTypeOptionData { // message fields + pub grid_id: ::std::string::String, pub field_id: ::std::string::String, pub type_option_data: ::std::vec::Vec, // special fields @@ -2191,7 +2192,33 @@ impl FieldTypeOptionData { ::std::default::Default::default() } - // string field_id = 1; + // 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 { @@ -2217,7 +2244,7 @@ impl FieldTypeOptionData { ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) } - // bytes type_option_data = 2; + // bytes type_option_data = 3; pub fn get_type_option_data(&self) -> &[u8] { @@ -2254,9 +2281,12 @@ impl ::protobuf::Message for FieldTypeOptionData { 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)?; + ::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_bytes_into(wire_type, is, &mut self.type_option_data)?; }, _ => { @@ -2271,11 +2301,14 @@ impl ::protobuf::Message for FieldTypeOptionData { #[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(1, &self.field_id); + my_size += ::protobuf::rt::string_size(2, &self.field_id); } if !self.type_option_data.is_empty() { - my_size += ::protobuf::rt::bytes_size(2, &self.type_option_data); + 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); @@ -2283,11 +2316,14 @@ impl ::protobuf::Message for FieldTypeOptionData { } 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(1, &self.field_id)?; + os.write_string(2, &self.field_id)?; } if !self.type_option_data.is_empty() { - os.write_bytes(2, &self.type_option_data)?; + os.write_bytes(3, &self.type_option_data)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -2327,6 +2363,11 @@ impl ::protobuf::Message for FieldTypeOptionData { 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: &FieldTypeOptionData| { &m.grid_id }, + |m: &mut FieldTypeOptionData| { &mut m.grid_id }, + )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", |m: &FieldTypeOptionData| { &m.field_id }, @@ -2353,6 +2394,7 @@ impl ::protobuf::Message for FieldTypeOptionData { impl ::protobuf::Clear for FieldTypeOptionData { fn clear(&mut self) { + self.grid_id.clear(); self.field_id.clear(); self.type_option_data.clear(); self.unknown_fields.clear(); @@ -8257,27 +8299,28 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x86\x01\n\x10EditFieldPayload\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\x0fo\ - ne_of_field_id\"|\n\x10EditFieldContext\x12\x17\n\x07grid_id\x18\x01\x20\ - \x01(\tR\x06gridId\x12%\n\ngrid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\t\ - gridField\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOption\ - Data\"Z\n\x13FieldTypeOptionData\x12\x19\n\x08field_id\x18\x01\x20\x01(\ - \tR\x07fieldId\x12(\n\x10type_option_data\x18\x02\x20\x01(\x0cR\x0etypeO\ - ptionData\"-\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\x08RowOrder\x12\x15\n\x06ro\ - w_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_b\ - y_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFiel\ - dId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellBy\ - FieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05va\ - lue\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedR\ - ow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11Re\ - peatedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\ - \x05items\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\ - \tR\x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trow\ - Orders\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.Row\ - OrderR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\ + ne_of_field_id\"\x82\x01\n\x16FieldTypeOptionContext\x12\x17\n\x07grid_i\ + d\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\"s\n\x13FieldTypeOptionData\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07\ + fieldId\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionDa\ + ta\"-\n\rRepeatedField\x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.Fiel\ + dR\x05items\"7\n\x12RepeatedFieldOrder\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\x07b\ + lockId\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_fiel\ + d_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\ + \x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFie\ + ldIdEntry\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\x11Repe\ + atedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05i\ + tems\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\ + \x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrd\ + ers\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrd\ + erR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\ \x0e\n\x0cone_of_index\"Q\n\x0fUpdatedRowOrder\x12&\n\trow_order\x18\x01\ \x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x03row\x18\x02\x20\x01(\ \x0b2\x04.RowR\x03row\"\xc6\x01\n\x11GridRowsChangeset\x12\x19\n\x08bloc\ 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 5913b0ca0e..c1aa74b0e7 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 @@ -38,14 +38,15 @@ message EditFieldPayload { oneof one_of_field_id { string field_id = 2; }; FieldType field_type = 3; } -message EditFieldContext { +message FieldTypeOptionContext { string grid_id = 1; Field grid_field = 2; bytes type_option_data = 3; } message FieldTypeOptionData { - string field_id = 1; - bytes type_option_data = 2; + string grid_id = 1; + string field_id = 2; + bytes type_option_data = 3; } message RepeatedField { repeated Field items = 1; diff --git a/shared-lib/lib-infra/Cargo.toml b/shared-lib/lib-infra/Cargo.toml index 9659490959..8b74a68a4c 100644 --- a/shared-lib/lib-infra/Cargo.toml +++ b/shared-lib/lib-infra/Cargo.toml @@ -16,6 +16,7 @@ rand = "0.8.5" serde = { version = "1.0", features = ["derive"]} serde_json = "1.0" + cmd_lib = { version = "1", optional = true } protoc-rust = { version = "2", optional = true } walkdir = { version = "2", optional = true } diff --git a/shared-lib/lib-infra/src/code_gen/protobuf_file/mod.rs b/shared-lib/lib-infra/src/code_gen/protobuf_file/mod.rs index ff1f5fa5f5..a65d4d5bd9 100644 --- a/shared-lib/lib-infra/src/code_gen/protobuf_file/mod.rs +++ b/shared-lib/lib-infra/src/code_gen/protobuf_file/mod.rs @@ -7,6 +7,7 @@ mod proto_info; mod template; use crate::code_gen::util::path_string_with_component; +use itertools::Itertools; use log::info; pub use proto_gen::*; pub use proto_info::*; @@ -132,7 +133,7 @@ fn generate_dart_protobuf_files( } } -fn check_pb_dart_plugin() { +pub fn check_pb_dart_plugin() { if cfg!(target_os = "windows") { //Command::new("cmd") // .arg("/C") @@ -141,15 +142,39 @@ fn check_pb_dart_plugin() { // .expect("failed to execute process"); //panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly.")) } else { - let is_success = Command::new("sh") + let exit_result = Command::new("sh") .arg("-c") .arg("command -v protoc-gen-dart") .status() - .expect("failed to execute process") - .success(); + .expect("failed to execute process"); - if !is_success { - panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly. \n✅ You can fix that by adding \"{}\" to your shell's config file.(.bashrc, .bash, etc.)", "dart pub global activate protoc_plugin")) + if !exit_result.success() { + let mut msg = "\n❌ Can't find protoc-gen-dart in $PATH:\n".to_string(); + let output = Command::new("sh").arg("-c").arg("echo $PATH").output(); + let paths = String::from_utf8(output.unwrap().stdout) + .unwrap() + .split(":") + .map(|s| s.to_string()) + .collect::>(); + + paths.iter().for_each(|s| msg.push_str(&format!("{}\n", s))); + + match Command::new("sh").arg("-c").arg("which protoc-gen-dart").output() { + Ok(output) => { + msg.push_str(&format!( + "Installed protoc-gen-dart path: {:?}\n", + String::from_utf8(output.stdout).unwrap() + )); + } + Err(_) => {} + } + + msg.push_str(&format!("✅ You can fix that by adding:")); + msg.push_str(&format!("\n\texport PATH=\"$PATH\":\"$HOME/.pub-cache/bin\"\n",)); + msg.push_str(&format!( + "to your shell's config file.(.bashrc, .bash, .profile, .zshrc etc.)" + )); + panic!("{}", msg) } } } From 4840d23fff6793bd0e4344b68b76600ae91924c5 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 18 May 2022 15:43:10 +0800 Subject: [PATCH 3/8] chore: add GridFieldContext --- .../app_flowy/lib/startup/deps_resolver.dart | 12 -- .../cell/cell_service/context_builder.dart | 15 ++- .../grid/cell/cell_service/data_loader.dart | 37 +++--- .../grid/field/field_editor_bloc.dart | 115 ++++-------------- .../grid/field/field_editor_pannel_bloc.dart | 40 +++--- .../application/grid/field/field_service.dart | 111 +++++++++++++++++ .../type_option/type_option_service.dart | 16 +-- .../select_option_editor.dart | 70 ++++++----- .../grid/src/widgets/header/field_cell.dart | 1 + .../grid/src/widgets/header/field_editor.dart | 99 +++++++-------- .../widgets/header/field_editor_pannel.dart | 41 ++----- .../grid/src/widgets/header/grid_header.dart | 1 + .../grid/src/widgets/row/row_detail.dart | 1 + .../src/widgets/toolbar/grid_property.dart | 1 + .../lib/style_widget/hover.dart | 13 +- .../src/entities/grid.rs | 2 +- .../src/protobuf/model/grid.rs | 97 ++++++++------- .../src/protobuf/proto/grid.proto | 2 +- 18 files changed, 351 insertions(+), 323 deletions(-) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 7e65130fa8..698cc63531 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -15,7 +15,6 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/home/menu/menu.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' show FieldTypeOptionData; 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'; @@ -157,13 +156,6 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (gridId, fieldLoader) => FieldEditorBloc( - gridId: gridId, - fieldLoader: fieldLoader, - ), - ); - getIt.registerFactoryParam( (context, _) => TextCellBloc( cellContext: context, @@ -195,10 +187,6 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => FieldEditorPannelBloc(context), - ); - getIt.registerFactoryParam( (typeOption, _) => DateTypeOptionBloc(typeOption: typeOption), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart index 4f81e119fc..ed191c7d60 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart @@ -19,7 +19,7 @@ class GridCellContextBuilder { return GridCellContext( gridCell: _gridCell, cellCache: _cellCache, - cellDataLoader: CellDataLoader(gridCell: _gridCell), + cellDataLoader: GridCellDataLoader(gridCell: _gridCell), cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.DateTime: @@ -30,17 +30,24 @@ class GridCellContextBuilder { cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell), ); case FieldType.Number: + final cellDataLoader = GridCellDataLoader( + gridCell: _gridCell, + config: const GridCellDataConfig( + reloadOnCellChanged: true, + reloadOnFieldChanged: true, + ), + ); return GridCellContext( gridCell: _gridCell, cellCache: _cellCache, - cellDataLoader: CellDataLoader(gridCell: _gridCell, reloadOnCellChanged: true), + cellDataLoader: cellDataLoader, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.RichText: return GridCellContext( gridCell: _gridCell, cellCache: _cellCache, - cellDataLoader: CellDataLoader(gridCell: _gridCell), + cellDataLoader: GridCellDataLoader(gridCell: _gridCell), cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.MultiSelect: @@ -62,7 +69,7 @@ class _GridCellContext extends Equatable { final GridCell gridCell; final GridCellCache cellCache; final GridCellCacheKey _cacheKey; - final _GridCellDataLoader cellDataLoader; + final IGridCellDataLoader cellDataLoader; final _GridCellDataPersistence cellDataPersistence; final FieldService _fieldService; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart index f625af9ad0..5be0435323 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart @@ -1,6 +1,6 @@ part of 'cell_service.dart'; -abstract class GridCellDataConfig { +abstract class IGridCellDataConfig { // The cell data will reload if it receives the field's change notification. bool get reloadOnFieldChanged; @@ -11,34 +11,36 @@ abstract class GridCellDataConfig { bool get reloadOnCellChanged; } -class DefaultCellDataConfig implements GridCellDataConfig { +class GridCellDataConfig implements IGridCellDataConfig { @override final bool reloadOnCellChanged; @override final bool reloadOnFieldChanged; - DefaultCellDataConfig({ + const GridCellDataConfig({ this.reloadOnCellChanged = false, this.reloadOnFieldChanged = false, }); } -abstract class _GridCellDataLoader { +abstract class IGridCellDataLoader { Future loadData(); - GridCellDataConfig get config; + IGridCellDataConfig get config; } -class CellDataLoader extends _GridCellDataLoader { +class GridCellDataLoader extends IGridCellDataLoader { final CellService service = CellService(); final GridCell gridCell; - final GridCellDataConfig _config; - CellDataLoader({ + @override + final IGridCellDataConfig config; + + GridCellDataLoader({ required this.gridCell, - bool reloadOnCellChanged = false, - }) : _config = DefaultCellDataConfig(reloadOnCellChanged: reloadOnCellChanged); + this.config = const GridCellDataConfig(), + }); @override Future loadData() { @@ -54,20 +56,17 @@ class CellDataLoader extends _GridCellDataLoader { }); }); } - - @override - GridCellDataConfig get config => _config; } -class DateCellDataLoader extends _GridCellDataLoader { +class DateCellDataLoader extends IGridCellDataLoader { final GridCell gridCell; - final GridCellDataConfig _config; + final IGridCellDataConfig _config; DateCellDataLoader({ required this.gridCell, - }) : _config = DefaultCellDataConfig(reloadOnFieldChanged: true); + }) : _config = const GridCellDataConfig(reloadOnFieldChanged: true); @override - GridCellDataConfig get config => _config; + IGridCellDataConfig get config => _config; @override Future loadData() { @@ -88,7 +87,7 @@ class DateCellDataLoader extends _GridCellDataLoader { } } -class SelectOptionCellDataLoader extends _GridCellDataLoader { +class SelectOptionCellDataLoader extends IGridCellDataLoader { final SelectOptionService service; final GridCell gridCell; SelectOptionCellDataLoader({ @@ -108,5 +107,5 @@ class SelectOptionCellDataLoader extends _GridCellDataLoader DefaultCellDataConfig(); + IGridCellDataConfig get config => const GridCellDataConfig(reloadOnFieldChanged: true); } 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 db84425f86..ba2c25fec6 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 @@ -1,40 +1,31 @@ -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'; -import 'package:protobuf/protobuf.dart'; - part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { - final String gridId; - final FieldContextLoader _loader; - FieldEditorBloc({ - required this.gridId, - required FieldContextLoader fieldLoader, - }) : _loader = fieldLoader, - super(FieldEditorState.initial(gridId)) { + required String gridId, + required String fieldName, + required FieldContextLoader fieldContextLoader, + }) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) { on( (event, emit) async { - await event.map( - initial: (_InitialField value) async { - await _getFieldTypeOptionContext(emit); + await event.when( + initial: () async { + final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader); + await fieldContext.loadData().then((result) { + result.fold( + (l) => emit(state.copyWith(fieldContext: Some(fieldContext))), + (r) => null, + ); + }); }, - updateName: (_UpdateName value) { - final newContext = _updateEditContext(name: value.name); - emit(state.copyWith(fieldTypeOptionData: newContext)); - }, - updateField: (_UpdateField value) { - final data = _updateEditContext(field: value.field, typeOptionData: value.typeOptionData); - emit(state.copyWith(fieldTypeOptionData: data)); - }, - done: (_Done value) async { - await _saveField(emit); + updateName: (name) { + state.fieldContext.fold(() => null, (fieldContext) => fieldContext.fieldName = name); + emit(state.copyWith(name: name)); }, ); }, @@ -45,78 +36,12 @@ class FieldEditorBloc extends Bloc { Future close() async { return super.close(); } - - Option _updateEditContext({ - String? name, - Field? field, - List? typeOptionData, - }) { - return state.fieldTypeOptionData.fold( - () => none(), - (context) { - context.freeze(); - final newFieldTypeOptionData = context.rebuild((newContext) { - newContext.field_2.rebuild((newField) { - if (name != null) { - newField.name = name; - } - - newContext.field_2 = newField; - }); - - if (field != null) { - newContext.field_2 = field; - } - - if (typeOptionData != null) { - newContext.typeOptionData = typeOptionData; - } - }); - - FieldService.insertField( - gridId: gridId, - field: newFieldTypeOptionData.field_2, - typeOptionData: newFieldTypeOptionData.typeOptionData, - ); - - return Some(newFieldTypeOptionData); - }, - ); - } - - Future _saveField(Emitter emit) async { - await state.fieldTypeOptionData.fold( - () async => null, - (data) async { - final result = await FieldService.insertField( - gridId: gridId, - field: data.field_2, - typeOptionData: data.typeOptionData, - ); - result.fold((l) => null, (r) => null); - }, - ); - } - - Future _getFieldTypeOptionContext(Emitter emit) async { - final result = await _loader.load(); - result.fold( - (context) { - emit(state.copyWith( - fieldTypeOptionData: Some(context), - )); - }, - (err) => Log.error(err), - ); - } } @freezed class FieldEditorEvent with _$FieldEditorEvent { const factory FieldEditorEvent.initial() = _InitialField; const factory FieldEditorEvent.updateName(String name) = _UpdateName; - const factory FieldEditorEvent.updateField(Field field, Uint8List typeOptionData) = _UpdateField; - const factory FieldEditorEvent.done() = _Done; } @freezed @@ -124,12 +49,14 @@ class FieldEditorState with _$FieldEditorState { const factory FieldEditorState({ required String gridId, required String errorText, - required Option fieldTypeOptionData, + required String name, + required Option fieldContext, }) = _FieldEditorState; - factory FieldEditorState.initial(String gridId) => FieldEditorState( + factory FieldEditorState.initial(String gridId, String fieldName, FieldContextLoader loader) => FieldEditorState( gridId: gridId, - fieldTypeOptionData: none(), + fieldContext: none(), errorText: '', + name: fieldName, ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart index ea10e4222f..c6d48c9d18 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart @@ -1,24 +1,29 @@ -import 'dart:typed_data'; 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_editor_pannel_bloc.freezed.dart'; class FieldEditorPannelBloc extends Bloc { - FieldEditorPannelBloc(FieldTypeOptionData editContext) : super(FieldEditorPannelState.initial(editContext)) { + final GridFieldContext _fieldContext; + void Function()? _fieldListenFn; + + FieldEditorPannelBloc(GridFieldContext fieldContext) + : _fieldContext = fieldContext, + super(FieldEditorPannelState.initial(fieldContext)) { on( (event, emit) async { - await event.map( - toFieldType: (_ToFieldType value) async { - emit(state.copyWith( - field: value.field, - typeOptionData: Uint8List.fromList(value.typeOptionData), - )); + event.when( + initial: () { + _fieldListenFn = fieldContext.addFieldListener((field) { + add(FieldEditorPannelEvent.didReceiveFieldUpdated(field)); + }); }, - didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) { - emit(state.copyWith(typeOptionData: value.typeOptionData)); + didReceiveFieldUpdated: (field) { + emit(state.copyWith(field: field)); }, ); }, @@ -27,27 +32,26 @@ class FieldEditorPannelBloc extends Bloc close() async { + if (_fieldListenFn != null) { + _fieldContext.removeFieldListener(_fieldListenFn!); + } return super.close(); } } @freezed class FieldEditorPannelEvent with _$FieldEditorPannelEvent { - const factory FieldEditorPannelEvent.toFieldType(Field field, List typeOptionData) = _ToFieldType; - const factory FieldEditorPannelEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData; + const factory FieldEditorPannelEvent.initial() = _Initial; + const factory FieldEditorPannelEvent.didReceiveFieldUpdated(Field field) = _DidReceiveFieldUpdated; } @freezed class FieldEditorPannelState with _$FieldEditorPannelState { const factory FieldEditorPannelState({ - required String gridId, required Field field, - required Uint8List typeOptionData, }) = _FieldEditorPannelState; - factory FieldEditorPannelState.initial(FieldTypeOptionData data) => FieldEditorPannelState( - gridId: data.gridId, - field: data.field_2, - typeOptionData: Uint8List.fromList(data.typeOptionData), + factory FieldEditorPannelState.initial(GridFieldContext fieldContext) => FieldEditorPannelState( + field: fieldContext.field, ); } 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 a760f13176..03f27dffe7 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,9 +1,12 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.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/field_entities.pb.dart'; +import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:protobuf/protobuf.dart'; part 'field_service.freezed.dart'; class FieldService { @@ -199,3 +202,111 @@ class DefaultFieldContextLoader extends FieldContextLoader { return fieldService.switchToField(fieldType); } } + +class GridFieldContext { + final String gridId; + final FieldContextLoader _loader; + + late FieldTypeOptionData _data; + ValueNotifier? _fieldNotifier; + + GridFieldContext({ + required this.gridId, + required FieldContextLoader loader, + }) : _loader = loader; + + Future> loadData() async { + final result = await _loader.load(); + return result.fold( + (data) { + data.freeze(); + _data = data; + + if (_fieldNotifier == null) { + _fieldNotifier = ValueNotifier(data.field_2); + } else { + _fieldNotifier?.value = data.field_2; + } + + return left(unit); + }, + (err) { + Log.error(err); + return right(err); + }, + ); + } + + Field get field => _data.field_2; + + set field(Field field) { + _updateData(newField: field); + } + + List get typeOptionData => _data.typeOptionData; + + set fieldName(String name) { + _updateData(name: name); + } + + set typeOptionData(List typeOptionData) { + _updateData(typeOptionData: typeOptionData); + } + + void _updateData({String? name, Field? newField, List? typeOptionData}) { + _data = _data.rebuild((rebuildData) { + if (name != null) { + rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) { + rebuildField.name = name; + }); + } + + if (newField != null) { + rebuildData.field_2 = newField; + } + + if (typeOptionData != null) { + rebuildData.typeOptionData = typeOptionData; + } + }); + + if (_data.field_2 != _fieldNotifier?.value) { + _fieldNotifier?.value = _data.field_2; + } + + FieldService.insertField( + gridId: gridId, + field: field, + typeOptionData: typeOptionData, + ); + } + + Future switchToField(FieldType newFieldType) { + return _loader.switchToField(field.id, newFieldType).then((result) { + return result.fold( + (fieldTypeOptionData) { + _updateData( + newField: fieldTypeOptionData.field_2, + typeOptionData: fieldTypeOptionData.typeOptionData, + ); + }, + (err) { + Log.error(err); + }, + ); + }); + } + + void Function() addFieldListener(void Function(Field) callback) { + listener() { + callback(field); + } + + _fieldNotifier?.addListener(listener); + return listener; + } + + void removeFieldListener(void Function() listener) { + _fieldNotifier?.removeListener(listener); + } +} 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 c762f14c1d..cf9b69780d 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 @@ -38,15 +38,17 @@ abstract class TypeOptionDataBuilder { } class TypeOptionContext { - final String gridId; - final Field field; - final Uint8List data; + final GridFieldContext _fieldContext; TypeOptionContext({ - required this.gridId, - required this.field, - required this.data, - }); + required GridFieldContext fieldContext, + }) : _fieldContext = fieldContext; + + String get gridId => _fieldContext.gridId; + + Field get field => _fieldContext.field; + + Uint8List get data => Uint8List.fromList(_fieldContext.typeOptionData); } abstract class TypeOptionFieldDelegate { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index 2effe120c2..14e1ee3d33 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart @@ -224,48 +224,46 @@ class _SelectOptionCell extends StatelessWidget { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, - child: Stack( - fit: StackFit.expand, + child: Row( children: [ - _body(theme, context), - InkWell( - onTap: () { - context.read().add(SelectOptionEditorEvent.selectOption(option.id)); - }, - ), + Expanded(child: _body(theme, context)), + FlowyIconButton( + width: 30, + onPressed: () => _showEditPannel(context), + iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), + icon: svgWidget("editor/details", color: theme.iconColor), + ) ], ), ); } - FlowyHover _body(AppTheme theme, BuildContext context) { - return FlowyHover( - style: HoverStyle(hoverColor: theme.hover), - builder: (_, onHover) { - List children = [ - SelectOptionTag( - name: option.name, - color: option.color.make(context), - isSelected: isSelected, - ), - const Spacer(), - ]; - - if (isSelected) { - children.add(svgWidget("grid/checkmark")); - } - - if (onHover) { - children.add(FlowyIconButton( - width: 30, - onPressed: () => _showEditPannel(context), - iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), - icon: svgWidget("editor/details", color: theme.iconColor), - )); - } - - return Row(children: children); - }, + Widget _body(AppTheme theme, BuildContext context) { + return Stack( + fit: StackFit.expand, + children: [ + FlowyHover( + style: HoverStyle(hoverColor: theme.hover), + builder: (_, onHover) { + return InkWell( + child: Row(children: [ + const HSpace(6), + SelectOptionTag( + name: option.name, + color: option.color.make(context), + isSelected: isSelected, + ), + const Spacer(), + if (isSelected) svgWidget("grid/checkmark"), + const HSpace(6), + ]), + onTap: () { + context.read().add(SelectOptionEditorEvent.selectOption(option.id)); + }, + ); + }, + ), + ], ); } 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 1e67f4c70b..9eec395ce0 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 @@ -63,6 +63,7 @@ class GridFieldCell extends StatelessWidget { FieldEditor( gridId: state.gridId, + fieldName: state.field.name, contextLoader: DefaultFieldContextLoader( gridId: state.gridId, field: state.field, 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 cc3a12930c..b3d96949f0 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,4 +1,3 @@ -import 'package:app_flowy/startup/startup.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:easy_localization/easy_localization.dart'; @@ -11,16 +10,42 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'field_name_input.dart'; import 'field_editor_pannel.dart'; -class FieldEditor extends FlowyOverlayDelegate { +class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { final String gridId; - final FieldEditorBloc _fieldEditorBloc; + final String fieldName; + final FieldContextLoader contextLoader; - FieldEditor({ + const FieldEditor({ required this.gridId, + required this.fieldName, required this.contextLoader, Key? key, - }) : _fieldEditorBloc = getIt(param1: gridId, param2: contextLoader) { - _fieldEditorBloc.add(const FieldEditorEvent.initial()); + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => FieldEditorBloc( + gridId: gridId, + fieldName: fieldName, + fieldContextLoader: contextLoader, + )..add(const FieldEditorEvent.initial()), + child: BlocBuilder( + buildWhen: (p, c) => false, + builder: (context, state) { + return ListView( + shrinkWrap: true, + children: [ + FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), + const VSpace(10), + const _FieldNameTextField(), + const VSpace(10), + const _FieldPannel(), + ], + ); + }, + ), + ); } void show( @@ -28,10 +53,9 @@ class FieldEditor extends FlowyOverlayDelegate { AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned, }) { FlowyOverlay.of(context).remove(identifier()); - final child = _FieldEditorPage(_fieldEditorBloc, contextLoader); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( - child: child, + child: this, constraints: BoxConstraints.loose(const Size(280, 400)), ), identifier: identifier(), @@ -46,49 +70,23 @@ class FieldEditor extends FlowyOverlayDelegate { return (FieldEditor).toString(); } - @override - void didRemove() { - _fieldEditorBloc.add(const FieldEditorEvent.done()); - } - @override bool asBarrier() => true; } -class _FieldEditorPage extends StatelessWidget { - final FieldEditorBloc editorBloc; - final FieldContextLoader contextLoader; - const _FieldEditorPage(this.editorBloc, this.contextLoader, {Key? key}) : super(key: key); +class _FieldPannel extends StatelessWidget { + const _FieldPannel({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return BlocProvider.value( - value: editorBloc, - child: BlocBuilder( - builder: (context, state) { - return state.fieldTypeOptionData.fold( - () => const SizedBox(), - (fieldTypeOptionContext) => ListView( - shrinkWrap: true, - children: [ - FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), - const VSpace(10), - const _FieldNameTextField(), - const VSpace(10), - FieldEditorPannel( - fieldTypeOptionData: fieldTypeOptionContext, - onSwitchToField: (fieldId, fieldType) { - return contextLoader.switchToField(fieldId, fieldType); - }, - onUpdated: (field, typeOptionData) { - context.read().add(FieldEditorEvent.updateField(field, typeOptionData)); - }, - ), - ], - ), - ); - }, - ), + return BlocBuilder( + buildWhen: (p, c) => p.fieldContext != c.fieldContext, + builder: (context, state) { + return state.fieldContext.fold( + () => const SizedBox(), + (fieldContext) => FieldEditorPannel(fieldContext: fieldContext), + ); + }, ); } } @@ -98,16 +96,11 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocSelector( - selector: (state) { - return state.fieldTypeOptionData.fold( - () => "", - (fieldTypeOptionContext) => fieldTypeOptionContext.field_2.name, - ); - }, - builder: (context, name) { + return BlocBuilder( + buildWhen: (p, c) => p.name != c.name, + builder: (context, state) { return FieldNameTextField( - name: name, + name: state.name, errorText: context.read().state.errorText, onNameChanged: (newName) { context.read().add(FieldEditorEvent.updateName(newName)); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index 5d96f92655..21df621705 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -7,14 +7,12 @@ 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/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/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; @@ -31,14 +29,10 @@ typedef SwitchToFieldCallback = Future> ); class FieldEditorPannel extends StatefulWidget { - final FieldTypeOptionData fieldTypeOptionData; - final UpdateFieldCallback onUpdated; - final SwitchToFieldCallback onSwitchToField; + final GridFieldContext fieldContext; const FieldEditorPannel({ - required this.fieldTypeOptionData, - required this.onUpdated, - required this.onSwitchToField, + required this.fieldContext, Key? key, }) : super(key: key); @@ -52,13 +46,10 @@ class _FieldEditorPannelState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: widget.fieldTypeOptionData), - child: BlocConsumer( - listener: (context, state) { - widget.onUpdated(state.field, state.typeOptionData); - }, + create: (context) => FieldEditorPannelBloc(widget.fieldContext)..add(const FieldEditorPannelEvent.initial()), + child: BlocBuilder( builder: (context, state) { - List children = [_switchFieldTypeButton(context, state.field)]; + List children = [_switchFieldTypeButton(context, widget.fieldContext.field)]; final typeOptionWidget = _typeOptionWidget(context: context, state: state); if (typeOptionWidget != null) { @@ -84,19 +75,7 @@ class _FieldEditorPannelState extends State { hoverColor: theme.hover, onTap: () { final list = FieldTypeList(onSelectField: (newFieldType) { - widget.onSwitchToField(field.id, newFieldType).then((result) { - result.fold( - (fieldTypeOptionContext) { - context.read().add( - FieldEditorPannelEvent.toFieldType( - fieldTypeOptionContext.field_2, - fieldTypeOptionContext.typeOptionData, - ), - ); - }, - (err) => Log.error(err), - ); - }); + widget.fieldContext.switchToField(newFieldType); }); _showOverlay(context, list); }, @@ -116,15 +95,11 @@ class _FieldEditorPannelState extends State { ); final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { - context.read().add(FieldEditorPannelEvent.didUpdateTypeOptionData(data)); + widget.fieldContext.typeOptionData = data; }); final builder = _makeTypeOptionBuild( - typeOptionContext: TypeOptionContext( - gridId: state.gridId, - field: state.field, - data: state.typeOptionData, - ), + typeOptionContext: TypeOptionContext(fieldContext: widget.fieldContext), overlayDelegate: overlayDelegate, dataDelegate: dataDelegate, ); 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 d7b24b4d8c..5e1296191b 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 @@ -150,6 +150,7 @@ class CreateFieldButton extends StatelessWidget { hoverColor: theme.hover, onTap: () => FieldEditor( gridId: gridId, + fieldName: "", contextLoader: NewFieldContextLoader(gridId: gridId), ).show(context), leftIcon: svgWidget("home/add"), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index 474a21773d..c8672d4ae3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -178,6 +178,7 @@ class _RowDetailCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: gridCell.gridId, + fieldName: gridCell.field.name, contextLoader: DefaultFieldContextLoader( gridId: gridCell.gridId, field: gridCell.field, 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 151afc1e3f..ec5ca40b1e 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 @@ -115,6 +115,7 @@ class _GridPropertyCell extends StatelessWidget { onTap: () { FieldEditor( gridId: gridId, + fieldName: field.name, contextLoader: DefaultFieldContextLoader(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, 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 5189908192..4f06a40b9b 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 @@ -109,7 +109,7 @@ abstract class HoverWidget extends StatefulWidget { } class FlowyHover2 extends StatefulWidget { - final HoverWidget child; + final Widget child; final EdgeInsets contentPadding; const FlowyHover2({ required this.child, @@ -127,9 +127,14 @@ class _FlowyHover2State extends State { @override void initState() { _hoverState = FlowyHoverState(); - widget.child.onFocus.addListener(() { - _hoverState.onFocus = widget.child.onFocus.value; - }); + + if (widget.child is HoverWidget) { + final hoverWidget = widget.child as HoverWidget; + hoverWidget.onFocus.addListener(() { + _hoverState.onFocus = hoverWidget.onFocus.value; + }); + } + super.initState(); } 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 ccbaff82e9..06b4f7222f 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -212,7 +212,7 @@ pub struct FieldTypeOptionData { pub grid_id: String, #[pb(index = 2)] - pub field_id: String, + pub field: Field, #[pb(index = 3)] pub type_option_data: Vec, 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 c0c03f65a7..6df3c847f0 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 @@ -2174,7 +2174,7 @@ impl ::protobuf::reflect::ProtobufValue for FieldTypeOptionContext { pub struct FieldTypeOptionData { // message fields pub grid_id: ::std::string::String, - pub field_id: ::std::string::String, + pub field: ::protobuf::SingularPtrField, pub type_option_data: ::std::vec::Vec, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -2218,30 +2218,37 @@ impl FieldTypeOptionData { ::std::mem::replace(&mut self.grid_id, ::std::string::String::new()) } - // string field_id = 2; + // .Field field = 2; - pub fn get_field_id(&self) -> &str { - &self.field_id + pub fn get_field(&self) -> &Field { + self.field.as_ref().unwrap_or_else(|| ::default_instance()) } - pub fn clear_field_id(&mut self) { - self.field_id.clear(); + 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_id(&mut self, v: ::std::string::String) { - self.field_id = v; + 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_id(&mut self) -> &mut ::std::string::String { - &mut self.field_id + 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_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) + pub fn take_field(&mut self) -> Field { + self.field.take().unwrap_or_else(|| Field::new()) } // bytes type_option_data = 3; @@ -2273,6 +2280,11 @@ impl FieldTypeOptionData { impl ::protobuf::Message for FieldTypeOptionData { fn is_initialized(&self) -> bool { + for v in &self.field { + if !v.is_initialized() { + return false; + } + }; true } @@ -2284,7 +2296,7 @@ impl ::protobuf::Message for FieldTypeOptionData { ::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)?; + ::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)?; @@ -2304,8 +2316,9 @@ impl ::protobuf::Message for FieldTypeOptionData { 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 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); @@ -2319,8 +2332,10 @@ impl ::protobuf::Message for FieldTypeOptionData { 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 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)?; @@ -2368,10 +2383,10 @@ impl ::protobuf::Message for FieldTypeOptionData { |m: &FieldTypeOptionData| { &m.grid_id }, |m: &mut FieldTypeOptionData| { &mut m.grid_id }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "field_id", - |m: &FieldTypeOptionData| { &m.field_id }, - |m: &mut FieldTypeOptionData| { &mut m.field_id }, + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "field", + |m: &FieldTypeOptionData| { &m.field }, + |m: &mut FieldTypeOptionData| { &mut m.field }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( "type_option_data", @@ -2395,7 +2410,7 @@ impl ::protobuf::Message for FieldTypeOptionData { impl ::protobuf::Clear for FieldTypeOptionData { fn clear(&mut self) { self.grid_id.clear(); - self.field_id.clear(); + self.field.clear(); self.type_option_data.clear(); self.unknown_fields.clear(); } @@ -8302,25 +8317,25 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ne_of_field_id\"\x82\x01\n\x16FieldTypeOptionContext\x12\x17\n\x07grid_i\ d\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\"s\n\x13FieldTypeOptionData\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07\ - fieldId\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionDa\ - ta\"-\n\rRepeatedField\x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.Fiel\ - dR\x05items\"7\n\x12RepeatedFieldOrder\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\x07b\ - lockId\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_fiel\ - d_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\ - \x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFie\ - ldIdEntry\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\x11Repe\ - atedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05i\ - tems\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\ - \x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrd\ - ers\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrd\ - erR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\ + \x0etypeOptionData\"v\n\x13FieldTypeOptionData\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\x0etype\ + OptionData\"-\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\x08RowOrder\x12\x15\n\x06ro\ + w_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_b\ + y_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFiel\ + dId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellBy\ + FieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05va\ + lue\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedR\ + ow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11Re\ + peatedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\ + \x05items\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\ + \tR\x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trow\ + Orders\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.Row\ + OrderR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\ \x0e\n\x0cone_of_index\"Q\n\x0fUpdatedRowOrder\x12&\n\trow_order\x18\x01\ \x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x03row\x18\x02\x20\x01(\ \x0b2\x04.RowR\x03row\"\xc6\x01\n\x11GridRowsChangeset\x12\x19\n\x08bloc\ 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 c1aa74b0e7..99024d3841 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 @@ -45,7 +45,7 @@ message FieldTypeOptionContext { } message FieldTypeOptionData { string grid_id = 1; - string field_id = 2; + Field field = 2; bytes type_option_data = 3; } message RepeatedField { From 5f5177355f16f30ebe983eee879305d5b88c3e35 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 18 May 2022 16:14:11 +0800 Subject: [PATCH 4/8] chore: update _OptionList cell UI --- .../cell/select_option_cell/extension.dart | 39 +++++++++++++++++++ .../select_option_editor.dart | 29 +++----------- .../header/type_option/select_option.dart | 17 +++++--- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart index c4140ad216..87042a419f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart @@ -1,5 +1,8 @@ +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/hover.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:easy_localization/easy_localization.dart'; @@ -106,3 +109,39 @@ class SelectOptionTag extends StatelessWidget { // ); } } + +class SelectOptionTagCell extends StatelessWidget { + final List children; + final void Function(SelectOption) onSelected; + final SelectOption option; + const SelectOptionTagCell({ + required this.option, + required this.onSelected, + this.children = const [], + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Stack( + fit: StackFit.expand, + children: [ + FlowyHover( + style: HoverStyle(hoverColor: theme.hover), + child: InkWell( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 3), + child: Row(children: [ + SelectOptionTag.fromSelectOption(context: context, option: option), + const Spacer(), + ...children, + ]), + ), + onTap: () => onSelected(option), + ), + ), + ], + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index 14e1ee3d33..e504e48f33 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart @@ -239,30 +239,13 @@ class _SelectOptionCell extends StatelessWidget { } Widget _body(AppTheme theme, BuildContext context) { - return Stack( - fit: StackFit.expand, + return SelectOptionTagCell( + option: option, + onSelected: (option) { + context.read().add(SelectOptionEditorEvent.selectOption(option.id)); + }, children: [ - FlowyHover( - style: HoverStyle(hoverColor: theme.hover), - builder: (_, onHover) { - return InkWell( - child: Row(children: [ - const HSpace(6), - SelectOptionTag( - name: option.name, - color: option.color.make(context), - isSelected: isSelected, - ), - const Spacer(), - if (isSelected) svgWidget("grid/checkmark"), - const HSpace(6), - ]), - onTap: () { - context.read().add(SelectOptionEditorEvent.selectOption(option.id)); - }, - ); - }, - ), + if (isSelected) svgWidget("grid/checkmark"), ], ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index a6a76673b3..4b6b1da614 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -1,10 +1,12 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/select_option_type_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/select_option_cell/extension.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.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/hover.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'; @@ -183,13 +185,18 @@ class _OptionCell extends StatelessWidget { @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: () => onSelected(option), - rightIcon: svgWidget("grid/details", color: theme.iconColor), + child: SelectOptionTagCell( + option: option, + onSelected: onSelected, + children: [ + svgWidget( + "grid/details", + color: theme.iconColor, + ), + ], ), ); } From 1267c7524eaee2c3c9fd086b7043f6ce8a639354 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 18 May 2022 17:26:50 +0800 Subject: [PATCH 5/8] refactor: TypeOptionContext --- .../app_flowy/lib/startup/deps_resolver.dart | 10 -- .../grid/field/type_option/date_bloc.dart | 13 ++- .../field/type_option/multi_select_bloc.dart | 18 ++- .../grid/field/type_option/number_bloc.dart | 13 ++- .../field/type_option/single_select_bloc.dart | 15 ++- .../type_option/type_option_service.dart | 21 +++- .../cell/select_option_cell/extension.dart | 2 - .../select_option_editor.dart | 1 - .../widgets/header/field_editor_pannel.dart | 104 +++++++++++------- .../widgets/header/type_option/checkbox.dart | 20 ++++ .../src/widgets/header/type_option/date.dart | 18 ++- .../header/type_option/multi_select.dart | 20 ++-- .../widgets/header/type_option/number.dart | 22 ++-- .../widgets/header/type_option/rich_text.dart | 21 ++++ .../header/type_option/select_option.dart | 7 +- .../header/type_option/single_select.dart | 20 ++-- 16 files changed, 211 insertions(+), 114 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 698cc63531..9be9420fb5 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -15,8 +15,6 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/home/menu/menu.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/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'; @@ -187,14 +185,6 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (typeOption, _) => DateTypeOptionBloc(typeOption: typeOption), - ); - - getIt.registerFactoryParam( - (typeOption, _) => NumberTypeOptionBloc(typeOption: typeOption), - ); - getIt.registerFactoryParam( (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache), ); 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 c0a232a84f..8784422c54 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,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.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'; @@ -5,8 +6,18 @@ import 'dart:async'; import 'package:protobuf/protobuf.dart'; part 'date_bloc.freezed.dart'; +typedef DateTypeOptionContext = TypeOptionContext; + +class DateTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + DateTypeOption fromBuffer(List buffer) { + return DateTypeOption.fromBuffer(buffer); + } +} + class DateTypeOptionBloc extends Bloc { - DateTypeOptionBloc({required DateTypeOption typeOption}) : super(DateTypeOptionState.initial(typeOption)) { + DateTypeOptionBloc({required DateTypeOptionContext typeOptionContext}) + : super(DateTypeOptionState.initial(typeOptionContext.typeOption)) { on( (event, emit) async { event.map( 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 0d42612595..f755abc2ce 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 @@ -8,12 +8,24 @@ import 'type_option_service.dart'; part 'multi_select_bloc.freezed.dart'; +typedef MultiSelectTypeOptionContext = TypeOptionContext; + +class MultiSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + MultiSelectTypeOption fromBuffer(List buffer) { + return MultiSelectTypeOption.fromBuffer(buffer); + } +} + class MultiSelectTypeOptionBloc extends Bloc { final TypeOptionService service; - MultiSelectTypeOptionBloc(TypeOptionContext typeOptionContext) - : service = TypeOptionService(gridId: typeOptionContext.gridId, fieldId: typeOptionContext.field.id), - super(MultiSelectTypeOptionState.initial(MultiSelectTypeOption.fromBuffer(typeOptionContext.data))) { + MultiSelectTypeOptionBloc(MultiSelectTypeOptionContext typeOptionContext) + : service = TypeOptionService( + gridId: typeOptionContext.gridId, + fieldId: typeOptionContext.field.id, + ), + super(MultiSelectTypeOptionState.initial(typeOptionContext.typeOption)) { on( (event, emit) async { await event.map( 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 a655ebc1e8..951bdb9261 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 @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; 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'; @@ -6,8 +7,18 @@ import 'package:protobuf/protobuf.dart'; part 'number_bloc.freezed.dart'; +typedef NumberTypeOptionContext = TypeOptionContext; + +class NumberTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + NumberTypeOption fromBuffer(List buffer) { + return NumberTypeOption.fromBuffer(buffer); + } +} + class NumberTypeOptionBloc extends Bloc { - NumberTypeOptionBloc({required NumberTypeOption typeOption}) : super(NumberTypeOptionState.initial(typeOption)) { + NumberTypeOptionBloc({required NumberTypeOptionContext typeOptionContext}) + : super(NumberTypeOptionState.initial(typeOptionContext.typeOption)) { on( (event, emit) async { event.map( 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 36a2f956b3..624e8fe08e 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 @@ -8,15 +8,22 @@ import 'type_option_service.dart'; part 'single_select_bloc.freezed.dart'; +typedef SingleSelectTypeOptionContext = TypeOptionContext; + +class SingleSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + SingleSelectTypeOption fromBuffer(List buffer) { + return SingleSelectTypeOption.fromBuffer(buffer); + } +} + class SingleSelectTypeOptionBloc extends Bloc { final TypeOptionService service; SingleSelectTypeOptionBloc( - TypeOptionContext typeOptionContext, + SingleSelectTypeOptionContext typeOptionContext, ) : service = TypeOptionService(gridId: typeOptionContext.gridId, fieldId: typeOptionContext.field.id), - super( - SingleSelectTypeOptionState.initial(SingleSelectTypeOption.fromBuffer(typeOptionContext.data)), - ) { + super(SingleSelectTypeOptionState.initial(typeOptionContext.typeOption)) { on( (event, emit) async { await event.map( 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 cf9b69780d..c088618825 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 @@ -8,6 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.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/selection_type_option.pb.dart'; +import 'package:protobuf/protobuf.dart'; class TypeOptionService { final String gridId; @@ -37,10 +38,13 @@ abstract class TypeOptionDataBuilder { T fromBuffer(List buffer); } -class TypeOptionContext { +class TypeOptionContext { + T? _typeOptionObject; final GridFieldContext _fieldContext; + final TypeOptionDataBuilder dataBuilder; TypeOptionContext({ + required this.dataBuilder, required GridFieldContext fieldContext, }) : _fieldContext = fieldContext; @@ -48,7 +52,20 @@ class TypeOptionContext { Field get field => _fieldContext.field; - Uint8List get data => Uint8List.fromList(_fieldContext.typeOptionData); + T get typeOption { + if (_typeOptionObject != null) { + return _typeOptionObject!; + } + + final T object = dataBuilder.fromBuffer(_fieldContext.typeOptionData); + _typeOptionObject = object; + return object; + } + + set typeOption(T typeOption) { + _fieldContext.typeOptionData = typeOption.writeToBuffer(); + _typeOptionObject = null; + } } abstract class TypeOptionFieldDelegate { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart index 87042a419f..3cbf2331fd 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart @@ -1,8 +1,6 @@ -import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/hover.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:easy_localization/easy_localization.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index e504e48f33..f82d52cfb4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart @@ -7,7 +7,6 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common 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'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index 21df621705..30599cef30 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -1,6 +1,8 @@ import 'dart:typed_data'; +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart'; import 'package:dartz/dartz.dart' show Either; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -9,8 +11,6 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.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/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/workspace/application/grid/prelude.dart'; @@ -20,6 +20,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header import 'field_type_extension.dart'; import 'type_option/multi_select.dart'; import 'type_option/number.dart'; +import 'type_option/rich_text.dart'; import 'type_option/single_select.dart'; typedef UpdateFieldCallback = void Function(Field, Uint8List); @@ -94,14 +95,9 @@ class _FieldEditorPannelState extends State { hideOverlay: _hideOverlay, ); - final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { - widget.fieldContext.typeOptionData = data; - }); - final builder = _makeTypeOptionBuild( - typeOptionContext: TypeOptionContext(fieldContext: widget.fieldContext), + typeOptionContext: _makeTypeOptionContext(widget.fieldContext), overlayDelegate: overlayDelegate, - dataDelegate: dataDelegate, ); return builder.customWidget; @@ -141,27 +137,79 @@ abstract class TypeOptionBuilder { TypeOptionBuilder _makeTypeOptionBuild({ required TypeOptionContext typeOptionContext, required TypeOptionOverlayDelegate overlayDelegate, - required TypeOptionDataDelegate dataDelegate, }) { switch (typeOptionContext.field.fieldType) { case FieldType.Checkbox: - return CheckboxTypeOptionBuilder(typeOptionContext.data); + return CheckboxTypeOptionBuilder( + typeOptionContext as CheckboxTypeOptionContext, + ); case FieldType.DateTime: - return DateTypeOptionBuilder(typeOptionContext.data, overlayDelegate, dataDelegate); + return DateTypeOptionBuilder( + typeOptionContext as DateTypeOptionContext, + overlayDelegate, + ); case FieldType.SingleSelect: - return SingleSelectTypeOptionBuilder(typeOptionContext, overlayDelegate, dataDelegate); + return SingleSelectTypeOptionBuilder( + typeOptionContext as SingleSelectTypeOptionContext, + overlayDelegate, + ); case FieldType.MultiSelect: - return MultiSelectTypeOptionBuilder(typeOptionContext, overlayDelegate, dataDelegate); + return MultiSelectTypeOptionBuilder( + typeOptionContext as MultiSelectTypeOptionContext, + overlayDelegate, + ); case FieldType.Number: - return NumberTypeOptionBuilder(typeOptionContext.data, overlayDelegate, dataDelegate); + return NumberTypeOptionBuilder( + typeOptionContext as NumberTypeOptionContext, + overlayDelegate, + ); case FieldType.RichText: - return RichTextTypeOptionBuilder(typeOptionContext.data); + return RichTextTypeOptionBuilder( + typeOptionContext as RichTextTypeOptionContext, + ); default: throw UnimplementedError; } } +TypeOptionContext _makeTypeOptionContext(GridFieldContext fieldContext) { + switch (fieldContext.field.fieldType) { + case FieldType.Checkbox: + return CheckboxTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: CheckboxTypeOptionDataBuilder(), + ); + case FieldType.DateTime: + return DateTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: DateTypeOptionDataBuilder(), + ); + case FieldType.MultiSelect: + return MultiSelectTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: MultiSelectTypeOptionDataBuilder(), + ); + case FieldType.Number: + return NumberTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: NumberTypeOptionDataBuilder(), + ); + case FieldType.RichText: + return RichTextTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: RichTextTypeOptionDataBuilder(), + ); + case FieldType.SingleSelect: + return SingleSelectTypeOptionContext( + fieldContext: fieldContext, + dataBuilder: SingleSelectTypeOptionDataBuilder(), + ); + default: + throw UnimplementedError(); + } +} + abstract class TypeOptionWidget extends StatelessWidget { const TypeOptionWidget({Key? key}) : super(key: key); } @@ -183,29 +231,3 @@ class TypeOptionOverlayDelegate { required this.hideOverlay, }); } - -class TypeOptionDataDelegate { - TypeOptionDataCallback didUpdateTypeOptionData; - - TypeOptionDataDelegate({ - required this.didUpdateTypeOptionData, - }); -} - -class RichTextTypeOptionBuilder extends TypeOptionBuilder { - RichTextTypeOption typeOption; - - RichTextTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = RichTextTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => null; -} - -class CheckboxTypeOptionBuilder extends TypeOptionBuilder { - CheckboxTypeOption typeOption; - - CheckboxTypeOptionBuilder(TypeOptionData typeOptionData) : typeOption = CheckboxTypeOption.fromBuffer(typeOptionData); - - @override - Widget? get customWidget => null; -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart new file mode 100644 index 0000000000..c1e202f358 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart @@ -0,0 +1,20 @@ +import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; +import 'package:flutter/material.dart'; + +typedef CheckboxTypeOptionContext = TypeOptionContext; + +class CheckboxTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + CheckboxTypeOption fromBuffer(List buffer) { + return CheckboxTypeOption.fromBuffer(buffer); + } +} + +class CheckboxTypeOptionBuilder extends TypeOptionBuilder { + CheckboxTypeOptionBuilder(CheckboxTypeOptionContext typeOptionContext); + + @override + Widget? get customWidget => null; +} 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 677e043703..f4031dc9ce 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,4 +1,3 @@ -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_editor_pannel.dart'; @@ -18,12 +17,10 @@ class DateTypeOptionBuilder extends TypeOptionBuilder { final DateTypeOptionWidget _widget; DateTypeOptionBuilder( - TypeOptionData typeOptionData, + DateTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, - TypeOptionDataDelegate dataDelegate, ) : _widget = DateTypeOptionWidget( - typeOption: DateTypeOption.fromBuffer(typeOptionData), - dataDelegate: dataDelegate, + typeOptionContext: typeOptionContext, overlayDelegate: overlayDelegate, ); @@ -32,12 +29,11 @@ class DateTypeOptionBuilder extends TypeOptionBuilder { } class DateTypeOptionWidget extends TypeOptionWidget { - final DateTypeOption typeOption; + final DateTypeOptionContext typeOptionContext; final TypeOptionOverlayDelegate overlayDelegate; - final TypeOptionDataDelegate dataDelegate; + const DateTypeOptionWidget({ - required this.typeOption, - required this.dataDelegate, + required this.typeOptionContext, required this.overlayDelegate, Key? key, }) : super(key: key); @@ -45,9 +41,9 @@ class DateTypeOptionWidget extends TypeOptionWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: typeOption), + create: (context) => DateTypeOptionBloc(typeOptionContext: typeOptionContext), child: BlocConsumer( - listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + listener: (context, state) => typeOptionContext.typeOption = state.typeOption, builder: (context, state) { return Column(children: [ _renderDateFormatButton(context, state.typeOption.dateFormat), 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 cd2997738c..b1b530fcf3 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,5 +1,4 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -10,13 +9,11 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { final MultiSelectTypeOptionWidget _widget; MultiSelectTypeOptionBuilder( - TypeOptionContext typeOptionContext, + MultiSelectTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, - TypeOptionDataDelegate dataDelegate, ) : _widget = MultiSelectTypeOptionWidget( typeOptionContext: typeOptionContext, overlayDelegate: overlayDelegate, - dataDelegate: dataDelegate, ); @override @@ -24,13 +21,12 @@ class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { } class MultiSelectTypeOptionWidget extends TypeOptionWidget { - final TypeOptionContext typeOptionContext; + final MultiSelectTypeOptionContext typeOptionContext; final TypeOptionOverlayDelegate overlayDelegate; - final TypeOptionDataDelegate dataDelegate; + const MultiSelectTypeOptionWidget({ required this.typeOptionContext, required this.overlayDelegate, - required this.dataDelegate, Key? key, }) : super(key: key); @@ -40,7 +36,7 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { create: (context) => MultiSelectTypeOptionBloc(typeOptionContext), child: BlocConsumer( listener: (context, state) { - dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); + typeOptionContext.typeOption = state.typeOption; }, builder: (context, state) { return SelectOptionTypeOptionWidget( @@ -51,11 +47,11 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { createSelectOptionCallback: (name) { context.read().add(MultiSelectTypeOptionEvent.createOption(name)); }, - updateSelectOptionCallback: (updateOption) { - context.read().add(MultiSelectTypeOptionEvent.updateOption(updateOption)); + updateSelectOptionCallback: (option) { + context.read().add(MultiSelectTypeOptionEvent.updateOption(option)); }, - deleteSelectOptionCallback: (deleteOption) { - context.read().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption)); + deleteSelectOptionCallback: (option) { + context.read().add(MultiSelectTypeOptionEvent.deleteOption(option)); }, overlayDelegate: overlayDelegate, // key: ValueKey(state.typeOption.hashCode), 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 9e3ced1c43..3a330a02b7 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,4 +1,3 @@ -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/application/grid/field/type_option/number_format_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; @@ -20,12 +19,10 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder { final NumberTypeOptionWidget _widget; NumberTypeOptionBuilder( - TypeOptionData typeOptionData, + NumberTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, - TypeOptionDataDelegate dataDelegate, ) : _widget = NumberTypeOptionWidget( - typeOption: NumberTypeOption.fromBuffer(typeOptionData), - dataDelegate: dataDelegate, + typeOptionContext: typeOptionContext, overlayDelegate: overlayDelegate, ); @@ -34,22 +31,23 @@ class NumberTypeOptionBuilder extends TypeOptionBuilder { } class NumberTypeOptionWidget extends TypeOptionWidget { - final TypeOptionDataDelegate dataDelegate; final TypeOptionOverlayDelegate overlayDelegate; - final NumberTypeOption typeOption; - const NumberTypeOptionWidget( - {required this.typeOption, required this.dataDelegate, required this.overlayDelegate, Key? key}) - : super(key: key); + final NumberTypeOptionContext typeOptionContext; + const NumberTypeOptionWidget({ + required this.typeOptionContext, + required this.overlayDelegate, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); return BlocProvider( - create: (context) => getIt(param1: typeOption), + create: (context) => NumberTypeOptionBloc(typeOptionContext: typeOptionContext), child: SizedBox( height: GridSize.typeOptionItemHeight, child: BlocConsumer( - listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), + listener: (context, state) => typeOptionContext.typeOption = state.typeOption, builder: (context, state) { return FlowyButton( text: Row( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart new file mode 100644 index 0000000000..03f9ed347c --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart @@ -0,0 +1,21 @@ +import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; + +import 'package:flutter/material.dart'; + +typedef RichTextTypeOptionContext = TypeOptionContext; + +class RichTextTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + RichTextTypeOption fromBuffer(List buffer) { + return RichTextTypeOption.fromBuffer(buffer); + } +} + +class RichTextTypeOptionBuilder extends TypeOptionBuilder { + RichTextTypeOptionBuilder(RichTextTypeOptionContext typeOptionContext); + + @override + Widget? get customWidget => null; +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index 4b6b1da614..68711a0ad4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -6,7 +6,6 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header 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/hover.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'; @@ -63,7 +62,11 @@ class SelectOptionTypeOptionWidget extends StatelessWidget { List children = [ const TypeOptionSeparator(), const OptionTitle(), - if (state.isEditingOption) const _CreateOptionTextField(), + if (state.isEditingOption) + const Padding( + padding: EdgeInsets.only(bottom: 10), + child: _CreateOptionTextField(), + ), if (state.options.isEmpty && !state.isEditingOption) const _AddOptionButton(), _OptionList(overlayDelegate) ]; 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 11793fbb43..bbe3b1550b 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,5 +1,4 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -9,12 +8,10 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { final SingleSelectTypeOptionWidget _widget; SingleSelectTypeOptionBuilder( - TypeOptionContext typeOptionContext, + SingleSelectTypeOptionContext typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, - TypeOptionDataDelegate dataDelegate, ) : _widget = SingleSelectTypeOptionWidget( typeOptionContext: typeOptionContext, - dataDelegate: dataDelegate, overlayDelegate: overlayDelegate, ); @@ -23,12 +20,11 @@ class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { } class SingleSelectTypeOptionWidget extends TypeOptionWidget { - final TypeOptionContext typeOptionContext; + final SingleSelectTypeOptionContext typeOptionContext; final TypeOptionOverlayDelegate overlayDelegate; - final TypeOptionDataDelegate dataDelegate; + const SingleSelectTypeOptionWidget({ required this.typeOptionContext, - required this.dataDelegate, required this.overlayDelegate, Key? key, }) : super(key: key); @@ -39,7 +35,7 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { create: (context) => SingleSelectTypeOptionBloc(typeOptionContext), child: BlocConsumer( listener: (context, state) { - dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); + typeOptionContext.typeOption = state.typeOption; }, builder: (context, state) { return SelectOptionTypeOptionWidget( @@ -50,11 +46,11 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { createSelectOptionCallback: (name) { context.read().add(SingleSelectTypeOptionEvent.createOption(name)); }, - updateSelectOptionCallback: (updateOption) { - context.read().add(SingleSelectTypeOptionEvent.updateOption(updateOption)); + updateSelectOptionCallback: (option) { + context.read().add(SingleSelectTypeOptionEvent.updateOption(option)); }, - deleteSelectOptionCallback: (deleteOption) { - context.read().add(SingleSelectTypeOptionEvent.deleteOption(deleteOption)); + deleteSelectOptionCallback: (option) { + context.read().add(SingleSelectTypeOptionEvent.deleteOption(option)); }, overlayDelegate: overlayDelegate, // key: ValueKey(state.typeOption.hashCode), From f3b87d419fe9cf5d18bb8777b3df1004e0e925e8 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 18 May 2022 20:11:49 +0800 Subject: [PATCH 6/8] chore: optimaze create option progress --- .../field/type_option/multi_select_bloc.dart | 101 ------------------ .../type_option/multi_select_type_option.dart | 77 +++++++++++++ .../select_option_type_option_bloc.dart | 49 +++++---- .../field/type_option/single_select_bloc.dart | 99 ----------------- .../single_select_type_option.dart | 78 ++++++++++++++ .../type_option/type_option_service.dart | 2 +- .../workspace/application/grid/prelude.dart | 2 +- .../grid/src/widgets/common/text_field.dart | 6 ++ .../widgets/header/field_editor_pannel.dart | 2 +- .../header/type_option/multi_select.dart | 35 ++---- .../header/type_option/select_option.dart | 55 ++++------ .../header/type_option/single_select.dart | 35 ++---- 12 files changed, 227 insertions(+), 314 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart delete 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/single_select_type_option.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 deleted file mode 100644 index f755abc2ce..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart +++ /dev/null @@ -1,101 +0,0 @@ -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'; - -typedef MultiSelectTypeOptionContext = TypeOptionContext; - -class MultiSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { - @override - MultiSelectTypeOption fromBuffer(List buffer) { - return MultiSelectTypeOption.fromBuffer(buffer); - } -} - -class MultiSelectTypeOptionBloc extends Bloc { - final TypeOptionService service; - - MultiSelectTypeOptionBloc(MultiSelectTypeOptionContext typeOptionContext) - : service = TypeOptionService( - gridId: typeOptionContext.gridId, - fieldId: typeOptionContext.field.id, - ), - super(MultiSelectTypeOptionState.initial(typeOptionContext.typeOption)) { - on( - (event, emit) async { - await event.map( - createOption: (_CreateOption value) async { - final result = await service.newOption(name: 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))); - }, - ); - }, - ); - } - - @override - Future 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.updateOption(SelectOption option) = _UpdateOption; - const factory MultiSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption; -} - -@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/multi_select_type_option.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart new file mode 100644 index 0000000000..bb72277f0b --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart @@ -0,0 +1,77 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'dart:async'; +import 'package:protobuf/protobuf.dart'; +import 'select_option_type_option_bloc.dart'; +import 'type_option_service.dart'; + +class MultiSelectTypeOptionContext extends TypeOptionContext with SelectOptionTypeOptionAction { + final TypeOptionService service; + + MultiSelectTypeOptionContext({ + required MultiSelectTypeOptionDataBuilder dataBuilder, + required GridFieldContext fieldContext, + }) : service = TypeOptionService( + gridId: fieldContext.gridId, + fieldId: fieldContext.field.id, + ), + super(dataBuilder: dataBuilder, fieldContext: fieldContext); + + @override + List Function(SelectOption) get deleteOption { + return (SelectOption option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options.removeAt(index); + } + }); + return typeOption.options; + }; + } + + @override + Future> Function(String) get insertOption { + return (String optionName) { + return service.newOption(name: optionName).then((result) { + return result.fold( + (option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + typeOption.options.insert(0, option); + }); + + return typeOption.options; + }, + (err) { + Log.error(err); + return typeOption.options; + }, + ); + }); + }; + } + + @override + List Function(SelectOption) get udpateOption { + return (SelectOption option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options[index] = option; + } + }); + return typeOption.options; + }; + } +} + +class MultiSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + MultiSelectTypeOption fromBuffer(List buffer) { + return MultiSelectTypeOption.fromBuffer(buffer); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart index 7e1bf9a0d9..d4290cd8ff 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/select_option_type_option_bloc.dart @@ -5,26 +5,41 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; part 'select_option_type_option_bloc.freezed.dart'; -class SelectOptionTypeOptionBloc extends Bloc { - SelectOptionTypeOptionBloc({required List options}) - : super(SelectOptionTyepOptionState.initial(options)) { +abstract class SelectOptionTypeOptionAction { + Future> Function(String) get insertOption; + + List Function(SelectOption) get deleteOption; + + List Function(SelectOption) get udpateOption; +} + +class SelectOptionTypeOptionBloc extends Bloc { + final SelectOptionTypeOptionAction typeOptionAction; + + SelectOptionTypeOptionBloc({ + required List options, + required this.typeOptionAction, + }) : super(SelectOptionTypeOptionState.initial(options)) { on( (event, emit) async { - await event.map( - createOption: (_CreateOption value) async { - emit(state.copyWith(isEditingOption: true, newOptionName: Some(value.optionName))); + await event.when( + createOption: (optionName) async { + final List options = await typeOptionAction.insertOption(optionName); + emit(state.copyWith(options: options)); }, - addingOption: (_AddingOption value) { + addingOption: () { emit(state.copyWith(isEditingOption: true, newOptionName: none())); }, - endAddingOption: (_EndAddingOption value) { + endAddingOption: () { emit(state.copyWith(isEditingOption: false, newOptionName: none())); }, - updateOption: (_UpdateOption value) { - emit(state.copyWith(updateOption: Some(value.option))); + updateOption: (option) { + final List options = typeOptionAction.udpateOption(option); + emit(state.copyWith(options: options)); }, - deleteOption: (_DeleteOption value) { - emit(state.copyWith(deleteOption: Some(value.option))); + deleteOption: (option) { + final List options = typeOptionAction.deleteOption(option); + emit(state.copyWith(options: options)); }, ); }, @@ -47,20 +62,16 @@ class SelectOptionTypeOptionEvent with _$SelectOptionTypeOptionEvent { } @freezed -class SelectOptionTyepOptionState with _$SelectOptionTyepOptionState { - const factory SelectOptionTyepOptionState({ +class SelectOptionTypeOptionState with _$SelectOptionTypeOptionState { + const factory SelectOptionTypeOptionState({ required List options, required bool isEditingOption, required Option newOptionName, - required Option updateOption, - required Option deleteOption, }) = _SelectOptionTyepOptionState; - factory SelectOptionTyepOptionState.initial(List options) => SelectOptionTyepOptionState( + factory SelectOptionTypeOptionState.initial(List options) => SelectOptionTypeOptionState( 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 deleted file mode 100644 index 624e8fe08e..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart +++ /dev/null @@ -1,99 +0,0 @@ -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 'single_select_bloc.freezed.dart'; - -typedef SingleSelectTypeOptionContext = TypeOptionContext; - -class SingleSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { - @override - SingleSelectTypeOption fromBuffer(List buffer) { - return SingleSelectTypeOption.fromBuffer(buffer); - } -} - -class SingleSelectTypeOptionBloc extends Bloc { - final TypeOptionService service; - - SingleSelectTypeOptionBloc( - SingleSelectTypeOptionContext typeOptionContext, - ) : service = TypeOptionService(gridId: typeOptionContext.gridId, fieldId: typeOptionContext.field.id), - super(SingleSelectTypeOptionState.initial(typeOptionContext.typeOption)) { - on( - (event, emit) async { - await event.map( - createOption: (_CreateOption value) async { - final result = await service.newOption(name: 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))); - }, - ); - }, - ); - } - - @override - Future 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.updateOption(SelectOption option) = _UpdateOption; - const factory SingleSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption; -} - -@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/single_select_type_option.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart new file mode 100644 index 0000000000..91d8de7a28 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart @@ -0,0 +1,78 @@ +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'dart:async'; +import 'package:protobuf/protobuf.dart'; +import 'select_option_type_option_bloc.dart'; +import 'type_option_service.dart'; + +class SingleSelectTypeOptionContext extends TypeOptionContext + with SelectOptionTypeOptionAction { + final TypeOptionService service; + + SingleSelectTypeOptionContext({ + required SingleSelectTypeOptionDataBuilder dataBuilder, + required GridFieldContext fieldContext, + }) : service = TypeOptionService( + gridId: fieldContext.gridId, + fieldId: fieldContext.field.id, + ), + super(dataBuilder: dataBuilder, fieldContext: fieldContext); + + @override + List Function(SelectOption) get deleteOption { + return (SelectOption option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options.removeAt(index); + } + }); + return typeOption.options; + }; + } + + @override + Future> Function(String) get insertOption { + return (String optionName) { + return service.newOption(name: optionName).then((result) { + return result.fold( + (option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + typeOption.options.insert(0, option); + }); + + return typeOption.options; + }, + (err) { + Log.error(err); + return typeOption.options; + }, + ); + }); + }; + } + + @override + List Function(SelectOption) get udpateOption { + return (SelectOption option) { + typeOption.freeze(); + typeOption = typeOption.rebuild((typeOption) { + final index = typeOption.options.indexWhere((element) => element.id == option.id); + if (index != -1) { + typeOption.options[index] = option; + } + }); + return typeOption.options; + }; + } +} + +class SingleSelectTypeOptionDataBuilder extends TypeOptionDataBuilder { + @override + SingleSelectTypeOption fromBuffer(List buffer) { + return SingleSelectTypeOption.fromBuffer(buffer); + } +} 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 c088618825..4bf61cc1ff 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 @@ -64,7 +64,7 @@ class TypeOptionContext { set typeOption(T typeOption) { _fieldContext.typeOptionData = typeOption.writeToBuffer(); - _typeOptionObject = null; + _typeOptionObject = typeOption; } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 3a0ebc5112..6ea198f303 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -13,7 +13,7 @@ export 'field/field_editor_pannel_bloc.dart'; // Field Type Option export 'field/type_option/date_bloc.dart'; export 'field/type_option/number_bloc.dart'; -export 'field/type_option/single_select_bloc.dart'; +export 'field/type_option/single_select_type_option.dart'; // Cell export 'cell/text_cell_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart index b5860b1fbb..43d394bfe1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart @@ -7,6 +7,7 @@ class InputTextField extends StatefulWidget { final void Function(String)? onDone; final void Function(String)? onChanged; final void Function() onCanceled; + final bool autoClearWhenDone; final String text; const InputTextField({ @@ -14,6 +15,7 @@ class InputTextField extends StatefulWidget { this.onDone, required this.onCanceled, this.onChanged, + this.autoClearWhenDone = false, Key? key, }) : super(key: key); @@ -57,6 +59,10 @@ class _InputTextFieldState extends State { if (widget.onDone != null) { widget.onDone!(_controller.text); } + + if (widget.autoClearWhenDone) { + _controller.text = ""; + } }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index 30599cef30..eb42267445 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; -import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart'; import 'package:dartz/dartz.dart' show Either; 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 b1b530fcf3..fc310410f9 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,7 +1,6 @@ -import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_type_option.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'select_option.dart'; @@ -32,32 +31,12 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => MultiSelectTypeOptionBloc(typeOptionContext), - child: BlocConsumer( - listener: (context, state) { - typeOptionContext.typeOption = state.typeOption; - }, - builder: (context, state) { - return SelectOptionTypeOptionWidget( - options: state.typeOption.options, - beginEdit: () { - overlayDelegate.hideOverlay(context); - }, - createSelectOptionCallback: (name) { - context.read().add(MultiSelectTypeOptionEvent.createOption(name)); - }, - updateSelectOptionCallback: (option) { - context.read().add(MultiSelectTypeOptionEvent.updateOption(option)); - }, - deleteSelectOptionCallback: (option) { - context.read().add(MultiSelectTypeOptionEvent.deleteOption(option)); - }, - overlayDelegate: overlayDelegate, - // key: ValueKey(state.typeOption.hashCode), - ); - }, - ), + return SelectOptionTypeOptionWidget( + options: typeOptionContext.typeOption.options, + beginEdit: () => overlayDelegate.hideOverlay(context), + overlayDelegate: overlayDelegate, + typeOptionAction: typeOptionContext, + // key: ValueKey(state.typeOption.hashCode), ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart index 68711a0ad4..b308995dd1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/select_option.dart @@ -19,45 +19,22 @@ import 'select_option_editor.dart'; class SelectOptionTypeOptionWidget extends StatelessWidget { final List options; final VoidCallback beginEdit; - final Function(String optionName) createSelectOptionCallback; - final Function(SelectOption) updateSelectOptionCallback; - final Function(SelectOption) deleteSelectOptionCallback; final TypeOptionOverlayDelegate overlayDelegate; + final SelectOptionTypeOptionAction typeOptionAction; const SelectOptionTypeOptionWidget({ required this.options, required this.beginEdit, - required this.createSelectOptionCallback, - required this.updateSelectOptionCallback, - required this.deleteSelectOptionCallback, required this.overlayDelegate, + required this.typeOptionAction, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => SelectOptionTypeOptionBloc(options: options), - child: BlocConsumer( - listener: (context, state) { - if (state.isEditingOption) { - beginEdit(); - } - state.newOptionName.fold( - () => null, - (optionName) => createSelectOptionCallback(optionName), - ); - - state.updateOption.fold( - () => null, - (updateOption) => updateSelectOptionCallback(updateOption), - ); - - state.deleteOption.fold( - () => null, - (deleteOption) => deleteSelectOptionCallback(deleteOption), - ); - }, + create: (context) => SelectOptionTypeOptionBloc(options: options, typeOptionAction: typeOptionAction), + child: BlocBuilder( builder: (context, state) { List children = [ const TypeOptionSeparator(), @@ -83,7 +60,7 @@ class OptionTitle extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; if (state.options.isNotEmpty) { @@ -130,7 +107,7 @@ class _OptionList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( buildWhen: (previous, current) { return previous.options != current.options; }, @@ -230,13 +207,19 @@ class _CreateOptionTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return InputTextField( - text: "", - onCanceled: () { - context.read().add(const SelectOptionTypeOptionEvent.endAddingOption()); - }, - onDone: (optionName) { - context.read().add(SelectOptionTypeOptionEvent.createOption(optionName)); + return BlocBuilder( + builder: (context, state) { + final text = state.newOptionName.foldRight("", (a, previous) => a); + return InputTextField( + autoClearWhenDone: true, + text: text, + onCanceled: () { + context.read().add(const SelectOptionTypeOptionEvent.endAddingOption()); + }, + onDone: (optionName) { + context.read().add(SelectOptionTypeOptionEvent.createOption(optionName)); + }, + ); }, ); } 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 bbe3b1550b..fedddec11d 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,7 +1,6 @@ -import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_type_option.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'select_option.dart'; class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { @@ -31,32 +30,12 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => SingleSelectTypeOptionBloc(typeOptionContext), - child: BlocConsumer( - listener: (context, state) { - typeOptionContext.typeOption = state.typeOption; - }, - builder: (context, state) { - return SelectOptionTypeOptionWidget( - options: state.typeOption.options, - beginEdit: () { - overlayDelegate.hideOverlay(context); - }, - createSelectOptionCallback: (name) { - context.read().add(SingleSelectTypeOptionEvent.createOption(name)); - }, - updateSelectOptionCallback: (option) { - context.read().add(SingleSelectTypeOptionEvent.updateOption(option)); - }, - deleteSelectOptionCallback: (option) { - context.read().add(SingleSelectTypeOptionEvent.deleteOption(option)); - }, - overlayDelegate: overlayDelegate, - // key: ValueKey(state.typeOption.hashCode), - ); - }, - ), + return SelectOptionTypeOptionWidget( + options: typeOptionContext.typeOption.options, + beginEdit: () => overlayDelegate.hideOverlay(context), + overlayDelegate: overlayDelegate, + typeOptionAction: typeOptionContext, + // key: ValueKey(state.typeOption.hashCode), ); } } From 23900b49f50d3293b1624fb30e15996597a8ffb5 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 19 May 2022 10:41:00 +0800 Subject: [PATCH 7/8] chore: fix bugs --- .../grid/field/field_editor_bloc.dart | 6 +- .../application/grid/field/field_service.dart | 66 ++--- .../grid/src/widgets/header/field_cell.dart | 2 +- .../grid/src/widgets/header/field_editor.dart | 3 +- .../src/widgets/header/field_name_input.dart | 30 +- .../grid/src/widgets/row/row_detail.dart | 2 +- .../src/widgets/toolbar/grid_property.dart | 2 +- .../dart_event/flowy-grid/dart_event.dart | 17 ++ .../flowy-grid-data-model/grid.pb.dart | 27 +- .../flowy-grid-data-model/grid.pbjson.dart | 8 +- .../protobuf/flowy-grid/event_map.pbenum.dart | 2 + .../protobuf/flowy-grid/event_map.pbjson.dart | 3 +- .../rust-lib/flowy-grid/src/event_handler.rs | 82 +++--- frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../src/protobuf/model/event_map.rs | 19 +- .../src/protobuf/proto/event_map.proto | 1 + .../flowy-grid/src/services/grid_editor.rs | 12 +- .../src/entities/grid.rs | 31 ++- .../src/protobuf/model/grid.rs | 262 +++++++++--------- .../src/protobuf/proto/grid.proto | 3 +- 20 files changed, 322 insertions(+), 260 deletions(-) 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 ba2c25fec6..2815d5519d 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 @@ -9,7 +9,7 @@ class FieldEditorBloc extends Bloc { FieldEditorBloc({ required String gridId, required String fieldName, - required FieldContextLoader fieldContextLoader, + required IFieldContextLoader fieldContextLoader, }) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) { on( (event, emit) async { @@ -18,7 +18,7 @@ class FieldEditorBloc extends Bloc { final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader); await fieldContext.loadData().then((result) { result.fold( - (l) => emit(state.copyWith(fieldContext: Some(fieldContext))), + (l) => emit(state.copyWith(fieldContext: Some(fieldContext), name: fieldContext.field.name)), (r) => null, ); }); @@ -53,7 +53,7 @@ class FieldEditorState with _$FieldEditorState { required Option fieldContext, }) = _FieldEditorState; - factory FieldEditorState.initial(String gridId, String fieldName, FieldContextLoader loader) => FieldEditorState( + factory FieldEditorState.initial(String gridId, String fieldName, IFieldContextLoader loader) => FieldEditorState( gridId: gridId, fieldContext: none(), 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 03f27dffe7..36547071b9 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 @@ -15,15 +15,6 @@ class FieldService { FieldService({required this.gridId, required this.fieldId}); - Future> switchToField(FieldType fieldType) { - final payload = EditFieldPayload.create() - ..gridId = gridId - ..fieldId = fieldId - ..fieldType = fieldType; - - return GridEventSwitchToField(payload).send(); - } - Future> moveField(int fromIndex, int toIndex) { final payload = MoveItemPayload.create() ..gridId = gridId @@ -146,13 +137,22 @@ class GridFieldCellContext with _$GridFieldCellContext { }) = _GridFieldCellContext; } -abstract class FieldContextLoader { +abstract class IFieldContextLoader { + String get gridId; Future> load(); - Future> switchToField(String fieldId, FieldType fieldType); + Future> switchToField(String fieldId, FieldType fieldType) { + final payload = EditFieldPayload.create() + ..gridId = gridId + ..fieldId = fieldId + ..fieldType = fieldType; + + return GridEventSwitchToField(payload).send(); + } } -class NewFieldContextLoader extends FieldContextLoader { +class NewFieldContextLoader extends IFieldContextLoader { + @override final String gridId; NewFieldContextLoader({ required this.gridId, @@ -164,24 +164,16 @@ class NewFieldContextLoader extends FieldContextLoader { ..gridId = gridId ..fieldType = FieldType.RichText; - return GridEventGetFieldTypeOption(payload).send(); - } - - @override - Future> switchToField(String fieldId, FieldType fieldType) { - final payload = EditFieldPayload.create() - ..gridId = gridId - ..fieldType = fieldType; - - return GridEventGetFieldTypeOption(payload).send(); + return GridEventCreateFieldTypeOption(payload).send(); } } -class DefaultFieldContextLoader extends FieldContextLoader { +class FieldContextLoader extends IFieldContextLoader { + @override final String gridId; final Field field; - DefaultFieldContextLoader({ + FieldContextLoader({ required this.gridId, required this.field, }); @@ -195,24 +187,18 @@ class DefaultFieldContextLoader extends FieldContextLoader { return GridEventGetFieldTypeOption(payload).send(); } - - @override - Future> switchToField(String fieldId, FieldType fieldType) async { - final fieldService = FieldService(gridId: gridId, fieldId: fieldId); - return fieldService.switchToField(fieldType); - } } class GridFieldContext { final String gridId; - final FieldContextLoader _loader; + final IFieldContextLoader _loader; late FieldTypeOptionData _data; ValueNotifier? _fieldNotifier; GridFieldContext({ required this.gridId, - required FieldContextLoader loader, + required IFieldContextLoader loader, }) : _loader = loader; Future> loadData() async { @@ -246,18 +232,18 @@ class GridFieldContext { List get typeOptionData => _data.typeOptionData; set fieldName(String name) { - _updateData(name: name); + _updateData(newName: name); } set typeOptionData(List typeOptionData) { - _updateData(typeOptionData: typeOptionData); + _updateData(newTypeOptionData: typeOptionData); } - void _updateData({String? name, Field? newField, List? typeOptionData}) { + void _updateData({String? newName, Field? newField, List? newTypeOptionData}) { _data = _data.rebuild((rebuildData) { - if (name != null) { + if (newName != null) { rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) { - rebuildField.name = name; + rebuildField.name = newName; }); } @@ -265,8 +251,8 @@ class GridFieldContext { rebuildData.field_2 = newField; } - if (typeOptionData != null) { - rebuildData.typeOptionData = typeOptionData; + if (newTypeOptionData != null) { + rebuildData.typeOptionData = newTypeOptionData; } }); @@ -287,7 +273,7 @@ class GridFieldContext { (fieldTypeOptionData) { _updateData( newField: fieldTypeOptionData.field_2, - typeOptionData: fieldTypeOptionData.typeOptionData, + newTypeOptionData: fieldTypeOptionData.typeOptionData, ); }, (err) { 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 9eec395ce0..48866457f7 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 @@ -64,7 +64,7 @@ class GridFieldCell extends StatelessWidget { FieldEditor( gridId: state.gridId, fieldName: state.field.name, - contextLoader: DefaultFieldContextLoader( + contextLoader: FieldContextLoader( gridId: state.gridId, field: state.field, ), 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 b3d96949f0..3390351663 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 @@ -14,7 +14,7 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate { final String gridId; final String fieldName; - final FieldContextLoader contextLoader; + final IFieldContextLoader contextLoader; const FieldEditor({ required this.gridId, required this.fieldName, @@ -97,7 +97,6 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder( - buildWhen: (p, c) => p.name != c.name, builder: (context, state) { return FieldNameTextField( name: state.name, 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 80cb327379..acc1256cbc 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 @@ -3,7 +3,7 @@ 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 { +class FieldNameTextField extends StatefulWidget { final void Function(String) onNameChanged; final String name; final String errorText; @@ -14,19 +14,41 @@ class FieldNameTextField extends StatelessWidget { Key? key, }) : super(key: key); + @override + State createState() => _FieldNameTextFieldState(); +} + +class _FieldNameTextFieldState extends State { + late String name; + TextEditingController controller = TextEditingController(); + + @override + void initState() { + controller.text = widget.name; + super.initState(); + } + @override Widget build(BuildContext context) { final theme = context.watch(); return RoundedInputField( height: 36, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500), - initialValue: name, + controller: controller, normalBorderColor: theme.shader4, errorBorderColor: theme.red, focusBorderColor: theme.main1, cursorColor: theme.main1, - errorText: errorText, - onChanged: onNameChanged, + errorText: widget.errorText, + onChanged: widget.onNameChanged, ); } + + @override + void didUpdateWidget(covariant FieldNameTextField oldWidget) { + controller.text = widget.name; + controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length)); + + super.didUpdateWidget(oldWidget); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index c8672d4ae3..41cbcb1cc1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -179,7 +179,7 @@ class _RowDetailCell extends StatelessWidget { FieldEditor( gridId: gridCell.gridId, fieldName: gridCell.field.name, - contextLoader: DefaultFieldContextLoader( + contextLoader: FieldContextLoader( gridId: gridCell.gridId, field: gridCell.field, ), 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 ec5ca40b1e..c971b48479 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 @@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget { FieldEditor( gridId: gridId, fieldName: field.name, - contextLoader: DefaultFieldContextLoader(gridId: gridId, field: field), + contextLoader: FieldContextLoader(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ); 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 95c17f46cf..bf4964054e 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 @@ -188,6 +188,23 @@ class GridEventGetFieldTypeOption { } } +class GridEventCreateFieldTypeOption { + EditFieldPayload request; + GridEventCreateFieldTypeOption(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = GridEvent.CreateFieldTypeOption.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (okBytes) => left(FieldTypeOptionData.fromBuffer(okBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class GridEventNewSelectOption { CreateSelectOptionPayload request; GridEventNewSelectOption(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 ae450b2e6d..a1ecd8c059 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 @@ -490,21 +490,12 @@ class GetEditFieldContextPayload extends $pb.GeneratedMessage { void clearFieldType() => clearField(3); } -enum EditFieldPayload_OneOfFieldId { - fieldId, - notSet -} - class EditFieldPayload extends $pb.GeneratedMessage { - static const $core.Map<$core.int, EditFieldPayload_OneOfFieldId> _EditFieldPayload_OneOfFieldIdByTag = { - 2 : EditFieldPayload_OneOfFieldId.fieldId, - 0 : EditFieldPayload_OneOfFieldId.notSet - }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'EditFieldPayload', 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') ..e(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: FieldType.RichText, valueOf: FieldType.valueOf, enumValues: FieldType.values) + ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'createIfNotExist') ..hasRequiredFields = false ; @@ -513,6 +504,7 @@ class EditFieldPayload extends $pb.GeneratedMessage { $core.String? gridId, $core.String? fieldId, FieldType? fieldType, + $core.bool? createIfNotExist, }) { final _result = create(); if (gridId != null) { @@ -524,6 +516,9 @@ class EditFieldPayload extends $pb.GeneratedMessage { if (fieldType != null) { _result.fieldType = fieldType; } + if (createIfNotExist != null) { + _result.createIfNotExist = createIfNotExist; + } return _result; } factory EditFieldPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -547,9 +542,6 @@ class EditFieldPayload extends $pb.GeneratedMessage { static EditFieldPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static EditFieldPayload? _defaultInstance; - EditFieldPayload_OneOfFieldId whichOneOfFieldId() => _EditFieldPayload_OneOfFieldIdByTag[$_whichOneof(0)]!; - void clearOneOfFieldId() => clearField($_whichOneof(0)); - @$pb.TagNumber(1) $core.String get gridId => $_getSZ(0); @$pb.TagNumber(1) @@ -576,6 +568,15 @@ class EditFieldPayload extends $pb.GeneratedMessage { $core.bool hasFieldType() => $_has(2); @$pb.TagNumber(3) void clearFieldType() => clearField(3); + + @$pb.TagNumber(4) + $core.bool get createIfNotExist => $_getBF(3); + @$pb.TagNumber(4) + set createIfNotExist($core.bool v) { $_setBool(3, v); } + @$pb.TagNumber(4) + $core.bool hasCreateIfNotExist() => $_has(3); + @$pb.TagNumber(4) + void clearCreateIfNotExist() => clearField(4); } class FieldTypeOptionContext 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 78e834edb7..3a925cb282 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 @@ -117,16 +117,14 @@ 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, '9': 0, '10': 'fieldId'}, + 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'}, - ], - '8': const [ - const {'1': 'one_of_field_id'}, + const {'1': 'create_if_not_exist', '3': 4, '4': 1, '5': 8, '10': 'createIfNotExist'}, ], }; /// Descriptor for `EditFieldPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List editFieldPayloadDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIbCghmaWVsZF9pZBgCIAEoCUgAUgdmaWVsZElkEikKCmZpZWxkX3R5cGUYAyABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZUIRCg9vbmVfb2ZfZmllbGRfaWQ='); +final $typed_data.Uint8List editFieldPayloadDescriptor = $convert.base64Decode('ChBFZGl0RmllbGRQYXlsb2FkEhcKB2dyaWRfaWQYASABKAlSBmdyaWRJZBIZCghmaWVsZF9pZBgCIAEoCVIHZmllbGRJZBIpCgpmaWVsZF90eXBlGAMgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSLQoTY3JlYXRlX2lmX25vdF9leGlzdBgEIAEoCFIQY3JlYXRlSWZOb3RFeGlzdA=='); @$core.Deprecated('Use fieldTypeOptionContextDescriptor instead') const FieldTypeOptionContext$json = const { '1': 'FieldTypeOptionContext', 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 f9945ab604..341dcf8d6a 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 @@ -21,6 +21,7 @@ class GridEvent extends $pb.ProtobufEnum { static const GridEvent DuplicateField = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField'); static const GridEvent MoveItem = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MoveItem'); static const GridEvent GetFieldTypeOption = GridEvent._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFieldTypeOption'); + static const GridEvent CreateFieldTypeOption = GridEvent._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateFieldTypeOption'); static const GridEvent NewSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewSelectOption'); static const GridEvent GetSelectOptionCellData = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptionCellData'); static const GridEvent UpdateSelectOption = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateSelectOption'); @@ -46,6 +47,7 @@ class GridEvent extends $pb.ProtobufEnum { DuplicateField, MoveItem, GetFieldTypeOption, + CreateFieldTypeOption, NewSelectOption, GetSelectOptionCellData, UpdateSelectOption, 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 89842a54d0..58a712a4da 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 @@ -23,6 +23,7 @@ const GridEvent$json = const { const {'1': 'DuplicateField', '2': 21}, const {'1': 'MoveItem', '2': 22}, const {'1': 'GetFieldTypeOption', '2': 23}, + const {'1': 'CreateFieldTypeOption', '2': 24}, const {'1': 'NewSelectOption', '2': 30}, const {'1': 'GetSelectOptionCellData', '2': 31}, const {'1': 'UpdateSelectOption', '2': 32}, @@ -39,4 +40,4 @@ const GridEvent$json = const { }; /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSDAoITW92ZUl0ZW0QFhIWChJHZXRGaWVsZFR5cGVPcHRpb24QFxITCg9OZXdTZWxlY3RPcHRpb24QHhIbChdHZXRTZWxlY3RPcHRpb25DZWxsRGF0YRAfEhYKElVwZGF0ZVNlbGVjdE9wdGlvbhAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSGgoWVXBkYXRlU2VsZWN0T3B0aW9uQ2VsbBBIEhIKDlVwZGF0ZURhdGVDZWxsEFASEwoPR2V0RGF0ZUNlbGxEYXRhEFo='); +final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSDAoITW92ZUl0ZW0QFhIWChJHZXRGaWVsZFR5cGVPcHRpb24QFxIZChVDcmVhdGVGaWVsZFR5cGVPcHRpb24QGBITCg9OZXdTZWxlY3RPcHRpb24QHhIbChdHZXRTZWxlY3RPcHRpb25DZWxsRGF0YRAfEhYKElVwZGF0ZVNlbGVjdE9wdGlvbhAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSGgoWVXBkYXRlU2VsZWN0T3B0aW9uQ2VsbBBIEhIKDlVwZGF0ZURhdGVDZWxsEFASEwoPR2V0RGF0ZUNlbGxEYXRhEFo='); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index a8c8b99e68..724d898d31 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -2,7 +2,6 @@ use crate::manager::GridManager; use crate::services::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::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; @@ -100,15 +99,24 @@ pub(crate) async fn switch_to_field_handler( manager: AppData>, ) -> DataResult { let params: EditFieldParams = data.into_inner().try_into()?; - if params.field_id.is_none() { - return Err(ErrorCode::FieldIdIsEmpty.into()); - } - let field_id = params.field_id.unwrap(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - editor.switch_to_field_type(&field_id, ¶ms.field_type).await?; - let field_meta = editor.get_field_meta(&field_id).await; - let data = - make_field_type_option_data(¶ms.grid_id, Some(field_id), params.field_type, editor, field_meta).await?; + editor + .switch_to_field_type(¶ms.field_id, ¶ms.field_type) + .await?; + + // Get the FieldMeta with field_id, if it doesn't exist, we create the default FieldMeta from the FieldType. + let field_meta = editor + .get_field_meta(¶ms.field_id) + .await + .unwrap_or(editor.next_field_meta(¶ms.field_type).await?); + + let type_option_data = get_type_option_data(&field_meta, ¶ms.field_type).await?; + let data = FieldTypeOptionData { + grid_id: params.grid_id, + field: field_meta.into(), + type_option_data, + }; + data_result(data) } @@ -123,6 +131,7 @@ pub(crate) async fn duplicate_field_handler( Ok(()) } +/// Return the FieldTypeOptionData if the Field exists otherwise return record not found error. #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_field_type_option_data_handler( data: Data, @@ -130,7 +139,29 @@ pub(crate) async fn get_field_type_option_data_handler( ) -> DataResult { let params: EditFieldParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let field_meta = get_or_create_field_meta(params.field_id, ¶ms.field_type, editor).await?; + match editor.get_field_meta(¶ms.field_id).await { + None => Err(FlowyError::record_not_found()), + Some(field_meta) => { + let type_option_data = get_type_option_data(&field_meta, &field_meta.field_type).await?; + let data = FieldTypeOptionData { + grid_id: params.grid_id, + field: field_meta.into(), + type_option_data, + }; + data_result(data) + } + } +} + +/// Create FieldMeta and save it. Return the FieldTypeOptionData. +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn create_field_type_option_data_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: CreateFieldParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(¶ms.grid_id)?; + let field_meta = editor.create_next_field_meta(¶ms.field_type).await?; let type_option_data = get_type_option_data(&field_meta, &field_meta.field_type).await?; data_result(FieldTypeOptionData { @@ -151,23 +182,6 @@ pub(crate) async fn move_item_handler( Ok(()) } -async fn make_field_type_option_data( - 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 type_option_data = get_type_option_data(&field_meta, &field_type).await?; - - Ok(FieldTypeOptionData { - grid_id: grid_id.to_string(), - field: field_meta.into(), - type_option_data, - }) -} - /// The FieldMeta contains multiple data, each of them belongs to a specific FieldType. async fn get_type_option_data(field_meta: &FieldMeta, field_type: &FieldType) -> FlowyResult> { let s = field_meta @@ -179,20 +193,6 @@ async fn get_type_option_data(field_meta: &FieldMeta, field_type: &FieldType) -> Ok(type_option_data) } -async fn get_or_create_field_meta( - field_id: Option, - field_type: &FieldType, - editor: Arc, -) -> FlowyResult { - match field_id { - None => editor.create_next_field_meta(field_type).await, - 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), - }, - } -} - #[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 fe749262ef..c740eee6d8 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -20,6 +20,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::DuplicateField, duplicate_field_handler) .event(GridEvent::MoveItem, move_item_handler) .event(GridEvent::GetFieldTypeOption, get_field_type_option_data_handler) + .event(GridEvent::CreateFieldTypeOption, create_field_type_option_data_handler) // Row .event(GridEvent::CreateRow, create_row_handler) .event(GridEvent::GetRow, get_row_handler) @@ -76,6 +77,9 @@ pub enum GridEvent { #[event(input = "EditFieldPayload", output = "FieldTypeOptionData")] GetFieldTypeOption = 23, + #[event(input = "EditFieldPayload", output = "FieldTypeOptionData")] + CreateFieldTypeOption = 24, + #[event(input = "CreateSelectOptionPayload", output = "SelectOption")] NewSelectOption = 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 f6c4861c29..6762254df7 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 @@ -36,6 +36,7 @@ pub enum GridEvent { DuplicateField = 21, MoveItem = 22, GetFieldTypeOption = 23, + CreateFieldTypeOption = 24, NewSelectOption = 30, GetSelectOptionCellData = 31, UpdateSelectOption = 32, @@ -68,6 +69,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { 21 => ::std::option::Option::Some(GridEvent::DuplicateField), 22 => ::std::option::Option::Some(GridEvent::MoveItem), 23 => ::std::option::Option::Some(GridEvent::GetFieldTypeOption), + 24 => ::std::option::Option::Some(GridEvent::CreateFieldTypeOption), 30 => ::std::option::Option::Some(GridEvent::NewSelectOption), 31 => ::std::option::Option::Some(GridEvent::GetSelectOptionCellData), 32 => ::std::option::Option::Some(GridEvent::UpdateSelectOption), @@ -97,6 +99,7 @@ impl ::protobuf::ProtobufEnum for GridEvent { GridEvent::DuplicateField, GridEvent::MoveItem, GridEvent::GetFieldTypeOption, + GridEvent::CreateFieldTypeOption, GridEvent::NewSelectOption, GridEvent::GetSelectOptionCellData, GridEvent::UpdateSelectOption, @@ -137,18 +140,18 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0fevent_map.proto*\xc1\x03\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\ + \n\x0fevent_map.proto*\xdc\x03\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\x19\n\x15UpdateFieldTypeOption\x10\x0c\x12\ \x0f\n\x0bInsertField\x10\r\x12\x0f\n\x0bDeleteField\x10\x0e\x12\x11\n\r\ SwitchToField\x10\x14\x12\x12\n\x0eDuplicateField\x10\x15\x12\x0c\n\x08M\ - oveItem\x10\x16\x12\x16\n\x12GetFieldTypeOption\x10\x17\x12\x13\n\x0fNew\ - SelectOption\x10\x1e\x12\x1b\n\x17GetSelectOptionCellData\x10\x1f\x12\ - \x16\n\x12UpdateSelectOption\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\x06\ - GetRow\x103\x12\r\n\tDeleteRow\x104\x12\x10\n\x0cDuplicateRow\x105\x12\ - \x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\x1a\n\x16UpdateSel\ - ectOptionCell\x10H\x12\x12\n\x0eUpdateDateCell\x10P\x12\x13\n\x0fGetDate\ - CellData\x10Zb\x06proto3\ + oveItem\x10\x16\x12\x16\n\x12GetFieldTypeOption\x10\x17\x12\x19\n\x15Cre\ + ateFieldTypeOption\x10\x18\x12\x13\n\x0fNewSelectOption\x10\x1e\x12\x1b\ + \n\x17GetSelectOptionCellData\x10\x1f\x12\x16\n\x12UpdateSelectOption\ + \x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\r\n\tDeleteR\ + ow\x104\x12\x10\n\x0cDuplicateRow\x105\x12\x0b\n\x07GetCell\x10F\x12\x0e\ + \n\nUpdateCell\x10G\x12\x1a\n\x16UpdateSelectOptionCell\x10H\x12\x12\n\ + \x0eUpdateDateCell\x10P\x12\x13\n\x0fGetDateCellData\x10Zb\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 a0c88a7187..10e98a2934 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 @@ -12,6 +12,7 @@ enum GridEvent { DuplicateField = 21; MoveItem = 22; GetFieldTypeOption = 23; + CreateFieldTypeOption = 24; NewSelectOption = 30; GetSelectOptionCellData = 31; UpdateSelectOption = 32; 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 b0695af1fd..44c826f31d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -121,12 +121,22 @@ impl ClientGridEditor { Ok(()) } - pub async fn create_next_field_meta(&self, field_type: &FieldType) -> FlowyResult { + pub async fn next_field_meta(&self, field_type: &FieldType) -> FlowyResult { let name = format!("Property {}", self.grid_pad.read().await.fields().len() + 1); let field_meta = FieldBuilder::from_field_type(field_type).name(&name).build(); Ok(field_meta) } + pub async fn create_next_field_meta(&self, field_type: &FieldType) -> FlowyResult { + let field_meta = self.next_field_meta(field_type).await?; + let _ = self + .modify(|grid| Ok(grid.create_field_meta(field_meta.clone(), None)?)) + .await?; + let _ = self.notify_did_insert_grid_field(&field_meta.id).await?; + + Ok(field_meta) + } + pub async fn contain_field(&self, field_id: &str) -> bool { self.grid_pad.read().await.contain_field(field_id) } 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 06b4f7222f..5cde193623 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -167,16 +167,19 @@ pub struct EditFieldPayload { #[pb(index = 1)] pub grid_id: String, - #[pb(index = 2, one_of)] - pub field_id: Option, + #[pb(index = 2)] + pub field_id: String, #[pb(index = 3)] pub field_type: FieldType, + + #[pb(index = 4)] + pub create_if_not_exist: bool, } pub struct EditFieldParams { pub grid_id: String, - pub field_id: Option, + pub field_id: String, pub field_type: FieldType, } @@ -185,10 +188,28 @@ impl TryInto for EditFieldPayload { fn try_into(self) -> Result { let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - // let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; + let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?; Ok(EditFieldParams { grid_id: grid_id.0, - field_id: self.field_id, + field_id: field_id.0, + field_type: self.field_type, + }) + } +} + +pub struct CreateFieldParams { + pub grid_id: String, + pub field_type: FieldType, +} + +impl TryInto for EditFieldPayload { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + + Ok(CreateFieldParams { + grid_id: grid_id.0, field_type: self.field_type, }) } 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 6df3c847f0..0cda103da8 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 @@ -1644,9 +1644,9 @@ impl ::protobuf::reflect::ProtobufValue for GetEditFieldContextPayload { pub struct EditFieldPayload { // message fields pub grid_id: ::std::string::String, + pub field_id: ::std::string::String, pub field_type: FieldType, - // message oneof groups - pub one_of_field_id: ::std::option::Option, + pub create_if_not_exist: bool, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -1658,11 +1658,6 @@ impl<'a> ::std::default::Default for &'a EditFieldPayload { } } -#[derive(Clone,PartialEq,Debug)] -pub enum EditFieldPayload_oneof_one_of_field_id { - field_id(::std::string::String), -} - impl EditFieldPayload { pub fn new() -> EditFieldPayload { ::std::default::Default::default() @@ -1698,49 +1693,26 @@ impl EditFieldPayload { pub fn get_field_id(&self) -> &str { - match self.one_of_field_id { - ::std::option::Option::Some(EditFieldPayload_oneof_one_of_field_id::field_id(ref v)) => v, - _ => "", - } + &self.field_id } 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(EditFieldPayload_oneof_one_of_field_id::field_id(..)) => true, - _ => false, - } + self.field_id.clear(); } // 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(EditFieldPayload_oneof_one_of_field_id::field_id(v)) + 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 { - if let ::std::option::Option::Some(EditFieldPayload_oneof_one_of_field_id::field_id(_)) = self.one_of_field_id { - } else { - self.one_of_field_id = ::std::option::Option::Some(EditFieldPayload_oneof_one_of_field_id::field_id(::std::string::String::new())); - } - match self.one_of_field_id { - ::std::option::Option::Some(EditFieldPayload_oneof_one_of_field_id::field_id(ref mut v)) => v, - _ => panic!(), - } + &mut self.field_id } // 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(EditFieldPayload_oneof_one_of_field_id::field_id(v)) => v, - _ => panic!(), - } - } else { - ::std::string::String::new() - } + ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) } // .FieldType field_type = 3; @@ -1757,6 +1729,21 @@ impl EditFieldPayload { pub fn set_field_type(&mut self, v: FieldType) { self.field_type = v; } + + // bool create_if_not_exist = 4; + + + pub fn get_create_if_not_exist(&self) -> bool { + self.create_if_not_exist + } + pub fn clear_create_if_not_exist(&mut self) { + self.create_if_not_exist = false; + } + + // Param is passed by value, moved + pub fn set_create_if_not_exist(&mut self, v: bool) { + self.create_if_not_exist = v; + } } impl ::protobuf::Message for EditFieldPayload { @@ -1772,14 +1759,18 @@ impl ::protobuf::Message for EditFieldPayload { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?; }, 2 => { - 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(EditFieldPayload_oneof_one_of_field_id::field_id(is.read_string()?)); + ::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)? }, + 4 => { + 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.create_if_not_exist = tmp; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -1795,15 +1786,14 @@ impl ::protobuf::Message for EditFieldPayload { 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 != FieldType::RichText { 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 { - &EditFieldPayload_oneof_one_of_field_id::field_id(ref v) => { - my_size += ::protobuf::rt::string_size(2, &v); - }, - }; + if self.create_if_not_exist != false { + my_size += 2; } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1814,15 +1804,14 @@ impl ::protobuf::Message for EditFieldPayload { 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 != FieldType::RichText { 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 { - &EditFieldPayload_oneof_one_of_field_id::field_id(ref v) => { - os.write_string(2, v)?; - }, - }; + if self.create_if_not_exist != false { + os.write_bool(4, self.create_if_not_exist)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1867,16 +1856,21 @@ impl ::protobuf::Message for EditFieldPayload { |m: &EditFieldPayload| { &m.grid_id }, |m: &mut EditFieldPayload| { &mut m.grid_id }, )); - fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", - EditFieldPayload::has_field_id, - EditFieldPayload::get_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 }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( + "create_if_not_exist", + |m: &EditFieldPayload| { &m.create_if_not_exist }, + |m: &mut EditFieldPayload| { &mut m.create_if_not_exist }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "EditFieldPayload", fields, @@ -1894,8 +1888,9 @@ impl ::protobuf::Message for EditFieldPayload { impl ::protobuf::Clear for EditFieldPayload { fn clear(&mut self) { self.grid_id.clear(); - self.one_of_field_id = ::std::option::Option::None; + self.field_id.clear(); self.field_type = FieldType::RichText; + self.create_if_not_exist = false; self.unknown_fields.clear(); } } @@ -8311,83 +8306,84 @@ static file_descriptor_proto_data: &'static [u8] = b"\ extPayload\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\"\ - \x86\x01\n\x10EditFieldPayload\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\x0fo\ - ne_of_field_id\"\x82\x01\n\x16FieldTypeOptionContext\x12\x17\n\x07grid_i\ - d\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\"v\n\x13FieldTypeOptionData\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\x0etype\ - OptionData\"-\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\x08RowOrder\x12\x15\n\x06ro\ - w_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_b\ - y_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFiel\ - dId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellBy\ - FieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05va\ - lue\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedR\ - ow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11Re\ - peatedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\ - \x05items\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\ - \tR\x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trow\ - Orders\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.Row\ - OrderR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\ - \x0e\n\x0cone_of_index\"Q\n\x0fUpdatedRowOrder\x12&\n\trow_order\x18\x01\ - \x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x03row\x18\x02\x20\x01(\ - \x0b2\x04.RowR\x03row\"\xc6\x01\n\x11GridRowsChangeset\x12\x19\n\x08bloc\ - k_id\x18\x01\x20\x01(\tR\x07blockId\x123\n\rinserted_rows\x18\x02\x20\ - \x03(\x0b2\x0e.IndexRowOrderR\x0cinsertedRows\x12,\n\x0cdeleted_rows\x18\ - \x03\x20\x03(\x0b2\t.RowOrderR\x0bdeletedRows\x123\n\x0cupdated_rows\x18\ - \x04\x20\x03(\x0b2\x10.UpdatedRowOrderR\x0bupdatedRows\"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\"O\n\x04Cell\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ - \x07content\x12\x12\n\x04data\x18\x03\x20\x01(\tR\x04data\"+\n\x0cRepeat\ - edCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\ - \x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\ - \x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\ - \x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10\ - CreateRowPayload\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\x12InsertFieldPayload\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\x0etype\ - OptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartField\ - IdB\x17\n\x15one_of_start_field_id\"|\n\x1cUpdateFieldTypeOptionPayload\ - \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_i\ - d\x18\x02\x20\x01(\tR\x07fieldId\x12(\n\x10type_option_data\x18\x03\x20\ - \x01(\x0cR\x0etypeOptionData\"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\x16QueryGridBlocksPay\ - load\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_\ - orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"\xa8\ - \x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\x01(\t\ - R\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\x10type_optio\ - n_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_opt\ - ion_data\"\x9c\x01\n\x0fMoveItemPayload\x12\x17\n\x07grid_id\x18\x01\x20\ - \x01(\tR\x06gridId\x12\x17\n\x07item_id\x18\x02\x20\x01(\tR\x06itemId\ - \x12\x1d\n\nfrom_index\x18\x03\x20\x01(\x05R\tfromIndex\x12\x19\n\x08to_\ - index\x18\x04\x20\x01(\x05R\x07toIndex\x12\x1d\n\x02ty\x18\x05\x20\x01(\ - \x0e2\r.MoveItemTypeR\x02ty\"\xb3\x01\n\rCellChangeset\x12\x17\n\x07grid\ - _id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\t\ - R\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x126\n\ - \x16cell_content_changeset\x18\x04\x20\x01(\tH\0R\x14cellContentChangese\ - tB\x1f\n\x1done_of_cell_content_changeset**\n\x0cMoveItemType\x12\r\n\tM\ - oveField\x10\0\x12\x0b\n\x07MoveRow\x10\x01*d\n\tFieldType\x12\x0c\n\x08\ - RichText\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\ + \xa0\x01\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\x12-\n\x13creat\ + e_if_not_exist\x18\x04\x20\x01(\x08R\x10createIfNotExist\"\x82\x01\n\x16\ + FieldTypeOptionContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridI\ + d\x12%\n\ngrid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\ + \x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"v\n\x13Fie\ + ldTypeOptionData\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\"-\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\"U\n\x0eGridBlockO\ + rder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_or\ + ders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"_\n\rIndexRowOrder\ + \x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\ + \n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\x0cone_of_index\"Q\ + \n\x0fUpdatedRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrder\ + R\x08rowOrder\x12\x16\n\x03row\x18\x02\x20\x01(\x0b2\x04.RowR\x03row\"\ + \xc6\x01\n\x11GridRowsChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\t\ + R\x07blockId\x123\n\rinserted_rows\x18\x02\x20\x03(\x0b2\x0e.IndexRowOrd\ + erR\x0cinsertedRows\x12,\n\x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOr\ + derR\x0bdeletedRows\x123\n\x0cupdated_rows\x18\x04\x20\x03(\x0b2\x10.Upd\ + atedRowOrderR\x0bupdatedRows\"E\n\tGridBlock\x12\x0e\n\x02id\x18\x01\x20\ + \x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trow\ + Orders\"O\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\ + \x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\x12\x12\n\x04data\ + \x18\x03\x20\x01(\tR\x04data\"+\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\x05va\ + lue\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\x12Ins\ + ertFieldPayload\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_fie\ + ld_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_fiel\ + d_id\"|\n\x1cUpdateFieldTypeOptionPayload\x12\x17\n\x07grid_id\x18\x01\ + \x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fiel\ + dId\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"\ + d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gri\ + dId\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\"\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\0\ + R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfie\ + ld_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06\ + frozen\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\"\x9c\x01\n\x0fMoveIt\ + emPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x17\n\ + \x07item_id\x18\x02\x20\x01(\tR\x06itemId\x12\x1d\n\nfrom_index\x18\x03\ + \x20\x01(\x05R\tfromIndex\x12\x19\n\x08to_index\x18\x04\x20\x01(\x05R\ + \x07toIndex\x12\x1d\n\x02ty\x18\x05\x20\x01(\x0e2\r.MoveItemTypeR\x02ty\ + \"\xb3\x01\n\rCellChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06\ + gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08fie\ + ld_id\x18\x03\x20\x01(\tR\x07fieldId\x126\n\x16cell_content_changeset\ + \x18\x04\x20\x01(\tH\0R\x14cellContentChangesetB\x1f\n\x1done_of_cell_co\ + ntent_changeset**\n\x0cMoveItemType\x12\r\n\tMoveField\x10\0\x12\x0b\n\ + \x07MoveRow\x10\x01*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/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index 99024d3841..a2d74e96a3 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 @@ -35,8 +35,9 @@ message GetEditFieldContextPayload { } message EditFieldPayload { string grid_id = 1; - oneof one_of_field_id { string field_id = 2; }; + string field_id = 2; FieldType field_type = 3; + bool create_if_not_exist = 4; } message FieldTypeOptionContext { string grid_id = 1; From e8540b4b789ef55408c56322278565782da346f2 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 19 May 2022 10:53:11 +0800 Subject: [PATCH 8/8] chore: fix potential issue when call notifier after it was disposed --- .../grid/cell/cell_service/data_cache.dart | 2 + .../workspace/application/grid/grid_bloc.dart | 2 +- .../application/grid/grid_header_bloc.dart | 2 +- .../application/grid/grid_service.dart | 43 ++++++++++--------- .../grid/setting/property_bloc.dart | 2 +- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_cache.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_cache.dart index 409c236881..5e09573506 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_cache.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_cache.dart @@ -104,6 +104,8 @@ class GridCellCache { } Future dispose() async { + _fieldListenerByFieldId.clear(); + _cellDataByFieldId.clear(); fieldDelegate.dispose(); } } 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 7f35d50978..357ccadcd9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -93,7 +93,7 @@ class GridBloc extends Bloc { emit(state.copyWith( grid: Some(grid), - fields: fieldCache.clonedFields, + fields: fieldCache.fields, rows: rowCache.clonedRows, loadingState: GridLoadingState.finish(left(unit)), )); diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart index 3195715413..526dda9085 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_header_bloc.dart @@ -15,7 +15,7 @@ class GridHeaderBloc extends Bloc { GridHeaderBloc({ required this.gridId, required this.fieldCache, - }) : super(GridHeaderState.initial(fieldCache.clonedFields)) { + }) : super(GridHeaderState.initial(fieldCache.fields)) { on( (event, emit) async { await event.map( 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 98827e6b72..4ed54c5f3b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -59,7 +59,7 @@ typedef ChangesetListener = void Function(GridFieldChangeset); class GridFieldCache { final String gridId; late final GridFieldsListener _fieldListener; - final FieldsNotifier _fieldNotifier = FieldsNotifier(); + FieldsNotifier? _fieldNotifier = FieldsNotifier(); final List _changesetListener = []; GridFieldCache({required this.gridId}) { @@ -81,15 +81,16 @@ class GridFieldCache { Future dispose() async { await _fieldListener.stop(); - _fieldNotifier.dispose(); + _fieldNotifier?.dispose(); + _fieldNotifier = null; } - UnmodifiableListView get unmodifiableFields => UnmodifiableListView(_fieldNotifier.fields); + UnmodifiableListView get unmodifiableFields => UnmodifiableListView(_fieldNotifier?.fields ?? []); - List get clonedFields => [..._fieldNotifier.fields]; + List get fields => [..._fieldNotifier?.fields ?? []]; set fields(List fields) { - _fieldNotifier.fields = [...fields]; + _fieldNotifier?.fields = [...fields]; } VoidCallback addListener( @@ -100,7 +101,7 @@ class GridFieldCache { } if (onChanged != null) { - onChanged(clonedFields); + onChanged(fields); } if (listener != null) { @@ -108,12 +109,12 @@ class GridFieldCache { } } - _fieldNotifier.addListener(f); + _fieldNotifier?.addListener(f); return f; } void removeListener(VoidCallback f) { - _fieldNotifier.removeListener(f); + _fieldNotifier?.removeListener(f); } void addChangesetListener(ChangesetListener listener) { @@ -131,43 +132,43 @@ class GridFieldCache { if (deletedFields.isEmpty) { return; } - final List fields = _fieldNotifier.fields; + final List newFields = fields; final Map deletedFieldMap = { for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder }; - fields.retainWhere((field) => (deletedFieldMap[field.id] == null)); - _fieldNotifier.fields = fields; + newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); + _fieldNotifier?.fields = newFields; } void _insertFields(List insertedFields) { if (insertedFields.isEmpty) { return; } - final List fields = _fieldNotifier.fields; + final List newFields = fields; for (final indexField in insertedFields) { - if (fields.length > indexField.index) { - fields.insert(indexField.index, indexField.field_1); + if (newFields.length > indexField.index) { + newFields.insert(indexField.index, indexField.field_1); } else { - fields.add(indexField.field_1); + newFields.add(indexField.field_1); } } - _fieldNotifier.fields = fields; + _fieldNotifier?.fields = newFields; } void _updateFields(List updatedFields) { if (updatedFields.isEmpty) { return; } - final List fields = _fieldNotifier.fields; + final List newFields = fields; for (final updatedField in updatedFields) { - final index = fields.indexWhere((field) => field.id == updatedField.id); + final index = newFields.indexWhere((field) => field.id == updatedField.id); if (index != -1) { - fields.removeAt(index); - fields.insert(index, updatedField); + newFields.removeAt(index); + newFields.insert(index, updatedField); } } - _fieldNotifier.fields = fields; + _fieldNotifier?.fields = newFields; } } 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 42d2327f5b..a88423e56d 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 @@ -14,7 +14,7 @@ class GridPropertyBloc extends Bloc { GridPropertyBloc({required String gridId, required GridFieldCache fieldCache}) : _fieldCache = fieldCache, - super(GridPropertyState.initial(gridId, fieldCache.clonedFields)) { + super(GridPropertyState.initial(gridId, fieldCache.fields)) { on( (event, emit) async { await event.map(