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 01fc64a494..65a16a1732 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,7 +2,7 @@ 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:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart index ab5a5efbbe..3430cacec6 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/plugins/board/application/card/card_bloc.dart'; import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart index dad2b042d5..b45db13cf2 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_group.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart index 3c6b3fa818..726abdcc6d 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -65,7 +65,7 @@ class _SettingButtonState extends State<_SettingButton> { return AppFlowyPopover( controller: popoverController, constraints: BoxConstraints.loose(const Size(260, 400)), - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, child: FlowyIconButton( hoverColor: theme.hover, width: 22, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart index 1120294430..e1b9dbcbd8 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart @@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import '../cell_builder.dart'; import 'date_editor.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart index cc502f9cf9..35eb78e38d 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/grid/application/cell/date_cal_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -300,8 +300,7 @@ class _DateTypeOptionButton extends StatelessWidget { selector: (state) => state.dateTypeOptionPB, builder: (context, dateTypeOptionPB) { return AppFlowyPopover( - triggerActions: - PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(140, 100)), child: FlowyButton( @@ -340,36 +339,30 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { @override Widget build(BuildContext context) { List children = [ - Popover( + AppFlowyPopover( mutex: _popoverMutex, - triggerActions: - PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, + asBarrier: true, + triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), popupBuilder: (BuildContext context) { - return OverlayContainer( - constraints: BoxConstraints.loose(const Size(460, 440)), - child: DateFormatList( - selectedFormat: widget.dateTypeOptionPB.dateFormat, - onSelected: (format) => - widget.onEvent(DateCalEvent.setDateFormat(format)), - ), + return DateFormatList( + selectedFormat: widget.dateTypeOptionPB.dateFormat, + onSelected: (format) => + widget.onEvent(DateCalEvent.setDateFormat(format)), ); }, child: const DateFormatButton(), ), - Popover( + AppFlowyPopover( mutex: _popoverMutex, - triggerActions: - PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, + asBarrier: true, + triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), popupBuilder: (BuildContext context) { - return OverlayContainer( - constraints: BoxConstraints.loose(const Size(460, 440)), - child: TimeFormatList( - selectedFormat: widget.dateTypeOptionPB.timeFormat, - onSelected: (format) => - widget.onEvent(DateCalEvent.setTimeFormat(format)), - ), + return TimeFormatList( + selectedFormat: widget.dateTypeOptionPB.timeFormat, + onSelected: (format) => + widget.onEvent(DateCalEvent.setTimeFormat(format)), ); }, child: TimeFormatButton(timeFormat: widget.dateTypeOptionPB.timeFormat), 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 fe98b847ed..6ed04c8b04 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 @@ -1,6 +1,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; 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 a1fec9dc2c..9a0252e009 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 @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -243,6 +243,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> { return AppFlowyPopover( controller: _popoverController, offset: const Offset(20, 0), + asBarrier: true, constraints: BoxConstraints.loose(const Size(200, 300)), mutex: widget.popoverMutex, child: SizedBox( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart index ea7d38d15c..f20ffb5681 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/grid/application/cell/url_cell_bloc.dart'; import 'package:app_flowy/workspace/presentation/home/toast.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -220,7 +220,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory> constraints: BoxConstraints.loose(const Size(300, 160)), controller: _popoverController, direction: PopoverDirection.bottomWithLeftAligned, - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, offset: const Offset(0, 20), child: svgWidget("editor/edit", color: theme.iconColor), popupBuilder: (BuildContext popoverContext) { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index a5b54021cf..eec63e1be0 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -33,7 +33,7 @@ class GridFieldCell extends StatelessWidget { final button = AppFlowyPopover( constraints: BoxConstraints.loose(const Size(240, 840)), direction: PopoverDirection.bottomWithLeftAligned, - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, offset: const Offset(0, 10), popupBuilder: (BuildContext context) { return GridFieldCellActionSheet( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart index 6f3e583e35..398a2206ae 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_editor. import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart index 2008530dea..c7837accc9 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:flowy_infra/theme.dart'; @@ -244,7 +244,7 @@ class _DeleteFieldButton extends StatelessWidget { Widget _wrapPopover(Widget widget) { return AppFlowyPopover( - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, constraints: BoxConstraints.loose(const Size(400, 240)), mutex: popoverMutex, direction: PopoverDirection.center, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart index 2c6f262180..e504c0ab4f 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart @@ -1,4 +1,4 @@ -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart index e2dce9f6ea..047dd43ea1 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:dartz/dartz.dart' show Either; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -66,8 +66,8 @@ class FieldTypeOptionEditor extends StatelessWidget { height: GridSize.typeOptionItemHeight, child: AppFlowyPopover( constraints: BoxConstraints.loose(const Size(460, 440)), - triggerActions: - PopoverTriggerActionFlags.click | PopoverTriggerActionFlags.hover, + asBarrier: true, + triggerActions: PopoverTriggerFlags.click | PopoverTriggerFlags.hover, mutex: popoverMutex, offset: const Offset(20, 0), popupBuilder: (context) { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index d4774dfd47..c600f89688 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -177,9 +177,10 @@ class CreateFieldButton extends StatelessWidget { final theme = context.watch(); return AppFlowyPopover( - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, direction: PopoverDirection.bottomWithRightAligned, - constraints: BoxConstraints.loose(const Size(240, 200)), + asBarrier: true, + constraints: BoxConstraints.loose(const Size(240, 600)), child: FlowyButton( text: FlowyText.medium( LocaleKeys.grid_field_newColumn.tr(), diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index e00eda5ec0..e6d47a06c0 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart index a4ab3b55c0..d95406dcb2 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart @@ -11,7 +11,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import '../../../layout/sizes.dart'; import '../field_type_option_editor.dart'; import 'builder.dart'; @@ -64,8 +64,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) { return AppFlowyPopover( mutex: popoverMutex, - triggerActions: - PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(460, 440)), popupBuilder: (popoverContext) { @@ -86,8 +85,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) { return AppFlowyPopover( mutex: popoverMutex, - triggerActions: - PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(460, 440)), popupBuilder: (BuildContext popoverContext) { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart index 2dc804111d..a3982e6331 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/multi_select_type_option.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:flutter/material.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import '../field_type_option_editor.dart'; import 'builder.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart index f8c6fac88b..bf82aecabc 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/number_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/number_format_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -57,8 +57,8 @@ class NumberTypeOptionWidget extends TypeOptionWidget { builder: (context, state) { return AppFlowyPopover( mutex: popoverMutex, - triggerActions: PopoverTriggerActionFlags.hover | - PopoverTriggerActionFlags.click, + triggerActions: + PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(460, 440)), child: FlowyButton( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart index 90e4e22df1..06a9cd84b6 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -184,6 +184,7 @@ class _OptionCellState extends State<_OptionCell> { controller: _popoverController, mutex: widget.popoverMutex, offset: const Offset(20, 0), + asBarrier: true, constraints: BoxConstraints.loose(const Size(460, 440)), child: SizedBox( height: GridSize.typeOptionItemHeight, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/single_select.dart index 477e573ff2..37431128ea 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/single_select.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/single_select.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/single_sele import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:flutter/material.dart'; import '../field_type_option_editor.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'builder.dart'; import 'select_option.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart index b43a3a50ef..6ef6946df5 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 432b9a5de4..a68ac63984 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -15,7 +15,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import '../../layout/sizes.dart'; import '../cell/cell_accessory.dart'; @@ -197,7 +197,7 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> { return AppFlowyPopover( constraints: BoxConstraints.loose(const Size(240, 200)), controller: popoverController, - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, direction: PopoverDirection.topWithLeftAligned, onClose: widget.onClosed, child: Container( @@ -274,7 +274,7 @@ class _RowDetailCellState extends State<_RowDetailCell> { offset: const Offset(20, 0), popupBuilder: (popoverContext) { return OverlayContainer( - constraints: BoxConstraints.loose(const Size(240, 200)), + constraints: BoxConstraints.loose(const Size(240, 600)), child: FieldEditor( gridId: widget.cellId.gridId, fieldName: widget.cellId.fieldContext.field.name, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 0399670504..1f44a4fb88 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_editor. import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/setting/property_bloc.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -118,7 +118,7 @@ class _GridPropertyCell extends StatelessWidget { Widget _editFieldButton(AppTheme theme, BuildContext context) { return AppFlowyPopover( mutex: popoverMutex, - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(240, 200)), child: FlowyButton( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart index ba8f22fe31..39c5240db7 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart @@ -1,4 +1,4 @@ -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:app_flowy/plugins/grid/application/setting/setting_bloc.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -55,7 +55,7 @@ class _SettingButton extends StatelessWidget { final theme = context.watch(); return AppFlowyPopover( constraints: BoxConstraints.loose(const Size(260, 400)), - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, offset: const Offset(0, 10), child: FlowyIconButton( width: 22, diff --git a/frontend/app_flowy/packages/appflowy_popover/example/lib/example_button.dart b/frontend/app_flowy/packages/appflowy_popover/example/lib/example_button.dart index 357941dc7f..74f1645bd0 100644 --- a/frontend/app_flowy/packages/appflowy_popover/example/lib/example_button.dart +++ b/frontend/app_flowy/packages/appflowy_popover/example/lib/example_button.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; class PopoverMenu extends StatefulWidget { const PopoverMenu({Key? key}) : super(key: key); @@ -41,8 +41,8 @@ class _PopoverMenuState extends State { decoration: null)), ), Popover( - triggerActions: PopoverTriggerActionFlags.hover | - PopoverTriggerActionFlags.click, + triggerActions: + PopoverTriggerFlags.hover | PopoverTriggerFlags.click, mutex: popOverMutex, offset: const Offset(10, 0), popupBuilder: (BuildContext context) { @@ -54,8 +54,8 @@ class _PopoverMenuState extends State { ), ), Popover( - triggerActions: PopoverTriggerActionFlags.hover | - PopoverTriggerActionFlags.click, + triggerActions: + PopoverTriggerFlags.hover | PopoverTriggerFlags.click, mutex: popOverMutex, offset: const Offset(10, 0), popupBuilder: (BuildContext context) { @@ -86,7 +86,7 @@ class ExampleButton extends StatelessWidget { @override Widget build(BuildContext context) { return Popover( - triggerActions: PopoverTriggerActionFlags.click, + triggerActions: PopoverTriggerFlags.click, offset: offset, direction: direction ?? PopoverDirection.rightWithTopAligned, child: TextButton(child: Text(label), onPressed: () {}), diff --git a/frontend/app_flowy/packages/appflowy_popover/example/lib/main.dart b/frontend/app_flowy/packages/appflowy_popover/example/lib/main.dart index 178b075ee6..a6b09bb4d3 100644 --- a/frontend/app_flowy/packages/appflowy_popover/example/lib/main.dart +++ b/frontend/app_flowy/packages/appflowy_popover/example/lib/main.dart @@ -1,4 +1,4 @@ -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flutter/material.dart'; import "./example_button.dart"; diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/appflowy_popover.dart b/frontend/app_flowy/packages/appflowy_popover/lib/appflowy_popover.dart new file mode 100644 index 0000000000..925b9cad02 --- /dev/null +++ b/frontend/app_flowy/packages/appflowy_popover/lib/appflowy_popover.dart @@ -0,0 +1,5 @@ +/// AppFlowyBoard library +library appflowy_popover; + +export 'src/mutex.dart'; +export 'src/popover.dart'; diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart b/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart deleted file mode 100644 index c10e23ecce..0000000000 --- a/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart +++ /dev/null @@ -1,345 +0,0 @@ -import 'package:appflowy_popover/layout.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -/// If multiple popovers are exclusive, -/// pass the same mutex to them. -class PopoverMutex { - final ValueNotifier _stateNotifier = ValueNotifier(null); - PopoverMutex(); - - void removePopoverStateListener(VoidCallback listener) { - _stateNotifier.removeListener(listener); - } - - VoidCallback listenOnPopoverStateChanged(VoidCallback callback) { - listenerCallback() { - callback(); - } - - _stateNotifier.addListener(listenerCallback); - return listenerCallback; - } - - void close() { - _stateNotifier.value?.close(); - } - - PopoverState? get state => _stateNotifier.value; - - set state(PopoverState? newState) { - if (_stateNotifier.value != null && _stateNotifier.value != newState) { - _stateNotifier.value?.close(); - } - _stateNotifier.value = newState; - } - - void _removeState() { - _stateNotifier.value = null; - } - - void dispose() { - _stateNotifier.dispose(); - } -} - -class PopoverController { - PopoverState? state; - - close() { - state?.close(); - } - - show() { - state?.showOverlay(); - } -} - -class PopoverTriggerActionFlags { - static int click = 0x01; - static int hover = 0x02; -} - -enum PopoverDirection { - // Corner aligned with a corner of the SourceWidget - topLeft, - topRight, - bottomLeft, - bottomRight, - center, - - // Edge aligned with a edge of the SourceWidget - topWithLeftAligned, - topWithCenterAligned, - topWithRightAligned, - rightWithTopAligned, - rightWithCenterAligned, - rightWithBottomAligned, - bottomWithLeftAligned, - bottomWithCenterAligned, - bottomWithRightAligned, - leftWithTopAligned, - leftWithCenterAligned, - leftWithBottomAligned, - - custom, -} - -class Popover extends StatefulWidget { - final PopoverController? controller; - - final Offset? offset; - - final Decoration? maskDecoration; - - /// The function used to build the popover. - final Widget? Function(BuildContext context) popupBuilder; - - final int triggerActions; - - /// If multiple popovers are exclusive, - /// pass the same mutex to them. - final PopoverMutex? mutex; - - /// The direction of the popover - final PopoverDirection direction; - - final void Function()? onClose; - - /// The content area of the popover. - final Widget child; - - const Popover({ - Key? key, - required this.child, - required this.popupBuilder, - this.controller, - this.offset, - this.maskDecoration, - this.triggerActions = 0, - this.direction = PopoverDirection.rightWithTopAligned, - this.mutex, - this.onClose, - }) : super(key: key); - - @override - State createState() => PopoverState(); -} - -class PopoverState extends State { - final PopoverLink popoverLink = PopoverLink(); - OverlayEntry? _overlayEntry; - bool hasMask = true; - - static PopoverState? _popoverWithMask; - - @override - void initState() { - widget.controller?.state = this; - super.initState(); - } - - showOverlay() { - close(); - - if (widget.mutex != null) { - widget.mutex?.state = this; - } - - if (_popoverWithMask == null) { - _popoverWithMask = this; - } else { - hasMask = false; - } - - final newEntry = OverlayEntry(builder: (context) { - final children = []; - - if (hasMask) { - children.add(_PopoverMask( - decoration: widget.maskDecoration, - onTap: () => close(), - onExit: () => close(), - )); - } - - children.add(PopoverContainer( - direction: widget.direction, - popoverLink: popoverLink, - offset: widget.offset ?? Offset.zero, - popupBuilder: widget.popupBuilder, - onClose: () => close(), - onCloseAll: () => closeAll(), - )); - - return Stack(children: children); - }); - - _overlayEntry = newEntry; - - Overlay.of(context)?.insert(newEntry); - } - - close() { - if (_overlayEntry != null) { - _overlayEntry!.remove(); - _overlayEntry = null; - if (_popoverWithMask == this) { - _popoverWithMask = null; - } - if (widget.onClose != null) { - widget.onClose!(); - } - } - - if (widget.mutex?.state == this) { - widget.mutex?._removeState(); - } - } - - closeAll() { - _popoverWithMask?.close(); - } - - @override - void deactivate() { - close(); - super.deactivate(); - } - - _handleTargetPointerDown(PointerDownEvent event) { - if (widget.triggerActions & PopoverTriggerActionFlags.click != 0) { - showOverlay(); - } - } - - _handleTargetPointerEnter(PointerEnterEvent event) { - if (widget.triggerActions & PopoverTriggerActionFlags.hover != 0) { - showOverlay(); - } - } - - _buildContent(BuildContext context) { - if (widget.triggerActions == 0) { - return widget.child; - } - - return MouseRegion( - onEnter: _handleTargetPointerEnter, - child: Listener( - onPointerDown: _handleTargetPointerDown, - child: widget.child, - ), - ); - } - - @override - Widget build(BuildContext context) { - return PopoverTarget( - link: popoverLink, - child: _buildContent(context), - ); - } -} - -class _PopoverMask extends StatefulWidget { - final void Function() onTap; - final void Function()? onExit; - final Decoration? decoration; - - const _PopoverMask( - {Key? key, required this.onTap, this.onExit, this.decoration}) - : super(key: key); - - @override - State createState() => _PopoverMaskState(); -} - -class _PopoverMaskState extends State<_PopoverMask> { - @override - void initState() { - HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent); - super.initState(); - } - - bool _handleGlobalKeyEvent(KeyEvent event) { - if (event.logicalKey == LogicalKeyboardKey.escape) { - if (widget.onExit != null) { - widget.onExit!(); - } - - return true; - } - return false; - } - - @override - void deactivate() { - HardwareKeyboard.instance.removeHandler(_handleGlobalKeyEvent); - super.deactivate(); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: widget.onTap, - child: Container( - // decoration: widget.decoration, - decoration: widget.decoration ?? - const BoxDecoration( - color: Color.fromARGB(0, 244, 67, 54), - ), - ), - ); - } -} - -class PopoverContainer extends StatefulWidget { - final Widget? Function(BuildContext context) popupBuilder; - final PopoverDirection direction; - final PopoverLink popoverLink; - final Offset offset; - final void Function() onClose; - final void Function() onCloseAll; - - const PopoverContainer({ - Key? key, - required this.popupBuilder, - required this.direction, - required this.popoverLink, - required this.offset, - required this.onClose, - required this.onCloseAll, - }) : super(key: key); - - @override - State createState() => PopoverContainerState(); - - static PopoverContainerState of(BuildContext context) { - if (context is StatefulElement && context.state is PopoverContainerState) { - return context.state as PopoverContainerState; - } - final PopoverContainerState? result = - context.findAncestorStateOfType(); - return result!; - } -} - -class PopoverContainerState extends State { - @override - Widget build(BuildContext context) { - return CustomSingleChildLayout( - delegate: PopoverLayoutDelegate( - direction: widget.direction, - link: widget.popoverLink, - offset: widget.offset, - ), - child: widget.popupBuilder(context), - ); - } - - close() => widget.onClose(); - - closeAll() => widget.onCloseAll(); -} diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/follower.dart b/frontend/app_flowy/packages/appflowy_popover/lib/src/follower.dart similarity index 100% rename from frontend/app_flowy/packages/appflowy_popover/lib/follower.dart rename to frontend/app_flowy/packages/appflowy_popover/lib/src/follower.dart diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/layout.dart b/frontend/app_flowy/packages/appflowy_popover/lib/src/layout.dart similarity index 100% rename from frontend/app_flowy/packages/appflowy_popover/lib/layout.dart rename to frontend/app_flowy/packages/appflowy_popover/lib/src/layout.dart diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/src/mask.dart b/frontend/app_flowy/packages/appflowy_popover/lib/src/mask.dart new file mode 100644 index 0000000000..815321774f --- /dev/null +++ b/frontend/app_flowy/packages/appflowy_popover/lib/src/mask.dart @@ -0,0 +1,116 @@ +import 'dart:collection'; + +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +typedef EntryMap = LinkedHashMap; + +class RootOverlayEntry { + final EntryMap _entries = EntryMap(); + RootOverlayEntry(); + + void addEntry( + BuildContext context, + PopoverState newState, + OverlayEntry entry, + bool asBarrier, + ) { + _entries[newState] = OverlayEntryContext(entry, newState, asBarrier); + Overlay.of(context)?.insert(entry); + } + + bool contains(PopoverState oldState) { + return _entries.containsKey(oldState); + } + + void removeEntry(PopoverState oldState) { + if (_entries.isEmpty) return; + + final removedEntry = _entries.remove(oldState); + removedEntry?.overlayEntry.remove(); + } + + bool get isEmpty => _entries.isEmpty; + + bool get isNotEmpty => _entries.isNotEmpty; + + bool hasEntry() { + return _entries.isNotEmpty; + } + + PopoverState? popEntry() { + if (_entries.isEmpty) return null; + + final lastEntry = _entries.values.last; + _entries.remove(lastEntry.popoverState); + lastEntry.overlayEntry.remove(); + lastEntry.popoverState.widget.onClose?.call(); + + if (lastEntry.asBarrier) { + return lastEntry.popoverState; + } else { + return popEntry(); + } + } +} + +class OverlayEntryContext { + final bool asBarrier; + final PopoverState popoverState; + final OverlayEntry overlayEntry; + + OverlayEntryContext( + this.overlayEntry, + this.popoverState, + this.asBarrier, + ); +} + +class PopoverMask extends StatefulWidget { + final void Function() onTap; + final void Function()? onExit; + final Decoration? decoration; + + const PopoverMask( + {Key? key, required this.onTap, this.onExit, this.decoration}) + : super(key: key); + + @override + State createState() => _PopoverMaskState(); +} + +class _PopoverMaskState extends State { + @override + void initState() { + HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent); + super.initState(); + } + + bool _handleGlobalKeyEvent(KeyEvent event) { + if (event.logicalKey == LogicalKeyboardKey.escape) { + if (widget.onExit != null) { + widget.onExit!(); + } + return true; + } else { + return false; + } + } + + @override + void deactivate() { + HardwareKeyboard.instance.removeHandler(_handleGlobalKeyEvent); + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onTap, + child: Container( + decoration: widget.decoration, + ), + ); + } +} diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/src/mutex.dart b/frontend/app_flowy/packages/appflowy_popover/lib/src/mutex.dart new file mode 100644 index 0000000000..2c6db3100a --- /dev/null +++ b/frontend/app_flowy/packages/appflowy_popover/lib/src/mutex.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; + +import 'popover.dart'; + +/// If multiple popovers are exclusive, +/// pass the same mutex to them. +class PopoverMutex { + final ValueNotifier _stateNotifier = ValueNotifier(null); + PopoverMutex(); + + void removePopoverStateListener(VoidCallback listener) { + _stateNotifier.removeListener(listener); + } + + VoidCallback listenOnPopoverStateChanged(VoidCallback callback) { + listenerCallback() { + callback(); + } + + _stateNotifier.addListener(listenerCallback); + return listenerCallback; + } + + void close() { + _stateNotifier.value?.close(); + } + + PopoverState? get state => _stateNotifier.value; + + set state(PopoverState? newState) { + if (_stateNotifier.value != null && _stateNotifier.value != newState) { + _stateNotifier.value?.close(); + } + _stateNotifier.value = newState; + } + + void removeState() { + _stateNotifier.value = null; + } + + void dispose() { + _stateNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/src/popover.dart b/frontend/app_flowy/packages/appflowy_popover/lib/src/popover.dart new file mode 100644 index 0000000000..e1e9481816 --- /dev/null +++ b/frontend/app_flowy/packages/appflowy_popover/lib/src/popover.dart @@ -0,0 +1,248 @@ +import 'dart:async'; +import 'package:appflowy_popover/src/layout.dart'; +import 'package:flutter/material.dart'; +import 'mask.dart'; +import 'mutex.dart'; + +class PopoverController { + PopoverState? _state; + + close() { + _state?.close(); + } + + show() { + _state?.showOverlay(); + } +} + +class PopoverTriggerFlags { + static int click = 0x01; + static int hover = 0x02; +} + +enum PopoverDirection { + // Corner aligned with a corner of the SourceWidget + topLeft, + topRight, + bottomLeft, + bottomRight, + center, + + // Edge aligned with a edge of the SourceWidget + topWithLeftAligned, + topWithCenterAligned, + topWithRightAligned, + rightWithTopAligned, + rightWithCenterAligned, + rightWithBottomAligned, + bottomWithLeftAligned, + bottomWithCenterAligned, + bottomWithRightAligned, + leftWithTopAligned, + leftWithCenterAligned, + leftWithBottomAligned, + + custom, +} + +class Popover extends StatefulWidget { + final PopoverController? controller; + + final Offset? offset; + + final Decoration? maskDecoration; + + /// The function used to build the popover. + final Widget? Function(BuildContext context) popupBuilder; + + final int triggerActions; + + /// If multiple popovers are exclusive, + /// pass the same mutex to them. + final PopoverMutex? mutex; + + /// The direction of the popover + final PopoverDirection direction; + + final void Function()? onClose; + + final bool asBarrier; + + /// The content area of the popover. + final Widget child; + + const Popover({ + Key? key, + required this.child, + required this.popupBuilder, + this.controller, + this.offset, + this.maskDecoration = const BoxDecoration( + color: Color.fromARGB(0, 244, 67, 54), + ), + this.triggerActions = 0, + this.direction = PopoverDirection.rightWithTopAligned, + this.mutex, + this.onClose, + this.asBarrier = false, + }) : super(key: key); + + @override + State createState() => PopoverState(); +} + +class PopoverState extends State { + static final RootOverlayEntry _rootEntry = RootOverlayEntry(); + final PopoverLink popoverLink = PopoverLink(); + Timer? _debounceEnterRegionAction; + + @override + void initState() { + widget.controller?._state = this; + super.initState(); + } + + void showOverlay() { + close(); + + if (widget.mutex != null) { + widget.mutex?.state = this; + } + final shouldAddMask = _rootEntry.isEmpty; + final newEntry = OverlayEntry(builder: (context) { + final children = []; + if (shouldAddMask) { + children.add( + PopoverMask( + decoration: widget.maskDecoration, + onTap: () => _removeRootOverlay(), + onExit: () => _removeRootOverlay(), + ), + ); + } + + children.add( + PopoverContainer( + direction: widget.direction, + popoverLink: popoverLink, + offset: widget.offset ?? Offset.zero, + popupBuilder: widget.popupBuilder, + onClose: () => close(), + onCloseAll: () => _removeRootOverlay(), + ), + ); + + return Stack(children: children); + }); + + _rootEntry.addEntry(context, this, newEntry, widget.asBarrier); + } + + void close() { + if (_rootEntry.contains(this)) { + _rootEntry.removeEntry(this); + widget.onClose?.call(); + } + } + + void _removeRootOverlay() { + _rootEntry.popEntry(); + + if (widget.mutex?.state == this) { + widget.mutex?.removeState(); + } + } + + @override + void deactivate() { + close(); + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return PopoverTarget( + link: popoverLink, + child: _buildChild(context), + ); + } + + Widget _buildChild(BuildContext context) { + if (widget.triggerActions == 0) { + return widget.child; + } + + return MouseRegion( + onEnter: (event) { + _debounceEnterRegionAction = + Timer(const Duration(milliseconds: 200), () { + if (widget.triggerActions & PopoverTriggerFlags.hover != 0) { + showOverlay(); + } + }); + }, + onExit: (event) { + _debounceEnterRegionAction?.cancel(); + _debounceEnterRegionAction = null; + }, + child: Listener( + child: widget.child, + onPointerDown: (PointerDownEvent event) { + if (widget.triggerActions & PopoverTriggerFlags.click != 0) { + showOverlay(); + } + }, + ), + ); + } +} + +class PopoverContainer extends StatefulWidget { + final Widget? Function(BuildContext context) popupBuilder; + final PopoverDirection direction; + final PopoverLink popoverLink; + final Offset offset; + final void Function() onClose; + final void Function() onCloseAll; + + const PopoverContainer({ + Key? key, + required this.popupBuilder, + required this.direction, + required this.popoverLink, + required this.offset, + required this.onClose, + required this.onCloseAll, + }) : super(key: key); + + @override + State createState() => PopoverContainerState(); + + static PopoverContainerState of(BuildContext context) { + if (context is StatefulElement && context.state is PopoverContainerState) { + return context.state as PopoverContainerState; + } + final PopoverContainerState? result = + context.findAncestorStateOfType(); + return result!; + } +} + +class PopoverContainerState extends State { + @override + Widget build(BuildContext context) { + return CustomSingleChildLayout( + delegate: PopoverLayoutDelegate( + direction: widget.direction, + link: widget.popoverLink, + offset: widget.offset, + ), + child: widget.popupBuilder(context), + ); + } + + close() => widget.onClose(); + + closeAll() => widget.onCloseAll(); +} diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_stype_popover.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_stype_popover.dart index 3ef06389cc..fb13ce2df5 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_stype_popover.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_stype_popover.dart @@ -1,5 +1,5 @@ import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; -import 'package:appflowy_popover/popover.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flutter/material.dart'; class AppFlowyPopover extends StatelessWidget { @@ -12,6 +12,7 @@ class AppFlowyPopover extends StatelessWidget { final void Function()? onClose; final PopoverMutex? mutex; final Offset? offset; + final bool asBarrier; const AppFlowyPopover({ Key? key, @@ -24,6 +25,7 @@ class AppFlowyPopover extends StatelessWidget { this.triggerActions = 0, this.offset, this.controller, + this.asBarrier = false, }) : super(key: key); @override @@ -33,6 +35,7 @@ class AppFlowyPopover extends StatelessWidget { onClose: onClose, direction: direction, mutex: mutex, + asBarrier: asBarrier, triggerActions: triggerActions, popupBuilder: (context) { final child = popupBuilder(context);