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 583bb08b7c..01fc64a494 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 @@ -87,7 +87,7 @@ class _BoardSelectOptionCellState extends State { SelectOptionCellEditor.editorPanelWidth, 300, )); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popover, constraints: constraints, direction: PopoverDirection.bottomWithLeftAligned, 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 545fd70470..ab5a5efbbe 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart @@ -1,15 +1,17 @@ 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:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'board_cell.dart'; import 'card_cell_builder.dart'; -import 'card_container.dart'; +import 'container/accessory.dart'; +import 'container/card_container.dart'; class BoardCard extends StatefulWidget { final String gridId; @@ -38,6 +40,8 @@ class BoardCard extends StatefulWidget { class _BoardCardState extends State { late BoardCardBloc _cardBloc; late EditableRowNotifier rowNotifier; + late PopoverController popoverController; + AccessoryType? accessoryType; @override void initState() { @@ -54,6 +58,7 @@ class _BoardCardState extends State { _cardBloc.add(BoardCardEvent.setIsEditing(rowNotifier.isEditing.value)); }); + popoverController = PopoverController(); super.initState(); } @@ -64,32 +69,42 @@ class _BoardCardState extends State { child: BlocBuilder( buildWhen: (previous, current) { // Rebuild when: - // 1.If the lenght of the cells is not the same + // 1.If the length of the cells is not the same // 2.isEditing changed if (previous.cells.length != current.cells.length || previous.isEditing != current.isEditing) { return true; } - // 3.Compare the content of the cells. The cells consisits of + // 3.Compare the content of the cells. The cells consists of // list of [BoardCellEquatable] that extends the [Equatable]. return !listEquals(previous.cells, current.cells); }, builder: (context, state) { - return BoardCardContainer( - buildAccessoryWhen: () => state.isEditing == false, - accessoryBuilder: (context) { - return [ - _CardEditOption(rowNotifier: rowNotifier), - const _CardMoreOption(), - ]; - }, - onTap: (context) => widget.openCard(context), - child: _CellColumn( - groupId: widget.groupId, - rowNotifier: rowNotifier, - cellBuilder: widget.cellBuilder, - cells: state.cells, + return AppFlowyPopover( + controller: popoverController, + constraints: BoxConstraints.loose(const Size(140, 200)), + direction: PopoverDirection.rightWithCenterAligned, + popupBuilder: (popoverContext) => _handlePopoverBuilder( + context, + popoverContext, + ), + child: BoardCardContainer( + buildAccessoryWhen: () => state.isEditing == false, + accessoryBuilder: (context) { + return [ + _CardEditOption(rowNotifier: rowNotifier), + _CardMoreOption(), + ]; + }, + openAccessory: _handleOpenAccessory, + openCard: (context) => widget.openCard(context), + child: _CellColumn( + groupId: widget.groupId, + rowNotifier: rowNotifier, + cellBuilder: widget.cellBuilder, + cells: state.cells, + ), ), ); }, @@ -97,6 +112,30 @@ class _BoardCardState extends State { ); } + void _handleOpenAccessory(AccessoryType newAccessoryType) { + accessoryType = newAccessoryType; + switch (newAccessoryType) { + case AccessoryType.edit: + break; + case AccessoryType.more: + popoverController.show(); + break; + } + } + + Widget _handlePopoverBuilder( + BuildContext context, + BuildContext popoverContext, + ) { + switch (accessoryType!) { + case AccessoryType.edit: + throw UnimplementedError(); + case AccessoryType.more: + return GridRowActionSheet( + rowData: context.read().rowInfo()); + } + } + @override Future dispose() async { rowNotifier.dispose(); @@ -163,7 +202,7 @@ class _CellColumn extends StatelessWidget { } class _CardMoreOption extends StatelessWidget with CardAccessory { - const _CardMoreOption({Key? key}) : super(key: key); + _CardMoreOption({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -175,11 +214,7 @@ class _CardMoreOption extends StatelessWidget with CardAccessory { } @override - void onTap(BuildContext context) { - GridRowActionSheet( - rowData: context.read().rowInfo(), - ).show(context, direction: AnchorDirection.bottomWithCenterAligned); - } + AccessoryType get type => AccessoryType.more; } class _CardEditOption extends StatelessWidget with CardAccessory { @@ -201,7 +236,8 @@ class _CardEditOption extends StatelessWidget with CardAccessory { } @override - void onTap(BuildContext context) { - rowNotifier.becomeFirstResponder(); - } + void onTap(BuildContext context) => rowNotifier.becomeFirstResponder(); + + @override + AccessoryType get type => AccessoryType.edit; } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/container/accessory.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/container/accessory.dart new file mode 100644 index 0000000000..0052e0e29c --- /dev/null +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/container/accessory.dart @@ -0,0 +1,74 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +enum AccessoryType { + edit, + more, +} + +abstract class CardAccessory implements Widget { + AccessoryType get type; + void onTap(BuildContext context) {} +} + +typedef CardAccessoryBuilder = List Function( + BuildContext buildContext, +); + +class CardAccessoryContainer extends StatelessWidget { + final void Function(AccessoryType) onTapAccessory; + final List accessories; + const CardAccessoryContainer({ + required this.accessories, + required this.onTapAccessory, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.read(); + final children = accessories.map((accessory) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + accessory.onTap(context); + onTapAccessory(accessory.type); + }, + child: _wrapHover(theme, accessory), + ); + }).toList(); + return _wrapDecoration(context, Row(children: children)); + } + + FlowyHover _wrapHover(AppTheme theme, CardAccessory accessory) { + return FlowyHover( + style: HoverStyle( + hoverColor: theme.hover, + backgroundColor: theme.surface, + borderRadius: BorderRadius.zero, + ), + builder: (_, onHover) => SizedBox( + width: 24, + height: 24, + child: accessory, + ), + ); + } + + Widget _wrapDecoration(BuildContext context, Widget child) { + final theme = context.read(); + final borderSide = BorderSide(color: theme.shader6, width: 1.0); + final decoration = BoxDecoration( + color: Colors.transparent, + border: Border.fromBorderSide(borderSide), + borderRadius: const BorderRadius.all(Radius.circular(4)), + ); + return Container( + clipBehavior: Clip.hardEdge, + decoration: decoration, + child: child, + ); + } +} diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/container/card_container.dart similarity index 57% rename from frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart rename to frontend/app_flowy/lib/plugins/board/presentation/card/container/card_container.dart index c79a582661..ccdfc3fc3e 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/container/card_container.dart @@ -1,17 +1,19 @@ -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'accessory.dart'; + class BoardCardContainer extends StatelessWidget { final Widget child; final CardAccessoryBuilder? accessoryBuilder; final bool Function()? buildAccessoryWhen; - final void Function(BuildContext) onTap; + final void Function(BuildContext) openCard; + final void Function(AccessoryType) openAccessory; const BoardCardContainer({ required this.child, - required this.onTap, + required this.openCard, + required this.openAccessory, this.accessoryBuilder, this.buildAccessoryWhen, Key? key, @@ -34,13 +36,14 @@ class BoardCardContainer extends StatelessWidget { if (accessories.isNotEmpty) { container = _CardEnterRegion( accessories: accessories, + onTapAccessory: openAccessory, child: container, ); } } return GestureDetector( - onTap: () => onTap(context), + onTap: () => openCard(context), child: Padding( padding: const EdgeInsets.all(8), child: ConstrainedBox( @@ -55,69 +58,16 @@ class BoardCardContainer extends StatelessWidget { } } -abstract class CardAccessory implements Widget { - void onTap(BuildContext context); -} - -typedef CardAccessoryBuilder = List Function( - BuildContext buildContext, -); - -class CardAccessoryContainer extends StatelessWidget { - final List accessories; - const CardAccessoryContainer({required this.accessories, Key? key}) - : super(key: key); - - @override - Widget build(BuildContext context) { - final theme = context.read(); - final children = accessories.map((accessory) { - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => accessory.onTap(context), - child: _wrapHover(theme, accessory), - ); - }).toList(); - return _wrapDecoration(context, Row(children: children)); - } - - FlowyHover _wrapHover(AppTheme theme, CardAccessory accessory) { - return FlowyHover( - style: HoverStyle( - hoverColor: theme.hover, - backgroundColor: theme.surface, - borderRadius: BorderRadius.zero, - ), - builder: (_, onHover) => SizedBox( - width: 24, - height: 24, - child: accessory, - ), - ); - } - - Widget _wrapDecoration(BuildContext context, Widget child) { - final theme = context.read(); - final borderSide = BorderSide(color: theme.shader6, width: 1.0); - final decoration = BoxDecoration( - color: Colors.transparent, - border: Border.fromBorderSide(borderSide), - borderRadius: const BorderRadius.all(Radius.circular(4)), - ); - return Container( - clipBehavior: Clip.hardEdge, - decoration: decoration, - child: child, - ); - } -} - class _CardEnterRegion extends StatelessWidget { final Widget child; final List accessories; - const _CardEnterRegion( - {required this.child, required this.accessories, Key? key}) - : super(key: key); + final void Function(AccessoryType) onTapAccessory; + const _CardEnterRegion({ + required this.child, + required this.accessories, + required this.onTapAccessory, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -126,9 +76,12 @@ class _CardEnterRegion extends StatelessWidget { builder: (context, onEnter, _) { List children = [child]; if (onEnter) { - children.add(CardAccessoryContainer( - accessories: accessories, - ).positioned(right: 0)); + children.add( + CardAccessoryContainer( + accessories: accessories, + onTapAccessory: onTapAccessory, + ).positioned(right: 0), + ); } return MouseRegion( 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 27a59c69a6..3c6b3fa818 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 @@ -62,7 +62,7 @@ class _SettingButtonState extends State<_SettingButton> { @override Widget build(BuildContext context) { final theme = context.read(); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: popoverController, constraints: BoxConstraints.loose(const Size(260, 400)), triggerActions: PopoverTriggerActionFlags.click, 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 7b289d4a21..1120294430 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,7 +63,7 @@ class _DateCellState extends GridCellState { value: _cellBloc, child: BlocBuilder( builder: (context, state) { - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popover, offset: const Offset(0, 20), direction: PopoverDirection.bottomWithLeftAligned, 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 1fe45f60c8..cc502f9cf9 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 @@ -299,7 +299,7 @@ class _DateTypeOptionButton extends StatelessWidget { return BlocSelector( selector: (state) => state.dateTypeOptionPB, builder: (context, dateTypeOptionPB) { - return AppFlowyStylePopover( + return AppFlowyPopover( triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, offset: const Offset(20, 0), 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 3db0d75797..fe98b847ed 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 @@ -181,7 +181,7 @@ class _SelectOptionWrapState extends State { SelectOptionCellEditor.editorPanelWidth, 300, )); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popover, constraints: constraints, direction: PopoverDirection.bottomWithLeftAligned, 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 e502853b90..71d144978d 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 @@ -148,11 +148,7 @@ class _TextField extends StatelessWidget { selectedOptionMap: optionMap, distanceToText: _editorPanelWidth * 0.7, tagController: _tagController, - onClick: () { - popoverMutex.close(); - // FlowyOverlay.of(context) - // .remove(SelectOptionTypeOptionEditor.identifier); - }, + onClick: () => popoverMutex.close(), newText: (text) { context .read() @@ -244,7 +240,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> { @override Widget build(BuildContext context) { final theme = context.watch(); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popoverController, offset: const Offset(20, 0), constraints: BoxConstraints.loose(const Size(200, 300)), 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 155a75cae3..ea7d38d15c 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 @@ -130,7 +130,7 @@ class _GridURLCellState extends GridCellState { ), ); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popoverController, constraints: BoxConstraints.loose(const Size(300, 160)), direction: PopoverDirection.bottomWithLeftAligned, @@ -216,7 +216,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory> @override Widget build(BuildContext context) { final theme = context.watch(); - return AppFlowyStylePopover( + return AppFlowyPopover( constraints: BoxConstraints.loose(const Size(300, 160)), controller: _popoverController, direction: PopoverDirection.bottomWithLeftAligned, 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 d7300ef799..a5b54021cf 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 @@ -30,7 +30,7 @@ class GridFieldCell extends StatelessWidget { }, child: BlocBuilder( builder: (context, state) { - final button = AppFlowyStylePopover( + final button = AppFlowyPopover( constraints: BoxConstraints.loose(const Size(240, 840)), direction: PopoverDirection.bottomWithLeftAligned, triggerActions: PopoverTriggerActionFlags.click, 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 12058ccecc..15d84908f7 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 @@ -243,7 +243,7 @@ class _DeleteFieldButton extends StatelessWidget { } Widget _wrapPopover(Widget widget) { - return AppFlowyStylePopover( + return AppFlowyPopover( triggerActions: PopoverTriggerActionFlags.click, constraints: BoxConstraints.loose(const Size(400, 240)), mutex: popoverMutex, 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 fcbb211fc1..e2dce9f6ea 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 @@ -64,7 +64,7 @@ class FieldTypeOptionEditor extends StatelessWidget { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, - child: AppFlowyStylePopover( + child: AppFlowyPopover( constraints: BoxConstraints.loose(const Size(460, 440)), triggerActions: PopoverTriggerActionFlags.click | PopoverTriggerActionFlags.hover, 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 f9656e8dcc..d4774dfd47 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 @@ -176,7 +176,7 @@ class CreateFieldButton extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); - return AppFlowyStylePopover( + return AppFlowyPopover( triggerActions: PopoverTriggerActionFlags.click, direction: PopoverDirection.bottomWithRightAligned, constraints: BoxConstraints.loose(const Size(240, 200)), 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 2e9201324c..a4ab3b55c0 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 @@ -62,7 +62,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { } Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) { - return AppFlowyStylePopover( + return AppFlowyPopover( mutex: popoverMutex, triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, @@ -84,7 +84,7 @@ class DateTypeOptionWidget extends TypeOptionWidget { } Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) { - return AppFlowyStylePopover( + return AppFlowyPopover( mutex: popoverMutex, triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, 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 8651a18515..f8c6fac88b 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 @@ -55,7 +55,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { listener: (context, state) => typeOptionContext.typeOption = state.typeOption, builder: (context, state) { - return AppFlowyStylePopover( + return AppFlowyPopover( mutex: popoverMutex, triggerActions: PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, 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 0a7dc481d1..90e4e22df1 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 @@ -180,7 +180,7 @@ class _OptionCellState extends State<_OptionCell> { Widget build(BuildContext context) { final theme = context.watch(); - return AppFlowyStylePopover( + return AppFlowyPopover( controller: _popoverController, mutex: widget.popoverMutex, offset: const Offset(20, 0), 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 ebe2a41db2..b43a3a50ef 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,8 +1,10 @@ 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:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -56,20 +58,21 @@ class _GridRowWidgetState extends State { child: BlocBuilder( buildWhen: (p, c) => p.rowInfo.rowPB.height != c.rowInfo.rowPB.height, builder: (context, state) { - final children = [ - const _RowLeading(), - Expanded( - child: RowContent( - builder: widget.cellBuilder, - onExpand: () => widget.openDetailPage( - context, - widget.cellBuilder, - ), + final content = Expanded( + child: RowContent( + builder: widget.cellBuilder, + onExpand: () => widget.openDetailPage( + context, + widget.cellBuilder, ), ), + ); + + return Row(children: [ + const _RowLeading(), + content, const _RowTrailing(), - ]; - return Row(children: children); + ]); }, ), ), @@ -83,26 +86,51 @@ class _GridRowWidgetState extends State { } } -class _RowLeading extends StatelessWidget { +class _RowLeading extends StatefulWidget { const _RowLeading({Key? key}) : super(key: key); + @override + State<_RowLeading> createState() => _RowLeadingState(); +} + +class _RowLeadingState extends State<_RowLeading> { + late PopoverController popoverController; + + @override + void initState() { + popoverController = PopoverController(); + super.initState(); + } + @override Widget build(BuildContext context) { - return Consumer( - builder: (context, state, _) { - return SizedBox( - width: GridSize.leadingHeaderPadding, - child: state.onEnter ? _activeWidget() : null); + return AppFlowyPopover( + controller: popoverController, + constraints: BoxConstraints.loose(const Size(140, 200)), + direction: PopoverDirection.rightWithCenterAligned, + popupBuilder: (BuildContext popoverContext) { + return GridRowActionSheet( + rowData: context.read().state.rowInfo); }, + child: Consumer( + builder: (context, state, _) { + return SizedBox( + width: GridSize.leadingHeaderPadding, + child: state.onEnter ? _activeWidget() : null, + ); + }, + ), ); } Widget _activeWidget() { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: const [ - _InsertRowButton(), - _DeleteRowButton(), + children: [ + const _InsertButton(), + _MenuButton(openMenu: () { + popoverController.show(); + }), ], ); } @@ -117,8 +145,8 @@ class _RowTrailing extends StatelessWidget { } } -class _InsertRowButton extends StatelessWidget { - const _InsertRowButton({Key? key}) : super(key: key); +class _InsertButton extends StatelessWidget { + const _InsertButton({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -128,17 +156,29 @@ class _InsertRowButton extends StatelessWidget { hoverColor: theme.hover, width: 20, height: 30, - onPressed: () => context.read().add( - const RowEvent.createRow(), - ), + onPressed: () => context.read().add(const RowEvent.createRow()), iconPadding: const EdgeInsets.all(3), icon: svgWidget("home/add"), ); } } -class _DeleteRowButton extends StatelessWidget { - const _DeleteRowButton({Key? key}) : super(key: key); +class _MenuButton extends StatefulWidget { + final VoidCallback openMenu; + const _MenuButton({ + required this.openMenu, + Key? key, + }) : super(key: key); + + @override + State<_MenuButton> createState() => _MenuButtonState(); +} + +class _MenuButtonState extends State<_MenuButton> { + @override + void initState() { + super.initState(); + } @override Widget build(BuildContext context) { @@ -148,9 +188,7 @@ class _DeleteRowButton extends StatelessWidget { hoverColor: theme.hover, width: 20, height: 30, - onPressed: () => GridRowActionSheet( - rowData: context.read().state.rowInfo, - ).show(context), + onPressed: () => widget.openMenu(), iconPadding: const EdgeInsets.all(3), icon: svgWidget("editor/details"), ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart index 9f2c9e8ef5..b944bc24ad 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart @@ -3,7 +3,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -27,10 +26,7 @@ class GridRowActionSheet extends StatelessWidget { final cells = _RowAction.values .where((value) => value.enable()) .map( - (action) => _RowActionCell( - action: action, - onDismissed: () => remove(context), - ), + (action) => _RowActionCell(action: action), ) .toList(); @@ -52,37 +48,11 @@ class GridRowActionSheet extends StatelessWidget { ), ); } - - void show( - BuildContext overlayContext, { - AnchorDirection direction = AnchorDirection.leftWithCenterAligned, - }) { - FlowyOverlay.of(overlayContext).insertWithAnchor( - widget: OverlayContainer( - constraints: BoxConstraints.loose(const Size(140, 200)), - child: this, - ), - identifier: GridRowActionSheet.identifier(), - anchorContext: overlayContext, - anchorDirection: direction, - ); - } - - void remove(BuildContext overlayContext) { - FlowyOverlay.of(overlayContext).remove(GridRowActionSheet.identifier()); - } - - static String identifier() { - return (GridRowActionSheet).toString(); - } } class _RowActionCell extends StatelessWidget { final _RowAction action; - final VoidCallback onDismissed; - const _RowActionCell( - {required this.action, required this.onDismissed, Key? key}) - : super(key: key); + const _RowActionCell({required this.action, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -101,7 +71,6 @@ class _RowActionCell extends StatelessWidget { if (action.enable()) { action.performAction(context); } - onDismissed(); }, leftIcon: svgWidget(action.iconName(), color: theme.iconColor), ), 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 a1d65f89ae..432b9a5de4 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 @@ -194,7 +194,7 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> { Widget build(BuildContext context) { final theme = context.read(); - return AppFlowyStylePopover( + return AppFlowyPopover( constraints: BoxConstraints.loose(const Size(240, 200)), controller: popoverController, triggerActions: PopoverTriggerActionFlags.click, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart index 8709cd3ea3..dc3461b2e7 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart @@ -99,7 +99,6 @@ class _GridGroupCell extends StatelessWidget { ), ); onSelected(); - // FlowyOverlay.of(context).remove(GridGroupList.identifier()); }, ), ); 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 39331ce151..0399670504 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 @@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget { } Widget _editFieldButton(AppTheme theme, BuildContext context) { - return AppFlowyStylePopover( + return AppFlowyPopover( mutex: popoverMutex, triggerActions: PopoverTriggerActionFlags.click, offset: const Offset(20, 0), diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart index 9198f54de8..05bddf61d8 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart @@ -40,7 +40,6 @@ class GridSettingList extends StatelessWidget { previous.selectedAction != current.selectedAction, listener: (context, state) { state.selectedAction.foldLeft(null, (_, action) { - FlowyOverlay.of(context).remove(identifier()); onAction(action, settingContext); }); }, 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 7675eda943..ba8f22fe31 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 @@ -53,7 +53,7 @@ class _SettingButton extends StatelessWidget { @override Widget build(BuildContext context) { final theme = context.watch(); - return AppFlowyStylePopover( + return AppFlowyPopover( constraints: BoxConstraints.loose(const Size(260, 400)), triggerActions: PopoverTriggerActionFlags.click, offset: const Offset(0, 10), 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 663a8c0646..3ef06389cc 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 @@ -2,7 +2,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; import 'package:appflowy_popover/popover.dart'; import 'package:flutter/material.dart'; -class AppFlowyStylePopover extends StatelessWidget { +class AppFlowyPopover extends StatelessWidget { final Widget child; final PopoverController? controller; final Widget Function(BuildContext context) popupBuilder; @@ -13,7 +13,7 @@ class AppFlowyStylePopover extends StatelessWidget { final PopoverMutex? mutex; final Offset? offset; - const AppFlowyStylePopover({ + const AppFlowyPopover({ Key? key, required this.child, required this.popupBuilder,