mask.dart 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import 'dart:collection';
  2. import 'package:appflowy_popover/appflowy_popover.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. typedef EntryMap = LinkedHashMap<PopoverState, OverlayEntryContext>;
  6. class RootOverlayEntry {
  7. final EntryMap _entries = EntryMap();
  8. RootOverlayEntry();
  9. void addEntry(
  10. BuildContext context,
  11. PopoverState newState,
  12. OverlayEntry entry,
  13. bool asBarrier,
  14. ) {
  15. _entries[newState] = OverlayEntryContext(entry, newState, asBarrier);
  16. Overlay.of(context)?.insert(entry);
  17. }
  18. bool contains(PopoverState oldState) {
  19. return _entries.containsKey(oldState);
  20. }
  21. void removeEntry(PopoverState oldState) {
  22. if (_entries.isEmpty) return;
  23. final removedEntry = _entries.remove(oldState);
  24. removedEntry?.overlayEntry.remove();
  25. }
  26. bool get isEmpty => _entries.isEmpty;
  27. bool get isNotEmpty => _entries.isNotEmpty;
  28. bool hasEntry() {
  29. return _entries.isNotEmpty;
  30. }
  31. PopoverState? popEntry() {
  32. if (_entries.isEmpty) return null;
  33. final lastEntry = _entries.values.last;
  34. _entries.remove(lastEntry.popoverState);
  35. lastEntry.overlayEntry.remove();
  36. lastEntry.popoverState.widget.onClose?.call();
  37. if (lastEntry.asBarrier) {
  38. return lastEntry.popoverState;
  39. } else {
  40. return popEntry();
  41. }
  42. }
  43. }
  44. class OverlayEntryContext {
  45. final bool asBarrier;
  46. final PopoverState popoverState;
  47. final OverlayEntry overlayEntry;
  48. OverlayEntryContext(
  49. this.overlayEntry,
  50. this.popoverState,
  51. this.asBarrier,
  52. );
  53. }
  54. class PopoverMask extends StatefulWidget {
  55. final void Function() onTap;
  56. final void Function()? onExit;
  57. final Decoration? decoration;
  58. const PopoverMask(
  59. {Key? key, required this.onTap, this.onExit, this.decoration})
  60. : super(key: key);
  61. @override
  62. State<StatefulWidget> createState() => _PopoverMaskState();
  63. }
  64. class _PopoverMaskState extends State<PopoverMask> {
  65. @override
  66. void initState() {
  67. HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent);
  68. super.initState();
  69. }
  70. bool _handleGlobalKeyEvent(KeyEvent event) {
  71. if (event.logicalKey == LogicalKeyboardKey.escape) {
  72. if (widget.onExit != null) {
  73. widget.onExit!();
  74. }
  75. return true;
  76. } else {
  77. return false;
  78. }
  79. }
  80. @override
  81. void deactivate() {
  82. HardwareKeyboard.instance.removeHandler(_handleGlobalKeyEvent);
  83. super.deactivate();
  84. }
  85. @override
  86. Widget build(BuildContext context) {
  87. return GestureDetector(
  88. onTap: widget.onTap,
  89. child: Container(
  90. decoration: widget.decoration,
  91. ),
  92. );
  93. }
  94. }