import 'dart:math'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'swipe/swipe_controller.dart'; import 'swipe/swipe_config.dart'; import 'package:kaer_with_panels/app/utils/kr_log_util.dart'; class HIEdgeSwipeDetector extends StatefulWidget { final Widget child; final double reservedEdgeWidth; final double detectionEdgeWidth; final double minSwipeDistance; final double minSwipeVelocity; final SwipeConfig? config; const HIEdgeSwipeDetector( {super.key, required this.child, this.reservedEdgeWidth = 0, this.detectionEdgeWidth = 20, this.minSwipeDistance = 20, this.minSwipeVelocity = 300, this.config}); @override State createState() => _HIEdgeSwipeDetectorState(); } class _HIEdgeSwipeDetectorState extends State { Offset? _start; Offset? _last; DateTime? _startTime; final SwipeController _controller = Get.put(SwipeController(), permanent: true); bool _fromLeft = false; bool _fromRight = false; @override Widget build(BuildContext context) { return Stack( fit: StackFit.expand, children: [ widget.child, Positioned( left: 0, top: 0, bottom: 0, width: widget.detectionEdgeWidth, child: GestureDetector( behavior: HitTestBehavior.opaque, onHorizontalDragStart: (details) { _fromLeft = true; _fromRight = false; _start = details.globalPosition; _startTime = DateTime.now(); KRLogUtil.kr_d('dragStart LEFT x=${details.globalPosition.dx}', tag: 'HIEdgeSwipeDetector'); }, onHorizontalDragUpdate: (details) { _last = details.globalPosition; KRLogUtil.kr_d('dragUpdate LEFT dx=${details.delta.dx}', tag: 'HIEdgeSwipeDetector'); }, onHorizontalDragEnd: (details) { if (_start == null || _startTime == null) return; final durationMs = DateTime.now().difference(_startTime!).inMilliseconds; final velocity = details.velocity.pixelsPerSecond.dx.abs(); final distance = _last != null ? (_last!.dx - _start!.dx) : 0.0; final okByVelocity = velocity >= widget.minSwipeVelocity; final okByDistance = distance.abs() >= widget.minSwipeDistance; KRLogUtil.kr_d( 'dragEnd LEFT vel=${details.velocity.pixelsPerSecond.dx} dur=$durationMs dist=$distance okV=$okByVelocity okD=$okByDistance', tag: 'HIEdgeSwipeDetector'); if (!okByVelocity && !okByDistance) { _reset(); return; } if (distance > 0) { final cfg = widget.config; if (cfg == null || !cfg.enableLeft) { _reset(); return; } if (cfg.onLeft != null) { cfg.onLeft!(); } else { Get.back(); } } _reset(); }, ), ), Positioned( right: 0, top: 0, bottom: 0, width: widget.detectionEdgeWidth, child: GestureDetector( behavior: HitTestBehavior.opaque, onHorizontalDragStart: (details) { _fromLeft = false; _fromRight = true; _start = details.globalPosition; _startTime = DateTime.now(); KRLogUtil.kr_d('dragStart RIGHT x=${details.globalPosition.dx}', tag: 'HIEdgeSwipeDetector'); }, onHorizontalDragUpdate: (details) { _last = details.globalPosition; KRLogUtil.kr_d('dragUpdate RIGHT dx=${details.delta.dx}', tag: 'HIEdgeSwipeDetector'); }, onHorizontalDragEnd: (details) { if (_start == null || _startTime == null) return; final durationMs = DateTime.now().difference(_startTime!).inMilliseconds; final velocity = details.velocity.pixelsPerSecond.dx.abs(); final distance = _last != null ? (_last!.dx - _start!.dx) : 0.0; final okByVelocity = velocity >= widget.minSwipeVelocity; final okByDistance = distance.abs() >= widget.minSwipeDistance; KRLogUtil.kr_d( 'dragEnd RIGHT vel=${details.velocity.pixelsPerSecond.dx} dur=$durationMs dist=$distance okV=$okByVelocity okD=$okByDistance', tag: 'HIEdgeSwipeDetector'); if (!okByVelocity && !okByDistance) { _reset(); return; } if (distance < 0) { final cfg = widget.config; if (cfg == null || !cfg.enableRight) { _reset(); return; } if (cfg.onRight != null) { cfg.onRight!(); } else { _controller.openRightMenu(); } } _reset(); }, ), ), ], ); } void _reset() { _start = null; _last = null; _startTime = null; _fromLeft = false; _fromRight = false; } }