Browse Source

feat: add flags to popover

Vincent Chan 2 years ago
parent
commit
27557c52a3

+ 12 - 38
frontend/app_flowy/packages/appflowy_popover/example/lib/example_button.dart

@@ -7,16 +7,7 @@ class PopoverMenu extends StatefulWidget {
 }
 
 class _PopoverMenuState extends State<PopoverMenu> {
-  final PopoverMutex exclusive = PopoverMutex();
-  late PopoverController firstPopover;
-  late PopoverController secondPopover;
-
-  @override
-  void initState() {
-    firstPopover = PopoverController(mutex: exclusive);
-    secondPopover = PopoverController(mutex: exclusive);
-    super.initState();
-  }
+  final PopoverMutex popOverMutex = PopoverMutex();
 
   @override
   Widget build(BuildContext context) {
@@ -27,7 +18,9 @@ class _PopoverMenuState extends State<PopoverMenu> {
       child: ListView(children: [
         const Text("App"),
         Popover(
-          controller: firstPopover,
+          triggerActions:
+              PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,
+          mutex: popOverMutex,
           offset: const Offset(10, 0),
           targetAnchor: Alignment.topRight,
           followerAnchor: Alignment.topLeft,
@@ -35,19 +28,14 @@ class _PopoverMenuState extends State<PopoverMenu> {
             return PopoverMenu();
           },
           child: TextButton(
-            onPressed: () {
-              firstPopover.show();
-            },
-            onHover: (value) {
-              if (value) {
-                firstPopover.show();
-              }
-            },
+            onPressed: () {},
             child: const Text("First"),
           ),
         ),
         Popover(
-          controller: secondPopover,
+          triggerActions:
+              PopoverTriggerActionFlags.hover | PopoverTriggerActionFlags.click,
+          mutex: popOverMutex,
           offset: const Offset(10, 0),
           targetAnchor: Alignment.topRight,
           followerAnchor: Alignment.topLeft,
@@ -55,14 +43,7 @@ class _PopoverMenuState extends State<PopoverMenu> {
             return PopoverMenu();
           },
           child: TextButton(
-            onPressed: () {
-              secondPopover.show();
-            },
-            onHover: (value) {
-              if (value) {
-                secondPopover.show();
-              }
-            },
+            onPressed: () {},
             child: const Text("Second"),
           ),
         ),
@@ -72,14 +53,12 @@ class _PopoverMenuState extends State<PopoverMenu> {
 }
 
 class ExampleButton extends StatelessWidget {
-  final PopoverController _popover = PopoverController();
-
   final String label;
   final Alignment targetAnchor;
   final Alignment followerAnchor;
   final Offset? offset;
 
-  ExampleButton({
+  const ExampleButton({
     Key? key,
     required this.label,
     this.targetAnchor = Alignment.topLeft,
@@ -90,16 +69,11 @@ class ExampleButton extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return Popover(
-      controller: _popover,
       targetAnchor: targetAnchor,
       followerAnchor: followerAnchor,
+      triggerActions: PopoverTriggerActionFlags.click,
       offset: offset,
-      child: TextButton(
-        onPressed: (() {
-          _popover.show();
-        }),
-        child: Text(label),
-      ),
+      child: TextButton(child: Text(label), onPressed: () {}),
       popupBuilder: (BuildContext context) {
         return PopoverMenu();
       },

+ 42 - 26
frontend/app_flowy/packages/appflowy_popover/lib/popover.dart

@@ -3,32 +3,26 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 
 class PopoverMutex {
-  PopoverController? controller;
+  PopoverState? state;
 }
 
 class PopoverController {
   PopoverState? state;
-  PopoverMutex? mutex;
-
-  PopoverController({this.mutex});
 
   close() {
     state?.close();
-    if (mutex != null && mutex!.controller == this) {
-      mutex!.controller = null;
-    }
   }
 
   show() {
-    if (mutex != null) {
-      debugPrint("show popover");
-      mutex!.controller?.close();
-      mutex!.controller = this;
-    }
     state?.showOverlay();
   }
 }
 
+class PopoverTriggerActionFlags {
+  static int click = 0x01;
+  static int hover = 0x02;
+}
+
 class Popover extends StatefulWidget {
   final Widget child;
   final PopoverController? controller;
@@ -37,6 +31,8 @@ class Popover extends StatefulWidget {
   final Alignment targetAnchor;
   final Alignment followerAnchor;
   final Widget Function(BuildContext context) popupBuilder;
+  final int triggerActions;
+  final PopoverMutex? mutex;
   final void Function()? onClose;
 
   const Popover({
@@ -48,6 +44,8 @@ class Popover extends StatefulWidget {
     this.maskDecoration,
     this.targetAnchor = Alignment.topLeft,
     this.followerAnchor = Alignment.topLeft,
+    this.triggerActions = 0,
+    this.mutex,
     this.onClose,
   }) : super(key: key);
 
@@ -59,20 +57,12 @@ class PopoverState extends State<Popover> {
   final LayerLink layerLink = LayerLink();
   OverlayEntry? _overlayEntry;
   bool hasMask = true;
-  late TapGestureRecognizer _recognizer;
 
   static PopoverState? _popoverWithMask;
 
   @override
   void initState() {
     widget.controller?.state = this;
-    _recognizer = TapGestureRecognizer();
-    _recognizer.onTapDown = (details) {
-      debugPrint("ggg tapdown");
-    };
-    _recognizer.onTap = (() {
-      debugPrint("ggg tap");
-    });
     super.initState();
   }
 
@@ -80,12 +70,19 @@ class PopoverState extends State<Popover> {
     debugPrint("show overlay");
     close();
 
+    if (widget.mutex != null) {
+      if (widget.mutex!.state != null && widget.mutex!.state != this) {
+        widget.mutex!.state!.close();
+      }
+
+      widget.mutex!.state = this;
+    }
+
     if (_popoverWithMask == null) {
       _popoverWithMask = this;
     } else {
       hasMask = false;
     }
-    debugPrint("has mask: $hasMask");
 
     final newEntry = OverlayEntry(builder: (context) {
       final children = <Widget>[];
@@ -126,6 +123,10 @@ class PopoverState extends State<Popover> {
         widget.onClose!();
       }
     }
+
+    if (widget.mutex?.state == this) {
+      widget.mutex!.state = null;
+    }
   }
 
   @override
@@ -135,15 +136,30 @@ class PopoverState extends State<Popover> {
     super.deactivate();
   }
 
-  @override
-  void dispose() {
-    _recognizer.dispose();
-    super.dispose();
+  _handleTargetPointerDown(PointerDownEvent event) {
+    if (widget.triggerActions & PopoverTriggerActionFlags.click != 0) {
+      showOverlay();
+    }
+  }
+
+  _handleTargetPointerEnter(PointerEnterEvent event) {
+    if (widget.triggerActions & PopoverTriggerActionFlags.hover != 0) {
+      showOverlay();
+    }
   }
 
   @override
   Widget build(BuildContext context) {
-    return CompositedTransformTarget(link: layerLink, child: widget.child);
+    return CompositedTransformTarget(
+      link: layerLink,
+      child: MouseRegion(
+        onEnter: _handleTargetPointerEnter,
+        child: Listener(
+          onPointerDown: _handleTargetPointerDown,
+          child: widget.child,
+        ),
+      ),
+    );
   }
 }