diff --git a/lib/frontend/screens/chats/chat_screen.dart b/lib/frontend/screens/chats/chat_screen.dart index f2937d2..dd44b50 100644 --- a/lib/frontend/screens/chats/chat_screen.dart +++ b/lib/frontend/screens/chats/chat_screen.dart @@ -1705,7 +1705,6 @@ class _LongPressBubble extends StatefulWidget { class _LongPressBubbleState extends State<_LongPressBubble> { final GlobalKey _boundaryKey = GlobalKey(); MessageActionsController? _controller; - int? _lastPointerId; @override void dispose() { @@ -1715,9 +1714,6 @@ class _LongPressBubbleState extends State<_LongPressBubble> { } void _onLongPressStart(LongPressStartDetails details) { - final pointerId = _lastPointerId; - if (pointerId == null) return; - final ctx = _boundaryKey.currentContext; if (ctx == null) return; final renderObject = ctx.findRenderObject(); @@ -1738,7 +1734,7 @@ class _LongPressBubbleState extends State<_LongPressBubble> { Haptics.medium(); final controller = MessageActionsController(); - controller.attach(details.globalPosition, pointerId: pointerId); + controller.attach(details.globalPosition); _controller = controller; Navigator.of(ctx) @@ -1764,10 +1760,15 @@ class _LongPressBubbleState extends State<_LongPressBubble> { Widget build(BuildContext context) { return Listener( behavior: HitTestBehavior.deferToChild, - onPointerDown: (event) => _lastPointerId = event.pointer, + onPointerMove: (event) => _controller?.updatePointer(event.position), + onPointerUp: (event) => _controller?.commit(), + onPointerCancel: (event) => _controller?.commit(), child: GestureDetector( behavior: HitTestBehavior.deferToChild, onLongPressStart: _onLongPressStart, + onLongPressMoveUpdate: (d) => + _controller?.updatePointer(d.globalPosition), + onLongPressEnd: (_) => _controller?.commit(), child: RepaintBoundary( key: _boundaryKey, child: widget.child, diff --git a/lib/frontend/widgets/message_actions_overlay.dart b/lib/frontend/widgets/message_actions_overlay.dart index 90bd96d..38801db 100644 --- a/lib/frontend/widgets/message_actions_overlay.dart +++ b/lib/frontend/widgets/message_actions_overlay.dart @@ -10,33 +10,35 @@ import '../../core/utils/haptics.dart'; import 'custom_notification.dart'; class MessageActionsController extends ChangeNotifier { - int? _pointerId; Offset? pointer; Offset? initialPointer; bool committed = false; bool movedSignificantly = false; bool _attached = false; - void attach(Offset initial, {int? pointerId}) { + void attach(Offset initial) { if (_attached) return; _attached = true; - _pointerId = pointerId; initialPointer = initial; pointer = initial; GestureBinding.instance.pointerRouter.addGlobalRoute(_onPointerEvent); } + void updatePointer(Offset p) { + if (committed) return; + pointer = p; + if (initialPointer != null && + !movedSignificantly && + (p - initialPointer!).distance > 18) { + movedSignificantly = true; + } + notifyListeners(); + } + void _onPointerEvent(PointerEvent event) { if (committed) return; - if (_pointerId != null && event.pointer != _pointerId) return; if (event is PointerMoveEvent) { - pointer = event.position; - if (initialPointer != null && - !movedSignificantly && - (event.position - initialPointer!).distance > 18) { - movedSignificantly = true; - } - notifyListeners(); + updatePointer(event.position); } else if (event is PointerUpEvent || event is PointerCancelEvent) { commit(); } @@ -127,7 +129,6 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> { bool _initialized = false; int _hoveredIndex = -1; - bool _tapMode = false; bool _committedFired = false; @override @@ -186,7 +187,7 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> { } void _onControllerUpdate() { - if (!mounted || _tapMode) return; + if (!mounted) return; final p = widget.controller.pointer; if (p != null) { @@ -213,13 +214,11 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> { } void _onCommit() { - if (_hoveredIndex != -1) { + if (_hoveredIndex != -1 && widget.controller.movedSignificantly) { Haptics.medium(); _actions[_hoveredIndex].onTap(); } else if (widget.controller.movedSignificantly) { _close(); - } else { - setState(() => _tapMode = true); } } @@ -255,7 +254,7 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> { final bubbleScale = 1.0 + 0.05 * t; return GestureDetector( - onTap: _tapMode ? _close : null, + onTap: _close, behavior: HitTestBehavior.opaque, child: Stack( children: [ @@ -326,7 +325,6 @@ class _MessageActionsLayerState extends State<_MessageActionsLayer> { child: _ActionButton( action: _actions[i], highlighted: isHovered, - tapEnabled: _tapMode, ), ), ), @@ -394,11 +392,9 @@ class _Action { class _ActionButton extends StatelessWidget { final _Action action; final bool highlighted; - final bool tapEnabled; const _ActionButton({ required this.action, required this.highlighted, - required this.tapEnabled, }); @override @@ -425,12 +421,10 @@ class _ActionButton extends StatelessWidget { shape: const CircleBorder(), child: InkWell( customBorder: const CircleBorder(), - onTap: tapEnabled - ? () { - Haptics.tap(); - action.onTap(); - } - : null, + onTap: () { + Haptics.tap(); + action.onTap(); + }, child: Center( child: Icon(action.icon, color: iconColor, size: 24), ),