fix: open GridRowActionSheet with appflowy overlay

This commit is contained in:
appflowy 2022-09-19 15:36:59 +08:00
parent 4d835757d2
commit 53cc0fff9d
25 changed files with 250 additions and 186 deletions

View File

@ -87,7 +87,7 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
SelectOptionCellEditor.editorPanelWidth, SelectOptionCellEditor.editorPanelWidth,
300, 300,
)); ));
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popover, controller: _popover,
constraints: constraints, constraints: constraints,
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,

View File

@ -1,15 +1,17 @@
import 'package:app_flowy/plugins/board/application/card/card_bloc.dart'; 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/board/application/card/card_data_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet.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/image.dart';
import 'package:flowy_infra/theme.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/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'board_cell.dart'; import 'board_cell.dart';
import 'card_cell_builder.dart'; import 'card_cell_builder.dart';
import 'card_container.dart'; import 'container/accessory.dart';
import 'container/card_container.dart';
class BoardCard extends StatefulWidget { class BoardCard extends StatefulWidget {
final String gridId; final String gridId;
@ -38,6 +40,8 @@ class BoardCard extends StatefulWidget {
class _BoardCardState extends State<BoardCard> { class _BoardCardState extends State<BoardCard> {
late BoardCardBloc _cardBloc; late BoardCardBloc _cardBloc;
late EditableRowNotifier rowNotifier; late EditableRowNotifier rowNotifier;
late PopoverController popoverController;
AccessoryType? accessoryType;
@override @override
void initState() { void initState() {
@ -54,6 +58,7 @@ class _BoardCardState extends State<BoardCard> {
_cardBloc.add(BoardCardEvent.setIsEditing(rowNotifier.isEditing.value)); _cardBloc.add(BoardCardEvent.setIsEditing(rowNotifier.isEditing.value));
}); });
popoverController = PopoverController();
super.initState(); super.initState();
} }
@ -64,32 +69,42 @@ class _BoardCardState extends State<BoardCard> {
child: BlocBuilder<BoardCardBloc, BoardCardState>( child: BlocBuilder<BoardCardBloc, BoardCardState>(
buildWhen: (previous, current) { buildWhen: (previous, current) {
// Rebuild when: // 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 // 2.isEditing changed
if (previous.cells.length != current.cells.length || if (previous.cells.length != current.cells.length ||
previous.isEditing != current.isEditing) { previous.isEditing != current.isEditing) {
return true; 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]. // list of [BoardCellEquatable] that extends the [Equatable].
return !listEquals(previous.cells, current.cells); return !listEquals(previous.cells, current.cells);
}, },
builder: (context, state) { builder: (context, state) {
return BoardCardContainer( return AppFlowyPopover(
buildAccessoryWhen: () => state.isEditing == false, controller: popoverController,
accessoryBuilder: (context) { constraints: BoxConstraints.loose(const Size(140, 200)),
return [ direction: PopoverDirection.rightWithCenterAligned,
_CardEditOption(rowNotifier: rowNotifier), popupBuilder: (popoverContext) => _handlePopoverBuilder(
const _CardMoreOption(), context,
]; popoverContext,
}, ),
onTap: (context) => widget.openCard(context), child: BoardCardContainer(
child: _CellColumn( buildAccessoryWhen: () => state.isEditing == false,
groupId: widget.groupId, accessoryBuilder: (context) {
rowNotifier: rowNotifier, return [
cellBuilder: widget.cellBuilder, _CardEditOption(rowNotifier: rowNotifier),
cells: state.cells, _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<BoardCard> {
); );
} }
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<BoardCardBloc>().rowInfo());
}
}
@override @override
Future<void> dispose() async { Future<void> dispose() async {
rowNotifier.dispose(); rowNotifier.dispose();
@ -163,7 +202,7 @@ class _CellColumn extends StatelessWidget {
} }
class _CardMoreOption extends StatelessWidget with CardAccessory { class _CardMoreOption extends StatelessWidget with CardAccessory {
const _CardMoreOption({Key? key}) : super(key: key); _CardMoreOption({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -175,11 +214,7 @@ class _CardMoreOption extends StatelessWidget with CardAccessory {
} }
@override @override
void onTap(BuildContext context) { AccessoryType get type => AccessoryType.more;
GridRowActionSheet(
rowData: context.read<BoardCardBloc>().rowInfo(),
).show(context, direction: AnchorDirection.bottomWithCenterAligned);
}
} }
class _CardEditOption extends StatelessWidget with CardAccessory { class _CardEditOption extends StatelessWidget with CardAccessory {
@ -201,7 +236,8 @@ class _CardEditOption extends StatelessWidget with CardAccessory {
} }
@override @override
void onTap(BuildContext context) { void onTap(BuildContext context) => rowNotifier.becomeFirstResponder();
rowNotifier.becomeFirstResponder();
} @override
AccessoryType get type => AccessoryType.edit;
} }

View File

@ -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<CardAccessory> Function(
BuildContext buildContext,
);
class CardAccessoryContainer extends StatelessWidget {
final void Function(AccessoryType) onTapAccessory;
final List<CardAccessory> accessories;
const CardAccessoryContainer({
required this.accessories,
required this.onTapAccessory,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.read<AppTheme>();
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<AppTheme>();
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,
);
}
}

View File

@ -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:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'accessory.dart';
class BoardCardContainer extends StatelessWidget { class BoardCardContainer extends StatelessWidget {
final Widget child; final Widget child;
final CardAccessoryBuilder? accessoryBuilder; final CardAccessoryBuilder? accessoryBuilder;
final bool Function()? buildAccessoryWhen; final bool Function()? buildAccessoryWhen;
final void Function(BuildContext) onTap; final void Function(BuildContext) openCard;
final void Function(AccessoryType) openAccessory;
const BoardCardContainer({ const BoardCardContainer({
required this.child, required this.child,
required this.onTap, required this.openCard,
required this.openAccessory,
this.accessoryBuilder, this.accessoryBuilder,
this.buildAccessoryWhen, this.buildAccessoryWhen,
Key? key, Key? key,
@ -34,13 +36,14 @@ class BoardCardContainer extends StatelessWidget {
if (accessories.isNotEmpty) { if (accessories.isNotEmpty) {
container = _CardEnterRegion( container = _CardEnterRegion(
accessories: accessories, accessories: accessories,
onTapAccessory: openAccessory,
child: container, child: container,
); );
} }
} }
return GestureDetector( return GestureDetector(
onTap: () => onTap(context), onTap: () => openCard(context),
child: Padding( child: Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: ConstrainedBox( child: ConstrainedBox(
@ -55,69 +58,16 @@ class BoardCardContainer extends StatelessWidget {
} }
} }
abstract class CardAccessory implements Widget {
void onTap(BuildContext context);
}
typedef CardAccessoryBuilder = List<CardAccessory> Function(
BuildContext buildContext,
);
class CardAccessoryContainer extends StatelessWidget {
final List<CardAccessory> accessories;
const CardAccessoryContainer({required this.accessories, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.read<AppTheme>();
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<AppTheme>();
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 { class _CardEnterRegion extends StatelessWidget {
final Widget child; final Widget child;
final List<CardAccessory> accessories; final List<CardAccessory> accessories;
const _CardEnterRegion( final void Function(AccessoryType) onTapAccessory;
{required this.child, required this.accessories, Key? key}) const _CardEnterRegion({
: super(key: key); required this.child,
required this.accessories,
required this.onTapAccessory,
Key? key,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -126,9 +76,12 @@ class _CardEnterRegion extends StatelessWidget {
builder: (context, onEnter, _) { builder: (context, onEnter, _) {
List<Widget> children = [child]; List<Widget> children = [child];
if (onEnter) { if (onEnter) {
children.add(CardAccessoryContainer( children.add(
accessories: accessories, CardAccessoryContainer(
).positioned(right: 0)); accessories: accessories,
onTapAccessory: onTapAccessory,
).positioned(right: 0),
);
} }
return MouseRegion( return MouseRegion(

View File

@ -62,7 +62,7 @@ class _SettingButtonState extends State<_SettingButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.read<AppTheme>(); final theme = context.read<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
controller: popoverController, controller: popoverController,
constraints: BoxConstraints.loose(const Size(260, 400)), constraints: BoxConstraints.loose(const Size(260, 400)),
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,

View File

@ -63,7 +63,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
value: _cellBloc, value: _cellBloc,
child: BlocBuilder<DateCellBloc, DateCellState>( child: BlocBuilder<DateCellBloc, DateCellState>(
builder: (context, state) { builder: (context, state) {
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popover, controller: _popover,
offset: const Offset(0, 20), offset: const Offset(0, 20),
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,

View File

@ -299,7 +299,7 @@ class _DateTypeOptionButton extends StatelessWidget {
return BlocSelector<DateCalBloc, DateCalState, DateTypeOptionPB>( return BlocSelector<DateCalBloc, DateCalState, DateTypeOptionPB>(
selector: (state) => state.dateTypeOptionPB, selector: (state) => state.dateTypeOptionPB,
builder: (context, dateTypeOptionPB) { builder: (context, dateTypeOptionPB) {
return AppFlowyStylePopover( return AppFlowyPopover(
triggerActions: triggerActions:
PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,
offset: const Offset(20, 0), offset: const Offset(20, 0),

View File

@ -181,7 +181,7 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
SelectOptionCellEditor.editorPanelWidth, SelectOptionCellEditor.editorPanelWidth,
300, 300,
)); ));
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popover, controller: _popover,
constraints: constraints, constraints: constraints,
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,

View File

@ -148,11 +148,7 @@ class _TextField extends StatelessWidget {
selectedOptionMap: optionMap, selectedOptionMap: optionMap,
distanceToText: _editorPanelWidth * 0.7, distanceToText: _editorPanelWidth * 0.7,
tagController: _tagController, tagController: _tagController,
onClick: () { onClick: () => popoverMutex.close(),
popoverMutex.close();
// FlowyOverlay.of(context)
// .remove(SelectOptionTypeOptionEditor.identifier);
},
newText: (text) { newText: (text) {
context context
.read<SelectOptionCellEditorBloc>() .read<SelectOptionCellEditorBloc>()
@ -244,7 +240,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popoverController, controller: _popoverController,
offset: const Offset(20, 0), offset: const Offset(20, 0),
constraints: BoxConstraints.loose(const Size(200, 300)), constraints: BoxConstraints.loose(const Size(200, 300)),

View File

@ -130,7 +130,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
), ),
); );
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popoverController, controller: _popoverController,
constraints: BoxConstraints.loose(const Size(300, 160)), constraints: BoxConstraints.loose(const Size(300, 160)),
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,
@ -216,7 +216,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
constraints: BoxConstraints.loose(const Size(300, 160)), constraints: BoxConstraints.loose(const Size(300, 160)),
controller: _popoverController, controller: _popoverController,
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,

View File

@ -30,7 +30,7 @@ class GridFieldCell extends StatelessWidget {
}, },
child: BlocBuilder<FieldCellBloc, FieldCellState>( child: BlocBuilder<FieldCellBloc, FieldCellState>(
builder: (context, state) { builder: (context, state) {
final button = AppFlowyStylePopover( final button = AppFlowyPopover(
constraints: BoxConstraints.loose(const Size(240, 840)), constraints: BoxConstraints.loose(const Size(240, 840)),
direction: PopoverDirection.bottomWithLeftAligned, direction: PopoverDirection.bottomWithLeftAligned,
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,

View File

@ -243,7 +243,7 @@ class _DeleteFieldButton extends StatelessWidget {
} }
Widget _wrapPopover(Widget widget) { Widget _wrapPopover(Widget widget) {
return AppFlowyStylePopover( return AppFlowyPopover(
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
constraints: BoxConstraints.loose(const Size(400, 240)), constraints: BoxConstraints.loose(const Size(400, 240)),
mutex: popoverMutex, mutex: popoverMutex,

View File

@ -64,7 +64,7 @@ class FieldTypeOptionEditor extends StatelessWidget {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return SizedBox( return SizedBox(
height: GridSize.typeOptionItemHeight, height: GridSize.typeOptionItemHeight,
child: AppFlowyStylePopover( child: AppFlowyPopover(
constraints: BoxConstraints.loose(const Size(460, 440)), constraints: BoxConstraints.loose(const Size(460, 440)),
triggerActions: triggerActions:
PopoverTriggerActionFlags.click | PopoverTriggerActionFlags.hover, PopoverTriggerActionFlags.click | PopoverTriggerActionFlags.hover,

View File

@ -176,7 +176,7 @@ class CreateFieldButton extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
direction: PopoverDirection.bottomWithRightAligned, direction: PopoverDirection.bottomWithRightAligned,
constraints: BoxConstraints.loose(const Size(240, 200)), constraints: BoxConstraints.loose(const Size(240, 200)),

View File

@ -62,7 +62,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
} }
Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) { Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) {
return AppFlowyStylePopover( return AppFlowyPopover(
mutex: popoverMutex, mutex: popoverMutex,
triggerActions: triggerActions:
PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,
@ -84,7 +84,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
} }
Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) { Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) {
return AppFlowyStylePopover( return AppFlowyPopover(
mutex: popoverMutex, mutex: popoverMutex,
triggerActions: triggerActions:
PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click, PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,

View File

@ -55,7 +55,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
listener: (context, state) => listener: (context, state) =>
typeOptionContext.typeOption = state.typeOption, typeOptionContext.typeOption = state.typeOption,
builder: (context, state) { builder: (context, state) {
return AppFlowyStylePopover( return AppFlowyPopover(
mutex: popoverMutex, mutex: popoverMutex,
triggerActions: PopoverTriggerActionFlags.hover | triggerActions: PopoverTriggerActionFlags.hover |
PopoverTriggerActionFlags.click, PopoverTriggerActionFlags.click,

View File

@ -180,7 +180,7 @@ class _OptionCellState extends State<_OptionCell> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
controller: _popoverController, controller: _popoverController,
mutex: widget.popoverMutex, mutex: widget.popoverMutex,
offset: const Offset(20, 0), offset: const Offset(20, 0),

View File

@ -1,8 +1,10 @@
import 'package:app_flowy/plugins/grid/application/prelude.dart'; 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_cache.dart';
import 'package:app_flowy/plugins/grid/application/row/row_data_controller.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/image.dart';
import 'package:flowy_infra/theme.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:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -56,20 +58,21 @@ class _GridRowWidgetState extends State<GridRowWidget> {
child: BlocBuilder<RowBloc, RowState>( child: BlocBuilder<RowBloc, RowState>(
buildWhen: (p, c) => p.rowInfo.rowPB.height != c.rowInfo.rowPB.height, buildWhen: (p, c) => p.rowInfo.rowPB.height != c.rowInfo.rowPB.height,
builder: (context, state) { builder: (context, state) {
final children = [ final content = Expanded(
const _RowLeading(), child: RowContent(
Expanded( builder: widget.cellBuilder,
child: RowContent( onExpand: () => widget.openDetailPage(
builder: widget.cellBuilder, context,
onExpand: () => widget.openDetailPage( widget.cellBuilder,
context,
widget.cellBuilder,
),
), ),
), ),
);
return Row(children: [
const _RowLeading(),
content,
const _RowTrailing(), const _RowTrailing(),
]; ]);
return Row(children: children);
}, },
), ),
), ),
@ -83,26 +86,51 @@ class _GridRowWidgetState extends State<GridRowWidget> {
} }
} }
class _RowLeading extends StatelessWidget { class _RowLeading extends StatefulWidget {
const _RowLeading({Key? key}) : super(key: key); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<RegionStateNotifier>( return AppFlowyPopover(
builder: (context, state, _) { controller: popoverController,
return SizedBox( constraints: BoxConstraints.loose(const Size(140, 200)),
width: GridSize.leadingHeaderPadding, direction: PopoverDirection.rightWithCenterAligned,
child: state.onEnter ? _activeWidget() : null); popupBuilder: (BuildContext popoverContext) {
return GridRowActionSheet(
rowData: context.read<RowBloc>().state.rowInfo);
}, },
child: Consumer<RegionStateNotifier>(
builder: (context, state, _) {
return SizedBox(
width: GridSize.leadingHeaderPadding,
child: state.onEnter ? _activeWidget() : null,
);
},
),
); );
} }
Widget _activeWidget() { Widget _activeWidget() {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const [ children: [
_InsertRowButton(), const _InsertButton(),
_DeleteRowButton(), _MenuButton(openMenu: () {
popoverController.show();
}),
], ],
); );
} }
@ -117,8 +145,8 @@ class _RowTrailing extends StatelessWidget {
} }
} }
class _InsertRowButton extends StatelessWidget { class _InsertButton extends StatelessWidget {
const _InsertRowButton({Key? key}) : super(key: key); const _InsertButton({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -128,17 +156,29 @@ class _InsertRowButton extends StatelessWidget {
hoverColor: theme.hover, hoverColor: theme.hover,
width: 20, width: 20,
height: 30, height: 30,
onPressed: () => context.read<RowBloc>().add( onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
const RowEvent.createRow(),
),
iconPadding: const EdgeInsets.all(3), iconPadding: const EdgeInsets.all(3),
icon: svgWidget("home/add"), icon: svgWidget("home/add"),
); );
} }
} }
class _DeleteRowButton extends StatelessWidget { class _MenuButton extends StatefulWidget {
const _DeleteRowButton({Key? key}) : super(key: key); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -148,9 +188,7 @@ class _DeleteRowButton extends StatelessWidget {
hoverColor: theme.hover, hoverColor: theme.hover,
width: 20, width: 20,
height: 30, height: 30,
onPressed: () => GridRowActionSheet( onPressed: () => widget.openMenu(),
rowData: context.read<RowBloc>().state.rowInfo,
).show(context),
iconPadding: const EdgeInsets.all(3), iconPadding: const EdgeInsets.all(3),
icon: svgWidget("editor/details"), icon: svgWidget("editor/details"),
); );

View File

@ -3,7 +3,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.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/button.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
@ -27,10 +26,7 @@ class GridRowActionSheet extends StatelessWidget {
final cells = _RowAction.values final cells = _RowAction.values
.where((value) => value.enable()) .where((value) => value.enable())
.map( .map(
(action) => _RowActionCell( (action) => _RowActionCell(action: action),
action: action,
onDismissed: () => remove(context),
),
) )
.toList(); .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 { class _RowActionCell extends StatelessWidget {
final _RowAction action; final _RowAction action;
final VoidCallback onDismissed; const _RowActionCell({required this.action, Key? key}) : super(key: key);
const _RowActionCell(
{required this.action, required this.onDismissed, Key? key})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -101,7 +71,6 @@ class _RowActionCell extends StatelessWidget {
if (action.enable()) { if (action.enable()) {
action.performAction(context); action.performAction(context);
} }
onDismissed();
}, },
leftIcon: svgWidget(action.iconName(), color: theme.iconColor), leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
), ),

View File

@ -194,7 +194,7 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.read<AppTheme>(); final theme = context.read<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
constraints: BoxConstraints.loose(const Size(240, 200)), constraints: BoxConstraints.loose(const Size(240, 200)),
controller: popoverController, controller: popoverController,
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,

View File

@ -99,7 +99,6 @@ class _GridGroupCell extends StatelessWidget {
), ),
); );
onSelected(); onSelected();
// FlowyOverlay.of(context).remove(GridGroupList.identifier());
}, },
), ),
); );

View File

@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget {
} }
Widget _editFieldButton(AppTheme theme, BuildContext context) { Widget _editFieldButton(AppTheme theme, BuildContext context) {
return AppFlowyStylePopover( return AppFlowyPopover(
mutex: popoverMutex, mutex: popoverMutex,
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
offset: const Offset(20, 0), offset: const Offset(20, 0),

View File

@ -40,7 +40,6 @@ class GridSettingList extends StatelessWidget {
previous.selectedAction != current.selectedAction, previous.selectedAction != current.selectedAction,
listener: (context, state) { listener: (context, state) {
state.selectedAction.foldLeft(null, (_, action) { state.selectedAction.foldLeft(null, (_, action) {
FlowyOverlay.of(context).remove(identifier());
onAction(action, settingContext); onAction(action, settingContext);
}); });
}, },

View File

@ -53,7 +53,7 @@ class _SettingButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return AppFlowyStylePopover( return AppFlowyPopover(
constraints: BoxConstraints.loose(const Size(260, 400)), constraints: BoxConstraints.loose(const Size(260, 400)),
triggerActions: PopoverTriggerActionFlags.click, triggerActions: PopoverTriggerActionFlags.click,
offset: const Offset(0, 10), offset: const Offset(0, 10),

View File

@ -2,7 +2,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:appflowy_popover/popover.dart'; import 'package:appflowy_popover/popover.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AppFlowyStylePopover extends StatelessWidget { class AppFlowyPopover extends StatelessWidget {
final Widget child; final Widget child;
final PopoverController? controller; final PopoverController? controller;
final Widget Function(BuildContext context) popupBuilder; final Widget Function(BuildContext context) popupBuilder;
@ -13,7 +13,7 @@ class AppFlowyStylePopover extends StatelessWidget {
final PopoverMutex? mutex; final PopoverMutex? mutex;
final Offset? offset; final Offset? offset;
const AppFlowyStylePopover({ const AppFlowyPopover({
Key? key, Key? key,
required this.child, required this.child,
required this.popupBuilder, required this.popupBuilder,