fix: подписка на pointer через GestureBinding.pointerRouter вместо Listener (модальный route отрезал hit-цепочку)

This commit is contained in:
klockky
2026-05-23 05:49:21 +00:00
parent 2305860aa3
commit bb867c6816
2 changed files with 39 additions and 16 deletions
+6 -10
View File
@@ -1705,6 +1705,7 @@ class _LongPressBubble extends StatefulWidget {
class _LongPressBubbleState extends State<_LongPressBubble> {
final GlobalKey _boundaryKey = GlobalKey();
MessageActionsController? _controller;
int? _lastPointerId;
@override
void dispose() {
@@ -1714,6 +1715,9 @@ 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();
@@ -1734,7 +1738,7 @@ class _LongPressBubbleState extends State<_LongPressBubble> {
Haptics.medium();
final controller = MessageActionsController();
controller.updatePointer(details.globalPosition);
controller.attach(pointerId, details.globalPosition);
_controller = controller;
Navigator.of(ctx)
@@ -1760,15 +1764,7 @@ class _LongPressBubbleState extends State<_LongPressBubble> {
Widget build(BuildContext context) {
return Listener(
behavior: HitTestBehavior.deferToChild,
onPointerMove: (event) {
_controller?.updatePointer(event.position);
},
onPointerUp: (event) {
_controller?.commit();
},
onPointerCancel: (event) {
_controller?.commit();
},
onPointerDown: (event) => _lastPointerId = event.pointer,
child: GestureDetector(
behavior: HitTestBehavior.deferToChild,
onLongPressStart: _onLongPressStart,
@@ -9,18 +9,34 @@ 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;
void updatePointer(Offset p) {
initialPointer ??= p;
pointer = p;
if (!movedSignificantly && (p - initialPointer!).distance > 18) {
movedSignificantly = true;
void attach(int pointerId, Offset initial) {
if (_pointerId != null) return;
_pointerId = pointerId;
initialPointer = initial;
pointer = initial;
GestureBinding.instance.pointerRouter
.addRoute(pointerId, _onPointerEvent);
}
void _onPointerEvent(PointerEvent event) {
if (committed) return;
if (event is PointerMoveEvent) {
pointer = event.position;
if (initialPointer != null &&
!movedSignificantly &&
(event.position - initialPointer!).distance > 18) {
movedSignificantly = true;
}
notifyListeners();
} else if (event is PointerUpEvent || event is PointerCancelEvent) {
commit();
}
notifyListeners();
}
void commit() {
@@ -28,6 +44,17 @@ class MessageActionsController extends ChangeNotifier {
committed = true;
notifyListeners();
}
@override
void dispose() {
final id = _pointerId;
if (id != null) {
GestureBinding.instance.pointerRouter
.removeRoute(id, _onPointerEvent);
_pointerId = null;
}
super.dispose();
}
}
class MessageActionsRoute extends PageRouteBuilder<void> {