From 6c27b5455ea6b4fe2b2bbce8cc8809f488595132 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 18 Sep 2022 11:46:00 +0800 Subject: [PATCH] refactor: replace FlowyOverlay with AppFlowyPopover in select option --- .../card/board_select_option_cell.dart | 91 +++++++++------ .../select_option_cell.dart | 108 +++++++++--------- .../select_option_editor.dart | 48 +------- 3 files changed, 112 insertions(+), 135 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart index 6469a4e106..583bb08b7c 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart @@ -2,6 +2,8 @@ import 'package:app_flowy/plugins/board/application/card/board_select_option_cel import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart'; +import 'package:appflowy_popover/popover.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -26,9 +28,11 @@ class BoardSelectOptionCell extends StatefulWidget with EditableCell { class _BoardSelectOptionCellState extends State { late BoardSelectOptionCellBloc _cellBloc; + late PopoverController _popover; @override void initState() { + _popover = PopoverController(); final cellController = widget.cellControllerBuilder.build() as GridSelectOptionCellController; _cellBloc = BoardSelectOptionCellBloc(cellController: cellController) @@ -41,43 +45,60 @@ class _BoardSelectOptionCellState extends State { return BlocProvider.value( value: _cellBloc, child: BlocBuilder( - buildWhen: (previous, current) { - return previous.selectedOptions != current.selectedOptions; - }, - builder: (context, state) { - if (state.selectedOptions - .where((element) => element.id == widget.groupId) - .isNotEmpty || - state.selectedOptions.isEmpty) { - return const SizedBox(); - } else { - final children = state.selectedOptions - .map( - (option) => SelectOptionTag.fromOption( - context: context, - option: option, - onSelected: () { - SelectOptionCellEditor.show( - context: context, - cellController: widget.cellControllerBuilder.build() - as GridSelectOptionCellController, - ); - }, - ), - ) - .toList(); + buildWhen: (previous, current) { + return previous.selectedOptions != current.selectedOptions; + }, builder: (context, state) { + // Returns SizedBox if the content of the cell is empty + if (_isEmpty(state)) return const SizedBox(); - return IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 6), - child: SizedBox.expand( - child: Wrap(spacing: 4, runSpacing: 2, children: children), - ), - ), + final children = state.selectedOptions.map( + (option) { + final tag = SelectOptionTag.fromOption( + context: context, + option: option, + onSelected: () => _popover.show(), ); - } - }, - ), + return _wrapPopover(tag); + }, + ).toList(); + + return IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 6), + child: SizedBox.expand( + child: Wrap(spacing: 4, runSpacing: 2, children: children), + ), + ), + ); + }), + ); + } + + bool _isEmpty(BoardSelectOptionCellState state) { + // The cell should hide if the option id is equal to the groupId. + final isInGroup = state.selectedOptions + .where((element) => element.id == widget.groupId) + .isNotEmpty; + return isInGroup || state.selectedOptions.isEmpty; + } + + Widget _wrapPopover(Widget child) { + final constraints = BoxConstraints.loose(Size( + SelectOptionCellEditor.editorPanelWidth, + 300, + )); + return AppFlowyStylePopover( + controller: _popover, + constraints: constraints, + direction: PopoverDirection.bottomWithLeftAligned, + popupBuilder: (BuildContext context) { + return SelectOptionCellEditor( + cellController: widget.cellControllerBuilder.build() + as GridSelectOptionCellController, + ); + }, + onClose: () {}, + child: child, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart index 2e65226289..3db0d75797 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart @@ -164,67 +164,65 @@ class _SelectOptionWrapState extends State { @override Widget build(BuildContext context) { final theme = context.watch(); - final Widget child; - if (widget.selectOptions.isEmpty && widget.cellStyle != null) { - child = Align( - alignment: Alignment.centerLeft, - child: FlowyText.medium( - widget.cellStyle!.placeholder, - fontSize: 14, - color: theme.shader3, - ), - ); - } else { - child = Align( - alignment: Alignment.centerLeft, - child: Wrap( - spacing: 4, - runSpacing: 2, - children: widget.selectOptions - .map((option) => SelectOptionTag.fromOption( - context: context, - option: option, - )) - .toList(), - ), - ); - } + Widget child = _buildOptions(theme, context); return Stack( alignment: AlignmentDirectional.center, fit: StackFit.expand, children: [ - AppFlowyStylePopover( - controller: _popover, - constraints: BoxConstraints.loose( - Size(SelectOptionCellEditor.editorPanelWidth, 300)), - offset: const Offset(0, 20), - direction: PopoverDirection.bottomWithLeftAligned, - // triggerActions: PopoverTriggerActionFlags.c, - popupBuilder: (BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - widget.onFocus?.call(true); - }); - return SizedBox( - width: SelectOptionCellEditor.editorPanelWidth, - child: SelectOptionCellEditor( - cellController: widget.cellControllerBuilder.build() - as GridSelectOptionCellController, - onDismissed: () { - widget.onFocus?.call(false); - }, - ), - ); - }, - onClose: () { - widget.onFocus?.call(false); - }, - child: child, - ), - InkWell(onTap: () { - _popover.show(); - }), + _wrapPopover(child), + InkWell(onTap: () => _popover.show()), ], ); } + + Widget _wrapPopover(Widget child) { + final constraints = BoxConstraints.loose(Size( + SelectOptionCellEditor.editorPanelWidth, + 300, + )); + return AppFlowyStylePopover( + controller: _popover, + constraints: constraints, + direction: PopoverDirection.bottomWithLeftAligned, + popupBuilder: (BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.onFocus?.call(true); + }); + return SelectOptionCellEditor( + cellController: widget.cellControllerBuilder.build() + as GridSelectOptionCellController, + ); + }, + onClose: () => widget.onFocus?.call(false), + child: child, + ); + } + + Widget _buildOptions(AppTheme theme, BuildContext context) { + final Widget child; + if (widget.selectOptions.isEmpty && widget.cellStyle != null) { + child = FlowyText.medium( + widget.cellStyle!.placeholder, + fontSize: 14, + color: theme.shader3, + ); + } else { + final children = widget.selectOptions.map( + (option) { + return SelectOptionTag.fromOption( + context: context, + option: option, + ); + }, + ).toList(); + + child = Wrap( + spacing: 4, + runSpacing: 2, + children: children, + ); + } + return Align(alignment: Alignment.centerLeft, child: child); + } } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart index 1c0cad85b1..fecb5176f3 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart @@ -25,17 +25,13 @@ import 'text_field.dart'; const double _editorPanelWidth = 300; -class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { +class SelectOptionCellEditor extends StatelessWidget { final GridSelectOptionCellController cellController; - final VoidCallback? onDismissed; static double editorPanelWidth = 300; - const SelectOptionCellEditor({ - required this.cellController, - this.onDismissed, - Key? key, - }) : super(key: key); + const SelectOptionCellEditor({required this.cellController, Key? key}) + : super(key: key); @override Widget build(BuildContext context) { @@ -60,44 +56,6 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { ), ); } - - static void show({ - required BuildContext context, - required GridSelectOptionCellController cellController, - VoidCallback? onDismissed, - }) { - SelectOptionCellEditor.remove(context); - final editor = SelectOptionCellEditor( - cellController: cellController, - onDismissed: onDismissed, - ); - - // - FlowyOverlay.of(context).insertWithAnchor( - widget: OverlayContainer( - constraints: BoxConstraints.loose(const Size(_editorPanelWidth, 300)), - child: SizedBox(width: _editorPanelWidth, child: editor), - ), - identifier: SelectOptionCellEditor.identifier(), - anchorContext: context, - anchorDirection: AnchorDirection.bottomWithCenterAligned, - delegate: editor, - ); - } - - static void remove(BuildContext context) { - FlowyOverlay.of(context).remove(identifier()); - } - - static String identifier() { - return (SelectOptionCellEditor).toString(); - } - - @override - bool asBarrier() => true; - - @override - void didRemove() => onDismissed?.call(); } class _OptionList extends StatelessWidget {