diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/cell_option_pannel_bloc.dart similarity index 63% rename from frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/type_option/cell_option_pannel_bloc.dart index ccd0c47bab..e8114b3d53 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/cell_option_pannel_bloc.dart @@ -4,11 +4,11 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:protobuf/protobuf.dart'; import 'package:dartz/dartz.dart'; -part 'edit_option_bloc.freezed.dart'; +part 'cell_option_pannel_bloc.freezed.dart'; -class EditOptionBloc extends Bloc { - EditOptionBloc({required SelectOption option}) : super(EditOptionState.initial(option)) { - on( +class CellOptionPannelBloc extends Bloc { + CellOptionPannelBloc({required SelectOption option}) : super(CellOptionPannelState.initial(option)) { + on( (event, emit) async { event.map( updateName: (_UpdateName value) { @@ -46,20 +46,20 @@ class EditOptionBloc extends Bloc { } @freezed -class EditOptionEvent with _$EditOptionEvent { - const factory EditOptionEvent.updateName(String name) = _UpdateName; - const factory EditOptionEvent.updateColor(SelectOptionColor color) = _UpdateColor; - const factory EditOptionEvent.delete() = _Delete; +class CellOptionPannelEvent with _$CellOptionPannelEvent { + const factory CellOptionPannelEvent.updateName(String name) = _UpdateName; + const factory CellOptionPannelEvent.updateColor(SelectOptionColor color) = _UpdateColor; + const factory CellOptionPannelEvent.delete() = _Delete; } @freezed -class EditOptionState with _$EditOptionState { - const factory EditOptionState({ +class CellOptionPannelState with _$CellOptionPannelState { + const factory CellOptionPannelState({ required SelectOption option, required Option deleted, }) = _EditOptionState; - factory EditOptionState.initial(SelectOption option) => EditOptionState( + factory CellOptionPannelState.initial(SelectOption option) => CellOptionPannelState( option: option, deleted: none(), ); diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart similarity index 60% rename from frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart rename to frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart index 715cde72d7..04ae02309d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart @@ -3,11 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; -part 'option_pannel_bloc.freezed.dart'; +part 'field_option_pannel_bloc.freezed.dart'; -class OptionPannelBloc extends Bloc { - OptionPannelBloc({required List options}) : super(OptionPannelState.initial(options)) { - on( +class FieldOptionPannelBloc extends Bloc { + FieldOptionPannelBloc({required List options}) : super(FieldOptionPannelState.initial(options)) { + on( (event, emit) async { await event.map( createOption: (_CreateOption value) async { @@ -37,25 +37,25 @@ class OptionPannelBloc extends Bloc { } @freezed -class OptionPannelEvent with _$OptionPannelEvent { - const factory OptionPannelEvent.createOption(String optionName) = _CreateOption; - const factory OptionPannelEvent.beginAddingOption() = _BeginAddingOption; - const factory OptionPannelEvent.endAddingOption() = _EndAddingOption; - const factory OptionPannelEvent.updateOption(SelectOption option) = _UpdateOption; - const factory OptionPannelEvent.deleteOption(SelectOption option) = _DeleteOption; +class FieldOptionPannelEvent with _$FieldOptionPannelEvent { + const factory FieldOptionPannelEvent.createOption(String optionName) = _CreateOption; + const factory FieldOptionPannelEvent.beginAddingOption() = _BeginAddingOption; + const factory FieldOptionPannelEvent.endAddingOption() = _EndAddingOption; + const factory FieldOptionPannelEvent.updateOption(SelectOption option) = _UpdateOption; + const factory FieldOptionPannelEvent.deleteOption(SelectOption option) = _DeleteOption; } @freezed -class OptionPannelState with _$OptionPannelState { - const factory OptionPannelState({ +class FieldOptionPannelState with _$FieldOptionPannelState { + const factory FieldOptionPannelState({ required List options, required bool isEditingOption, required Option newOptionName, required Option updateOption, required Option deleteOption, - }) = _OptionPannelState; + }) = _FieldOptionPannelState; - factory OptionPannelState.initial(List options) => OptionPannelState( + factory FieldOptionPannelState.initial(List options) => FieldOptionPannelState( options: options, isEditingOption: false, newOptionName: none(), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 12f1f514b6..dc8ffcdad1 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -3,7 +3,7 @@ import 'dart:collection'; import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/cell_option_pannel.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -225,7 +225,7 @@ class _SelectOptionCell extends StatelessWidget { } void _showEditOptionPannel(BuildContext context) { - final pannel = EditSelectOptionPannel( + final pannel = CellSelectOptionPannel( option: option, onDeleted: () { context.read().add(SelectOptionEditorEvent.deleteOption(option)); 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/cell_option_pannel.dart similarity index 88% 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/cell_option_pannel.dart index 1893a77846..9cc81a46b8 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/cell_option_pannel.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/cell_option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.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 CellSelectOptionPannel extends StatelessWidget { final SelectOption option; final VoidCallback onDeleted; final Function(SelectOption) onUpdated; - const EditSelectOptionPannel({ + const CellSelectOptionPannel({ required this.option, required this.onDeleted, required this.onUpdated, @@ -28,23 +28,23 @@ class EditSelectOptionPannel extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => EditOptionBloc(option: option), + create: (context) => CellOptionPannelBloc(option: option), child: MultiBlocListener( listeners: [ - BlocListener( + BlocListener( listenWhen: (p, c) => p.deleted != c.deleted, listener: (context, state) { state.deleted.fold(() => null, (_) => onDeleted()); }, ), - BlocListener( + BlocListener( listenWhen: (p, c) => p.option != c.option, listener: (context, state) { onUpdated(state.option); }, ), ], - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { List slivers = [ SliverToBoxAdapter(child: _OptionNameTextField(state.option.name)), @@ -82,7 +82,7 @@ class _DeleteTag extends StatelessWidget { hoverColor: theme.hover, leftIcon: svgWidget("grid/delete", color: theme.iconColor), onTap: () { - context.read().add(const EditOptionEvent.delete()); + context.read().add(const CellOptionPannelEvent.delete()); }, ), ); @@ -99,7 +99,9 @@ class _OptionNameTextField extends StatelessWidget { name: name, onCanceled: () {}, onDone: (optionName) { - context.read().add(EditOptionEvent.updateName(optionName)); + if (name != optionName) { + context.read().add(CellOptionPannelEvent.updateName(optionName)); + } }, ); } @@ -178,7 +180,7 @@ class _SelectOptionColorCell extends StatelessWidget { leftIcon: colorIcon, rightIcon: checkmark, onTap: () { - context.read().add(EditOptionEvent.updateColor(color)); + context.read().add(CellOptionPannelEvent.updateColor(color)); }, ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart similarity index 83% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart index 034accfb19..7247f81a77 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_infra/image.dart'; @@ -12,10 +12,10 @@ 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 'cell_option_pannel.dart'; import 'widget.dart'; -class OptionPannel extends StatelessWidget { +class FieldSelectOptionPannel extends StatelessWidget { final List options; final VoidCallback beginEdit; final Function(String optionName) createOptionCallback; @@ -23,7 +23,7 @@ class OptionPannel extends StatelessWidget { final Function(SelectOption) deleteOptionCallback; final TypeOptionOverlayDelegate overlayDelegate; - const OptionPannel({ + const FieldSelectOptionPannel({ required this.options, required this.beginEdit, required this.createOptionCallback, @@ -36,8 +36,8 @@ class OptionPannel extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => OptionPannelBloc(options: options), - child: BlocConsumer( + create: (context) => FieldOptionPannelBloc(options: options), + child: BlocConsumer( listener: (context, state) { if (state.isEditingOption) { beginEdit(); @@ -88,7 +88,7 @@ class OptionTitle extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); - return BlocBuilder( + return BlocBuilder( builder: (context, state) { List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)]; if (state.options.isNotEmpty) { @@ -105,7 +105,7 @@ class OptionTitle extends StatelessWidget { ), hoverColor: theme.hover, onTap: () { - context.read().add(const OptionPannelEvent.beginAddingOption()); + context.read().add(const FieldOptionPannelEvent.beginAddingOption()); }, ), ), @@ -127,7 +127,7 @@ class _OptionList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( buildWhen: (previous, current) { return previous.options != current.options; }, @@ -155,15 +155,15 @@ class _OptionList extends StatelessWidget { return _OptionCell( option: option, onEdited: (option) { - final pannel = EditSelectOptionPannel( + final pannel = CellSelectOptionPannel( option: option, onDeleted: () { delegate.hideOverlay(context); - context.read().add(OptionPannelEvent.deleteOption(option)); + context.read().add(FieldOptionPannelEvent.deleteOption(option)); }, onUpdated: (updatedOption) { delegate.hideOverlay(context); - context.read().add(OptionPannelEvent.updateOption(updatedOption)); + context.read().add(FieldOptionPannelEvent.updateOption(updatedOption)); }, ); delegate.showOverlay(context, pannel); @@ -208,7 +208,7 @@ class _AddOptionButton extends StatelessWidget { text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr(), fontSize: 12), hoverColor: theme.hover, onTap: () { - context.read().add(const OptionPannelEvent.beginAddingOption()); + context.read().add(const FieldOptionPannelEvent.beginAddingOption()); }, leftIcon: svgWidget("home/add", color: theme.iconColor), ), @@ -222,12 +222,13 @@ class _OptionNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { return NameTextField( - name: "", - onCanceled: () { - context.read().add(const OptionPannelEvent.endAddingOption()); - }, - onDone: (optionName) { - context.read().add(OptionPannelEvent.createOption(optionName)); - }); + name: "", + onCanceled: () { + context.read().add(const FieldOptionPannelEvent.endAddingOption()); + }, + onDone: (optionName) { + context.read().add(FieldOptionPannelEvent.createOption(optionName)); + }, + ); } } 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 11d2c866ce..873a63ceef 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 @@ -5,7 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'option_pannel.dart'; +import 'field_option_pannel.dart'; class MultiSelectTypeOptionBuilder extends TypeOptionBuilder { final MultiSelectTypeOptionWidget _widget; @@ -48,7 +48,7 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget { dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); }, builder: (context, state) { - return OptionPannel( + return FieldSelectOptionPannel( options: state.typeOption.options, beginEdit: () { overlayDelegate.hideOverlay(context); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart index ecc0dfc80a..ba2668f851 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 @@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'option_pannel.dart'; +import 'field_option_pannel.dart'; class SingleSelectTypeOptionBuilder extends TypeOptionBuilder { final SingleSelectTypeOptionWidget _widget; @@ -47,7 +47,7 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget { dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()); }, builder: (context, state) { - return OptionPannel( + return FieldSelectOptionPannel( options: state.typeOption.options, beginEdit: () { overlayDelegate.hideOverlay(context); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart index 6f4e86a4e1..12c1d4997b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart @@ -60,13 +60,12 @@ class _NameTextFieldState extends State { } void notifyDidEndEditing() { - if (_controller.text.isEmpty) { - if (isEdited) { + if (!_focusNode.hasFocus) { + if (_controller.text.isEmpty) { widget.onCanceled(); + } else { + widget.onDone(_controller.text); } - isEdited = true; - } else { - widget.onDone(_controller.text); } } } 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 05a82d9f13..06d7f2a1f1 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -113,7 +113,9 @@ impl ClientGridEditor { } pub async fn replace_field(&self, field_meta: FieldMeta) -> FlowyResult<()> { + let field_id = field_meta.id.clone(); let _ = self.modify(|pad| Ok(pad.replace_field(field_meta)?)).await?; + let _ = self.notify_did_update_field(&field_id).await?; Ok(()) }