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 new file mode 100644 index 0000000000..c7964573d3 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_cell_bloc.dart @@ -0,0 +1,66 @@ +import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +part 'field_cell_bloc.freezed.dart'; + +class FieldCellBloc extends Bloc { + final FieldListener _fieldListener; + + FieldCellBloc({ + required GridFieldCellContext cellContext, + }) : _fieldListener = FieldListener(fieldId: cellContext.field.id), + super(FieldCellState.initial(cellContext)) { + on( + (event, emit) async { + await event.map( + initial: (_InitialCell value) async { + _startListening(); + }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(field: value.field)); + }, + ); + }, + ); + } + + @override + Future close() async { + await _fieldListener.stop(); + return super.close(); + } + + void _startListening() { + _fieldListener.updateFieldNotifier.addPublishListener((result) { + result.fold( + (field) => add(FieldCellEvent.didReceiveFieldUpdate(field)), + (err) => Log.error(err), + ); + }); + _fieldListener.start(); + } +} + +@freezed +class FieldCellEvent with _$FieldCellEvent { + const factory FieldCellEvent.initial() = _InitialCell; + const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; +} + +@freezed +class FieldCellState with _$FieldCellState { + const factory FieldCellState({ + required String gridId, + required Field field, + }) = _FieldCellState; + + factory FieldCellState.initial(GridFieldCellContext cellContext) => FieldCellState( + gridId: cellContext.gridId, + field: cellContext.field, + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_option_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/edit_select_option_bloc.dart similarity index 62% 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/edit_select_option_bloc.dart index ccd0c47bab..2854fcf199 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/edit_select_option_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 'edit_select_option_bloc.freezed.dart'; -class EditOptionBloc extends Bloc { - EditOptionBloc({required SelectOption option}) : super(EditOptionState.initial(option)) { - on( +class EditSelectOptionBloc extends Bloc { + EditSelectOptionBloc({required SelectOption option}) : super(EditSelectOptionState.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 EditSelectOptionEvent with _$EditSelectOptionEvent { + const factory EditSelectOptionEvent.updateName(String name) = _UpdateName; + const factory EditSelectOptionEvent.updateColor(SelectOptionColor color) = _UpdateColor; + const factory EditSelectOptionEvent.delete() = _Delete; } @freezed -class EditOptionState with _$EditOptionState { - const factory EditOptionState({ +class EditSelectOptionState with _$EditSelectOptionState { + const factory EditSelectOptionState({ required SelectOption option, required Option deleted, - }) = _EditOptionState; + }) = _EditSelectOptionState; - factory EditOptionState.initial(SelectOption option) => EditOptionState( + factory EditSelectOptionState.initial(SelectOption option) => EditSelectOptionState( 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_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 3e6f5b1649..64e01bda53 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -37,7 +37,7 @@ class _SingleSelectCellState extends State { return SizedBox.expand( child: InkWell( onTap: () { - SelectOptionEditor.show(context, state.cellData, state.options, state.selectedOptions); + SelectOptionCellEditor.show(context, state.cellData, state.options, state.selectedOptions); }, child: Row(children: children), ), @@ -86,7 +86,7 @@ class _MultiSelectCellState extends State { return SizedBox.expand( child: InkWell( onTap: () { - SelectOptionEditor.show(context, state.cellData, state.options, state.selectedOptions); + SelectOptionCellEditor.show(context, state.cellData, state.options, state.selectedOptions); }, child: Row(children: children), ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 12f1f514b6..b6f4001c59 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 @@ -18,19 +18,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'package:styled_widget/styled_widget.dart'; import 'package:textfield_tags/textfield_tags.dart'; import 'extension.dart'; const double _editorPannelWidth = 300; -class SelectOptionEditor extends StatelessWidget with FlowyOverlayDelegate { +class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { final CellData cellData; final List options; final List selectedOptions; - const SelectOptionEditor({ + const SelectOptionCellEditor({ required this.cellData, required this.options, required this.selectedOptions, @@ -38,7 +37,7 @@ class SelectOptionEditor extends StatelessWidget with FlowyOverlayDelegate { }) : super(key: key); static String identifier() { - return (SelectOptionEditor).toString(); + return (SelectOptionCellEditor).toString(); } @override @@ -73,8 +72,8 @@ class SelectOptionEditor extends StatelessWidget with FlowyOverlayDelegate { List options, List selectedOptions, ) { - SelectOptionEditor.hide(context); - final editor = SelectOptionEditor( + SelectOptionCellEditor.remove(context); + final editor = SelectOptionCellEditor( cellData: cellData, options: options, selectedOptions: selectedOptions, @@ -86,14 +85,14 @@ class SelectOptionEditor extends StatelessWidget with FlowyOverlayDelegate { child: SizedBox(width: _editorPannelWidth, child: editor), constraints: BoxConstraints.loose(const Size(_editorPannelWidth, 300)), ), - identifier: SelectOptionEditor.identifier(), + identifier: SelectOptionCellEditor.identifier(), anchorContext: context, anchorDirection: AnchorDirection.bottomWithCenterAligned, delegate: editor, ); } - static void hide(BuildContext context) { + static void remove(BuildContext context) { FlowyOverlay.of(context).remove(identifier()); } @@ -208,7 +207,7 @@ class _SelectOptionCell extends StatelessWidget { if (onHover) { children.add(FlowyIconButton( width: 30, - onPressed: () => _showEditOptionPannel(context), + onPressed: () => _showEditPannel(context), iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4), icon: svgWidget("editor/details", color: theme.iconColor), )); @@ -224,7 +223,7 @@ class _SelectOptionCell extends StatelessWidget { ); } - void _showEditOptionPannel(BuildContext context) { + void _showEditPannel(BuildContext context) { final pannel = EditSelectOptionPannel( option: option, onDeleted: () { @@ -233,9 +232,9 @@ class _SelectOptionCell extends StatelessWidget { onUpdated: (updatedOption) { context.read().add(SelectOptionEditorEvent.updateOption(updatedOption)); }, - // key: ValueKey(option.id), + key: ValueKey(option.id), // Use ValueKey to refresh the UI, otherwise, it will remain the old value. ); - final overlayIdentifier = pannel.toString(); + final overlayIdentifier = (EditSelectOptionPannel).toString(); FlowyOverlay.of(context).remove(overlayIdentifier); 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 89cd0b60ff..79e706085f 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 @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/grid/field/field_cell_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/image.dart'; @@ -12,46 +13,55 @@ import 'field_cell_action_sheet.dart'; import 'field_editor.dart'; class GridFieldCell extends StatelessWidget { - final GridFieldCellContext fieldCellContext; - const GridFieldCell(this.fieldCellContext, {Key? key}) : super(key: key); + final GridFieldCellContext cellContext; + const GridFieldCell(this.cellContext, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); - final field = fieldCellContext.field; - final button = FlowyButton( - hoverColor: theme.hover, - onTap: () => _showActionSheet(context), - rightIcon: svgWidget("editor/details", color: theme.iconColor), - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), - text: FlowyText.medium(field.name, fontSize: 12), - padding: GridSize.cellContentInsets, - ); + return BlocProvider( + create: (context) => FieldCellBloc(cellContext: cellContext)..add(const FieldCellEvent.initial()), + child: BlocBuilder( + builder: (context, state) { + final button = FlowyButton( + hoverColor: theme.hover, + onTap: () => _showActionSheet(context), + rightIcon: svgWidget("editor/details", color: theme.iconColor), + leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor), + text: FlowyText.medium(state.field.name, fontSize: 12), + padding: GridSize.cellContentInsets, + ); - final borderSide = BorderSide(color: theme.shader4, width: 0.4); - final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); + final borderSide = BorderSide(color: theme.shader4, width: 0.4); + final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); - return Container( - width: field.width.toDouble(), - decoration: decoration, - child: button, + return Container( + width: state.field.width.toDouble(), + decoration: decoration, + child: button, + ); + }, + ), ); } void _showActionSheet(BuildContext context) { + final state = context.read().state; GridFieldCellActionSheet( - fieldCellContext: fieldCellContext, + cellContext: GridFieldCellContext(gridId: state.gridId, field: state.field), onEdited: () => _showFieldEditor(context), ).show(context); } void _showFieldEditor(BuildContext context) { + final state = context.read().state; + FieldEditor( - gridId: fieldCellContext.gridId, + gridId: state.gridId, fieldContextLoader: FieldContextLoaderAdaptor( - gridId: fieldCellContext.gridId, - field: fieldCellContext.field, + gridId: state.gridId, + field: state.field, ), ).show(context); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart index 6cf62bf397..42d49b69fe 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell_action_sheet.dart @@ -13,9 +13,9 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate { - final GridFieldCellContext fieldCellContext; + final GridFieldCellContext cellContext; final VoidCallback onEdited; - const GridFieldCellActionSheet({required this.fieldCellContext, required this.onEdited, Key? key}) : super(key: key); + const GridFieldCellActionSheet({required this.cellContext, required this.onEdited, Key? key}) : super(key: key); void show(BuildContext overlayContext) { FlowyOverlay.of(overlayContext).insertWithAnchor( @@ -33,7 +33,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: fieldCellContext), + create: (context) => getIt(param1: cellContext), child: SingleChildScrollView( child: Column( children: [ @@ -44,15 +44,15 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate }, ), const VSpace(6), - _FieldOperationList(fieldCellContext, () => FlowyOverlay.of(context).remove(identifier())), + _FieldOperationList(cellContext, () => FlowyOverlay.of(context).remove(identifier())), ], ), ), ); } - String identifier() { - return toString(); + static String identifier() { + return (GridFieldCellActionSheet).toString(); } @override 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 3a41ee938b..f503877a4a 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 @@ -41,8 +41,8 @@ class FieldEditor extends FlowyOverlayDelegate { ); } - String identifier() { - return toString(); + static String identifier() { + return (FieldEditor).toString(); } @override 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 2a7baaa773..fa5b4822d7 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 @@ -58,7 +58,7 @@ class _GridHeaderDelegate extends SliverPersistentHeaderDelegate { @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { if (oldDelegate is _GridHeaderDelegate) { - return fields != oldDelegate.fields; + return fields.length != oldDelegate.fields.length; } return true; } 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 a31d371b09..e4365a9a1a 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 @@ -114,7 +114,7 @@ class DateFormatList extends StatelessWidget { dateFormat: format, onSelected: (format) { onSelected(format); - FlowyOverlay.of(context).remove(identifier()); + FlowyOverlay.of(context).remove(DateFormatList.identifier()); }, isSelected: selectedFormat == format); }).toList(); @@ -135,8 +135,8 @@ class DateFormatList extends StatelessWidget { ); } - String identifier() { - return toString(); + static String identifier() { + return (DateFormatList).toString(); } } @@ -205,7 +205,7 @@ class TimeFormatList extends StatelessWidget { timeFormat: format, onSelected: (format) { onSelected(format); - FlowyOverlay.of(context).remove(identifier()); + FlowyOverlay.of(context).remove(TimeFormatList.identifier()); }); }).toList(); @@ -225,8 +225,8 @@ class TimeFormatList extends StatelessWidget { ); } - String identifier() { - return toString(); + static String identifier() { + return (TimeFormatList).toString(); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index 1893a77846..f8805b7180 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,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/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/header/type_option/widget.dart'; @@ -28,23 +28,23 @@ class EditSelectOptionPannel extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => EditOptionBloc(option: option), + create: (context) => EditSelectOptionBloc(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 EditSelectOptionEvent.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(EditSelectOptionEvent.updateName(optionName)); + } }, ); } @@ -178,7 +180,7 @@ class _SelectOptionColorCell extends StatelessWidget { leftIcon: colorIcon, rightIcon: checkmark, onTap: () { - context.read().add(EditOptionEvent.updateColor(color)); + context.read().add(EditSelectOptionEvent.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 84% 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..359d0427c9 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'; @@ -15,7 +15,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'edit_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; }, @@ -159,12 +159,13 @@ class _OptionList extends StatelessWidget { 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)); }, + key: ValueKey(option.id), ); delegate.showOverlay(context, pannel); }, @@ -208,7 +209,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 +223,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/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index a12b7e2be9..5897699442 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 @@ -81,7 +81,7 @@ class NumberFormatList extends StatelessWidget { format: format, onSelected: (format) { onSelected(format); - FlowyOverlay.of(context).remove(identifier()); + FlowyOverlay.of(context).remove(NumberFormatList.identifier()); }); }).toList(); @@ -101,8 +101,8 @@ class NumberFormatList extends StatelessWidget { ); } - String identifier() { - return toString(); + static String identifier() { + return (NumberFormatList).toString(); } } 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/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index df26694331..143dc76b1e 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" name = "dart_ffi" # this value will change depending on the target os # default static lib -crate-type = ["staticlib"] +crate-type = ["cdylib"] [dependencies] diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 05a82d9f13..94f499fea1 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -58,7 +58,7 @@ impl ClientGridEditor { start_field_id, grid_id, } = params; - + let field_id = field.id.clone(); let _ = self .modify(|grid| { if grid.contain_field(&field.id) { @@ -84,6 +84,7 @@ impl ClientGridEditor { }) .await?; let _ = self.notify_did_update_grid().await?; + let _ = self.notify_did_update_field(&field_id).await?; Ok(()) } @@ -113,7 +114,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(()) } @@ -407,12 +410,13 @@ impl ClientGridEditor { Ok(()) } + #[tracing::instrument(level = "trace", skip_all, err)] async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> { let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?; debug_assert!(field_metas.len() == 1); if let Some(field_meta) = field_metas.pop() { - send_dart_notification(&self.grid_id, GridNotification::DidUpdateField) + send_dart_notification(&field_id, GridNotification::DidUpdateField) .payload(field_meta) .send(); }