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 77a739e164..fbdc2ec9ab 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 @@ -63,8 +63,6 @@ class _DateCellState extends GridCellState { builder: (context, state) { return Popover( controller: _popover, - targetAnchor: Alignment.bottomLeft, - followerAnchor: Alignment.topLeft, offset: const Offset(0, 20), child: SizedBox.expand( child: GestureDetector( 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 f651baef9d..25ecf613a6 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 @@ -306,8 +306,6 @@ class _DateTypeOptionButton extends StatelessWidget { return Popover( triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), child: FlowyButton( text: FlowyText.medium(title, fontSize: 12), @@ -353,8 +351,6 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, child: const DateFormatButton(), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), popupBuilder: (BuildContext context) { return OverlayContainer( @@ -372,8 +368,6 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, child: TimeFormatButton(timeFormat: widget.dateTypeOptionPB.timeFormat), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), popupBuilder: (BuildContext context) { return OverlayContainer( 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 6a070feed4..72794adee3 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 @@ -197,8 +197,6 @@ class _SelectOptionWrapState extends State { Popover( controller: _popover, child: child, - targetAnchor: Alignment.bottomCenter, - followerAnchor: Alignment.topCenter, offset: const Offset(0, 20), popupBuilder: (BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 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 aef241b1bd..abdbbdb3ab 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 @@ -39,8 +39,6 @@ class _GridFieldCellState extends State { field: state.field, onTap: () => popover.show(), ), - targetAnchor: Alignment.bottomLeft, - followerAnchor: Alignment.topLeft, offset: const Offset(0, 10), popupBuilder: (BuildContext context) { return GridFieldCellActionSheet( 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 b3c0c87301..6231ba5aba 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 @@ -69,8 +69,6 @@ class FieldTypeOptionEditor extends StatelessWidget { PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, mutex: popoverMutex, offset: const Offset(20, 0), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, popupBuilder: (context) { final list = FieldTypeList(onSelectField: (newFieldType) { dataController.switchToField(newFieldType); 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 f7d1df0a3d..bd1c82a254 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 @@ -67,8 +67,6 @@ class DateTypeOptionWidget extends TypeOptionWidget { triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, child: const DateFormatButton(), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), popupBuilder: (popoverContext) { return OverlayContainer( @@ -92,19 +90,19 @@ class DateTypeOptionWidget extends TypeOptionWidget { triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, child: TimeFormatButton(timeFormat: timeFormat), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), - popupBuilder: (BuildContext context) { + popupBuilder: (BuildContext popoverContext) { return OverlayContainer( - constraints: BoxConstraints.loose(const Size(460, 440)), - child: TimeFormatList( - selectedFormat: timeFormat, - onSelected: (format) { - context - .read() - .add(DateTypeOptionEvent.didSelectTimeFormat(format)); - })); + constraints: BoxConstraints.loose(const Size(460, 440)), + child: TimeFormatList( + selectedFormat: timeFormat, + onSelected: (format) { + context + .read() + .add(DateTypeOptionEvent.didSelectTimeFormat(format)); + PopoverContainerState.of(popoverContext).close(); + }), + ); }, ); } 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 b98c073da7..d9df038d22 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 @@ -63,8 +63,6 @@ class NumberTypeOptionWidget extends TypeOptionWidget { mutex: popoverMutex, triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), child: FlowyButton( margin: GridSize.typeOptionContentInsets, 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 bba80ab865..7d22c51fab 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 @@ -167,8 +167,6 @@ class _RowDetailCellState extends State<_RowDetailCell> { width: 150, child: Popover( controller: popover, - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), popupBuilder: (context) { return OverlayContainer( 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 453d2b838a..1912dc8499 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 @@ -96,8 +96,6 @@ class _GridPropertyCell extends StatelessWidget { Widget _editFieldButton(AppTheme theme, BuildContext context) { return Popover( triggerActions: PopoverTriggerActionFlags.click, - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, offset: const Offset(20, 0), child: FlowyButton( text: FlowyText.medium(field.name, fontSize: 12), 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 7327cefc86..38e95dc782 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 @@ -55,8 +55,6 @@ class _SettingButton extends StatelessWidget { final theme = context.watch(); return Popover( triggerActions: PopoverTriggerActionFlags.click, - targetAnchor: Alignment.bottomLeft, - followerAnchor: Alignment.topLeft, 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 80b06422ed..173baf823c 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 @@ -22,8 +22,6 @@ class _PopoverMenuState extends State { PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, mutex: popOverMutex, offset: const Offset(10, 0), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, popupBuilder: (BuildContext context) { return PopoverMenu(); }, @@ -37,8 +35,6 @@ class _PopoverMenuState extends State { PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, mutex: popOverMutex, offset: const Offset(10, 0), - targetAnchor: Alignment.topRight, - followerAnchor: Alignment.topLeft, popupBuilder: (BuildContext context) { return PopoverMenu(); }, @@ -69,8 +65,6 @@ class ExampleButton extends StatelessWidget { @override Widget build(BuildContext context) { return Popover( - targetAnchor: targetAnchor, - followerAnchor: followerAnchor, triggerActions: PopoverTriggerActionFlags.click, offset: offset, child: TextButton(child: Text(label), onPressed: () {}), diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/layout.dart b/frontend/app_flowy/packages/appflowy_popover/lib/layout.dart index ee97c7161a..d589f18723 100644 --- a/frontend/app_flowy/packages/appflowy_popover/lib/layout.dart +++ b/frontend/app_flowy/packages/appflowy_popover/lib/layout.dart @@ -6,10 +6,12 @@ import './popover.dart'; class PopoverLayoutDelegate extends SingleChildLayoutDelegate { PopoverLink link; PopoverDirection direction; + final Offset offset; PopoverLayoutDelegate({ required this.link, required this.direction, + required this.offset, }); @override @@ -165,8 +167,8 @@ class PopoverLayoutDelegate extends SingleChildLayoutDelegate { return Offset.zero; } final anchorRect = Rect.fromLTWH( - link.leaderOffset!.dx, - link.leaderOffset!.dy, + link.leaderOffset!.dx + offset.dx, + link.leaderOffset!.dy + offset.dy, link.leaderSize!.width, link.leaderSize!.height, ); diff --git a/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart b/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart index 3507c7d1bf..df51f7249d 100644 --- a/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart +++ b/frontend/app_flowy/packages/appflowy_popover/lib/popover.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:appflowy_popover/layout.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -55,8 +57,6 @@ class Popover extends StatefulWidget { final PopoverController? controller; final Offset? offset; final Decoration? maskDecoration; - final Alignment targetAnchor; - final Alignment followerAnchor; final Widget Function(BuildContext context) popupBuilder; final int triggerActions; final PopoverMutex? mutex; @@ -70,8 +70,6 @@ class Popover extends StatefulWidget { this.controller, this.offset, this.maskDecoration, - this.targetAnchor = Alignment.topLeft, - this.followerAnchor = Alignment.topLeft, this.triggerActions = 0, this.direction = PopoverDirection.rightWithTopAligned, this.mutex, @@ -124,15 +122,13 @@ class PopoverState extends State { )); } - children.add( - CustomSingleChildLayout( - delegate: PopoverLayoutDelegate( - direction: widget.direction, - link: popoverLink, - ), - child: widget.popupBuilder(context), - ), - ); + children.add(PopoverContainer( + direction: widget.direction, + popoverLink: popoverLink, + offset: widget.offset ?? Offset.zero, + popupBuilder: widget.popupBuilder, + onClose: () => close(), + )); return Stack(children: children); }); @@ -244,3 +240,50 @@ class _PopoverMaskState extends State<_PopoverMask> { ); } } + +class PopoverContainer extends StatefulWidget { + final Widget Function(BuildContext context) popupBuilder; + final PopoverDirection direction; + final PopoverLink popoverLink; + final Offset offset; + final void Function() onClose; + + const PopoverContainer({ + Key? key, + required this.popupBuilder, + required this.direction, + required this.popoverLink, + required this.offset, + required this.onClose, + }) : super(key: key); + + @override + State createState() => PopoverContainerState(); +} + +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(); + } + + 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!; + } +}