pop_up_action.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import 'package:flowy_infra/theme.dart';
  2. import 'package:flowy_infra_ui/flowy_infra_ui.dart';
  3. import 'package:flowy_infra_ui/style_widget/hover.dart';
  4. import 'package:flowy_infra_ui/style_widget/text.dart';
  5. import 'package:flowy_infra_ui/widget/spacing.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:provider/provider.dart';
  8. import 'package:styled_widget/styled_widget.dart';
  9. import 'package:dartz/dartz.dart' as dartz;
  10. abstract class ActionList<T extends ActionItemData> {
  11. List<T> get items;
  12. String get identifier => toString();
  13. double get maxWidth => 162;
  14. double get itemHeight => ActionListSizes.itemHeight;
  15. ListOverlayFooter? get footer;
  16. void Function(dartz.Option<T>) get selectCallback;
  17. FlowyOverlayDelegate? get delegate;
  18. void show(
  19. BuildContext buildContext,
  20. BuildContext anchorContext, {
  21. AnchorDirection anchorDirection = AnchorDirection.bottomRight,
  22. Offset? anchorOffset,
  23. }) {
  24. final widgets = items
  25. .map(
  26. (action) => ActionItem<T>(
  27. action: action,
  28. itemHeight: itemHeight,
  29. onSelected: (action) {
  30. FlowyOverlay.of(buildContext).remove(identifier);
  31. selectCallback(dartz.some(action));
  32. },
  33. ),
  34. )
  35. .toList();
  36. ListOverlay.showWithAnchor(
  37. buildContext,
  38. identifier: identifier,
  39. itemCount: widgets.length,
  40. itemBuilder: (context, index) => widgets[index],
  41. anchorContext: anchorContext,
  42. anchorDirection: anchorDirection,
  43. width: maxWidth,
  44. height: widgets.length * (itemHeight + ActionListSizes.padding * 2),
  45. delegate: delegate,
  46. anchorOffset: anchorOffset,
  47. footer: footer,
  48. );
  49. }
  50. }
  51. abstract class ActionItemData {
  52. Widget? get icon;
  53. String get name;
  54. }
  55. class ActionListSizes {
  56. static double itemHPadding = 10;
  57. static double itemHeight = 16;
  58. static double padding = 6;
  59. }
  60. class ActionItem<T extends ActionItemData> extends StatelessWidget {
  61. final T action;
  62. final Function(T) onSelected;
  63. final double itemHeight;
  64. const ActionItem({
  65. Key? key,
  66. required this.action,
  67. required this.onSelected,
  68. required this.itemHeight,
  69. }) : super(key: key);
  70. @override
  71. Widget build(BuildContext context) {
  72. final theme = context.watch<AppTheme>();
  73. return FlowyHover(
  74. config: HoverDisplayConfig(hoverColor: theme.hover),
  75. builder: (context, onHover) {
  76. return GestureDetector(
  77. behavior: HitTestBehavior.opaque,
  78. onTap: () => onSelected(action),
  79. child: SizedBox(
  80. height: itemHeight,
  81. child: Row(
  82. children: [
  83. if (action.icon != null) action.icon!,
  84. HSpace(ActionListSizes.itemHPadding),
  85. FlowyText.medium(
  86. action.name,
  87. fontSize: 12,
  88. ),
  89. ],
  90. ),
  91. ).padding(
  92. horizontal: ActionListSizes.padding,
  93. vertical: ActionListSizes.padding,
  94. ),
  95. );
  96. },
  97. );
  98. }
  99. }