Showing
6 changed files
with
197 additions
and
3 deletions
| @@ -19,7 +19,8 @@ class AutoTrackConfig { | @@ -19,7 +19,8 @@ class AutoTrackConfig { | ||
| 19 | this.enablePageView = true, | 19 | this.enablePageView = true, |
| 20 | this.enablePageLeave = false, | 20 | this.enablePageLeave = false, |
| 21 | this.enableClick = true, | 21 | this.enableClick = true, |
| 22 | - this.enableUpload = false | 22 | + this.enableUpload = false, |
| 23 | + this.enableDrag = false | ||
| 23 | }) { | 24 | }) { |
| 24 | trackId ??= const Uuid().v4().replaceAll('-', ''); | 25 | trackId ??= const Uuid().v4().replaceAll('-', ''); |
| 25 | signature ??= (t) => sha256.convert(utf8.encode('$appKey$t$appSecret')).toString(); | 26 | signature ??= (t) => sha256.convert(utf8.encode('$appKey$t$appSecret')).toString(); |
| @@ -55,6 +56,8 @@ class AutoTrackConfig { | @@ -55,6 +56,8 @@ class AutoTrackConfig { | ||
| 55 | bool enableClick; | 56 | bool enableClick; |
| 56 | 57 | ||
| 57 | bool enableUpload; | 58 | bool enableUpload; |
| 59 | + | ||
| 60 | + bool enableDrag; | ||
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | typedef PageWidgetFunc = bool Function(Widget); | 63 | typedef PageWidgetFunc = bool Function(Widget); |
| @@ -64,6 +64,10 @@ class AutoTrackConfigManager { | @@ -64,6 +64,10 @@ class AutoTrackConfigManager { | ||
| 64 | _config.enableClick = enable; | 64 | _config.enableClick = enable; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | + void enableDrag(bool enable) { | ||
| 68 | + _config.enableDrag = enable; | ||
| 69 | + } | ||
| 70 | + | ||
| 67 | void enableAutoTrack(bool enable) { | 71 | void enableAutoTrack(bool enable) { |
| 68 | _autoTrackEnable = enable; | 72 | _autoTrackEnable = enable; |
| 69 | } | 73 | } |
| @@ -102,6 +106,11 @@ class AutoTrackConfigManager { | @@ -102,6 +106,11 @@ class AutoTrackConfigManager { | ||
| 102 | if (getIgnoreElementStringKeySet().contains(key.toString())) { | 106 | if (getIgnoreElementStringKeySet().contains(key.toString())) { |
| 103 | return true; | 107 | return true; |
| 104 | } | 108 | } |
| 109 | + | ||
| 110 | + if (key is ValueKey) { | ||
| 111 | + return getIgnoreElementStringKeySet().contains(key.value); | ||
| 112 | + } | ||
| 113 | + | ||
| 105 | return false; | 114 | return false; |
| 106 | } | 115 | } |
| 107 | 116 | ||
| @@ -110,4 +119,6 @@ class AutoTrackConfigManager { | @@ -110,4 +119,6 @@ class AutoTrackConfigManager { | ||
| 110 | bool get pageLeaveEnable => _config.enablePageLeave; | 119 | bool get pageLeaveEnable => _config.enablePageLeave; |
| 111 | 120 | ||
| 112 | bool get clickEnable => _config.enableClick; | 121 | bool get clickEnable => _config.enableClick; |
| 122 | + | ||
| 123 | + bool get dragEnable => _config.enableDrag; | ||
| 113 | } | 124 | } |
lib/auto_track/drag/drag_info.dart
0 → 100644
| 1 | +import 'package:flutter/widgets.dart'; | ||
| 2 | + | ||
| 3 | +import '../config/manager.dart'; | ||
| 4 | +import '../page_view/page_info.dart'; | ||
| 5 | + | ||
| 6 | +class DragInfo { | ||
| 7 | + DragInfo._(this.pageInfo); | ||
| 8 | + | ||
| 9 | + factory DragInfo.from( | ||
| 10 | + {required Offset begin, | ||
| 11 | + required Offset end, | ||
| 12 | + required Element pageElement, | ||
| 13 | + required PageInfo pageInfo, | ||
| 14 | + required int duration}) { | ||
| 15 | + DragInfo dragInfo = DragInfo._(pageInfo); | ||
| 16 | + dragInfo._beginOffset = begin; | ||
| 17 | + dragInfo._endOffset = end; | ||
| 18 | + dragInfo._duration = duration; | ||
| 19 | + dragInfo._ignore = AutoTrackConfigManager.instance.isIgnoreElement( | ||
| 20 | + pageElement.widget.key ?? ValueKey(pageInfo.pageManualKey)); | ||
| 21 | + | ||
| 22 | + double dx = dragInfo.endOffset.dx - dragInfo.beginOffset.dx; | ||
| 23 | + double dy = dragInfo.endOffset.dy - dragInfo.beginOffset.dy; | ||
| 24 | + | ||
| 25 | + var direction = 'down'; | ||
| 26 | + if (dx.abs() > dy.abs()) { | ||
| 27 | + if (dx > 0) { | ||
| 28 | + direction = 'right'; | ||
| 29 | + } else { | ||
| 30 | + direction = 'left'; | ||
| 31 | + } | ||
| 32 | + } else if (dy.abs() > dx.abs()) { | ||
| 33 | + if (dy > 0) { | ||
| 34 | + direction = 'down'; | ||
| 35 | + } else { | ||
| 36 | + direction = 'up'; | ||
| 37 | + } | ||
| 38 | + } else { | ||
| 39 | + direction = 'none'; | ||
| 40 | + } | ||
| 41 | + dragInfo._direction = direction; | ||
| 42 | + | ||
| 43 | + return dragInfo; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + Offset _beginOffset = Offset.zero; | ||
| 47 | + Offset get beginOffset => _beginOffset; | ||
| 48 | + | ||
| 49 | + Offset _endOffset = Offset.zero; | ||
| 50 | + Offset get endOffset => _endOffset; | ||
| 51 | + | ||
| 52 | + bool _ignore = false; | ||
| 53 | + bool get ignore => _ignore; | ||
| 54 | + | ||
| 55 | + String _direction = 'none'; | ||
| 56 | + String get direction => _direction; | ||
| 57 | + | ||
| 58 | + int _duration = 0; | ||
| 59 | + int get duration => _duration; | ||
| 60 | + | ||
| 61 | + final PageInfo pageInfo; | ||
| 62 | + | ||
| 63 | + @override | ||
| 64 | + String toString() { | ||
| 65 | + return [ | ||
| 66 | + 'beginOffset: $beginOffset', | ||
| 67 | + 'endOffset: $endOffset', | ||
| 68 | + 'pageInfo: $pageInfo', | ||
| 69 | + ].join(', '); | ||
| 70 | + } | ||
| 71 | +} |
| 1 | +import 'package:auto_track/auto_track/drag/drag_info.dart'; | ||
| 2 | +import 'package:auto_track/auto_track/track/track.dart'; | ||
| 3 | +import 'package:flutter/gestures.dart'; | ||
| 4 | + | ||
| 5 | +import '../page_view/page_stack.dart'; | ||
| 6 | + | ||
| 7 | +class DragPointerEventListener { | ||
| 8 | + static final DragPointerEventListener instance = DragPointerEventListener._(); | ||
| 9 | + DragPointerEventListener._(); | ||
| 10 | + bool _started = false; | ||
| 11 | + late _AutoTrackPanGestureRecognizer _panGestureRecognizer; | ||
| 12 | + | ||
| 13 | + void start() { | ||
| 14 | + if (!_started) { | ||
| 15 | + _panGestureRecognizer = _AutoTrackPanGestureRecognizer(); | ||
| 16 | + GestureBinding.instance?.pointerRouter | ||
| 17 | + .addGlobalRoute(_panGestureRecognizer.addPointer); | ||
| 18 | + _started = true; | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + void stop() { | ||
| 23 | + if (_started) { | ||
| 24 | + GestureBinding.instance?.pointerRouter | ||
| 25 | + .removeGlobalRoute(_panGestureRecognizer.addPointer); | ||
| 26 | + _panGestureRecognizer.dispose(); | ||
| 27 | + _started = false; | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +class _AutoTrackPanGestureRecognizer extends PanGestureRecognizer { | ||
| 33 | + _AutoTrackPanGestureRecognizer({Object? debugOwner}) | ||
| 34 | + : super(debugOwner: debugOwner); | ||
| 35 | + | ||
| 36 | + PointerAddedEvent? beginEvent; | ||
| 37 | + int startTime = 0; | ||
| 38 | + | ||
| 39 | + @override | ||
| 40 | + void addPointer(PointerEvent event) { | ||
| 41 | + resolve(GestureDisposition.accepted); | ||
| 42 | + | ||
| 43 | + final page = PageStack.instance.getCurrentPage(); | ||
| 44 | + if (page == null) { | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + if (event is PointerAddedEvent) { | ||
| 48 | + beginEvent = event; | ||
| 49 | + startTime = DateTime.now().millisecondsSinceEpoch; | ||
| 50 | + } else if (event is PointerRemovedEvent) { | ||
| 51 | + if (beginEvent != null) { | ||
| 52 | + final distance = (beginEvent!.position.dx - event.position.dx).abs() + | ||
| 53 | + (beginEvent!.position.dy - event.position.dy).abs(); | ||
| 54 | + if (distance > 30) { | ||
| 55 | + final info = DragInfo.from( | ||
| 56 | + begin: beginEvent!.position, | ||
| 57 | + end: event.position, | ||
| 58 | + pageElement: page!.element, | ||
| 59 | + pageInfo: page!.pageInfo, | ||
| 60 | + duration: DateTime.now().millisecondsSinceEpoch - startTime); | ||
| 61 | + if (!info.ignore) { | ||
| 62 | + Track.instance.drag(info); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + beginEvent = null; | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | +} |
| 1 | +import 'package:auto_track/auto_track/drag/drag_pointer_event_listener.dart'; | ||
| 1 | import 'package:flutter/foundation.dart'; | 2 | import 'package:flutter/foundation.dart'; |
| 2 | 3 | ||
| 3 | import 'click/pointer_event_listener.dart'; | 4 | import 'click/pointer_event_listener.dart'; |
| @@ -81,6 +82,16 @@ class AutoTrack { | @@ -81,6 +82,16 @@ class AutoTrack { | ||
| 81 | return _instance; | 82 | return _instance; |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 85 | + AutoTrack enableDrag() { | ||
| 86 | + AutoTrackConfigManager.instance.enableDrag(true); | ||
| 87 | + return _instance; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + AutoTrack disableDrag() { | ||
| 91 | + AutoTrackConfigManager.instance.enableDrag(true); | ||
| 92 | + return _instance; | ||
| 93 | + } | ||
| 94 | + | ||
| 84 | AutoTrack disableClick() { | 95 | AutoTrack disableClick() { |
| 85 | AutoTrackConfigManager.instance.enableClick(false); | 96 | AutoTrackConfigManager.instance.enableClick(false); |
| 86 | return _instance; | 97 | return _instance; |
| @@ -89,12 +100,14 @@ class AutoTrack { | @@ -89,12 +100,14 @@ class AutoTrack { | ||
| 89 | AutoTrack enable() { | 100 | AutoTrack enable() { |
| 90 | AutoTrackConfigManager.instance.enableAutoTrack(true); | 101 | AutoTrackConfigManager.instance.enableAutoTrack(true); |
| 91 | PointerEventListener.instance.start(); | 102 | PointerEventListener.instance.start(); |
| 103 | + DragPointerEventListener.instance.start(); | ||
| 92 | return _instance; | 104 | return _instance; |
| 93 | } | 105 | } |
| 94 | 106 | ||
| 95 | AutoTrack disable() { | 107 | AutoTrack disable() { |
| 96 | AutoTrackConfigManager.instance.enableAutoTrack(false); | 108 | AutoTrackConfigManager.instance.enableAutoTrack(false); |
| 97 | PointerEventListener.instance.stop(); | 109 | PointerEventListener.instance.stop(); |
| 110 | + DragPointerEventListener.instance.stop(); | ||
| 98 | return _instance; | 111 | return _instance; |
| 99 | } | 112 | } |
| 100 | 113 |
| 1 | import 'package:auto_track/auto_track/config/queue.dart'; | 1 | import 'package:auto_track/auto_track/config/queue.dart'; |
| 2 | +import 'package:auto_track/auto_track/drag/drag_info.dart'; | ||
| 2 | import 'package:auto_track/auto_track/utils/track_model.dart'; | 3 | import 'package:auto_track/auto_track/utils/track_model.dart'; |
| 3 | 4 | ||
| 4 | import '../click/click_info.dart'; | 5 | import '../click/click_info.dart'; |
| @@ -68,6 +69,32 @@ class Track { | @@ -68,6 +69,32 @@ class Track { | ||
| 68 | AutoTrackLogger.getInstance().debug('track click => $params'); | 69 | AutoTrackLogger.getInstance().debug('track click => $params'); |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 72 | + void drag(DragInfo dragInfo) { | ||
| 73 | + if (!AutoTrackConfigManager.instance.autoTrackEnable) { | ||
| 74 | + return; | ||
| 75 | + } | ||
| 76 | + if (!AutoTrackConfigManager.instance.dragEnable) { | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + Map<String, dynamic> params = {}; | ||
| 80 | + params['manual_key'] = 'drag'; | ||
| 81 | + params['begin'] = { | ||
| 82 | + 'x': dragInfo.beginOffset.dx, | ||
| 83 | + 'y': dragInfo.beginOffset.dy, | ||
| 84 | + }; | ||
| 85 | + params['end'] = { | ||
| 86 | + 'x': dragInfo.endOffset.dx, | ||
| 87 | + 'y': dragInfo.endOffset.dy, | ||
| 88 | + }; | ||
| 89 | + params['drag_duration'] = dragInfo.duration; | ||
| 90 | + params['drag_direction'] = dragInfo.direction; | ||
| 91 | + | ||
| 92 | + _appendPageInfo(params, dragInfo.pageInfo); | ||
| 93 | + _TrackPlugin.drag(params); | ||
| 94 | + AutoTrackLogger.getInstance().debug('track drag => $params'); | ||
| 95 | + | ||
| 96 | + } | ||
| 97 | + | ||
| 71 | void customEvent(String type, Map<String, dynamic> params) { | 98 | void customEvent(String type, Map<String, dynamic> params) { |
| 72 | _TrackPlugin.customEvent(type, params); | 99 | _TrackPlugin.customEvent(type, params); |
| 73 | AutoTrackLogger.getInstance().debug('track custom_event => $params'); | 100 | AutoTrackLogger.getInstance().debug('track custom_event => $params'); |
| @@ -92,7 +119,7 @@ class _TrackPlugin { | @@ -92,7 +119,7 @@ class _TrackPlugin { | ||
| 92 | AutoTrackQueue.instance.appendQueue(TrackModel(type, DateTime.now().millisecondsSinceEpoch, params, params['key'] ?? type)); | 119 | AutoTrackQueue.instance.appendQueue(TrackModel(type, DateTime.now().millisecondsSinceEpoch, params, params['key'] ?? type)); |
| 93 | } | 120 | } |
| 94 | 121 | ||
| 95 | - static void scroll(Map<String, dynamic> params) { | ||
| 96 | - // AutoTrackQueue.instance.appendQueue(TrackModel('scroll', DateTime.now().millisecondsSinceEpoch, params)); | 122 | + static void drag(Map<String, dynamic> params) { |
| 123 | + AutoTrackQueue.instance.appendQueue(TrackModel('drag', DateTime.now().millisecondsSinceEpoch, params, params['manual_key'])); | ||
| 97 | } | 124 | } |
| 98 | } | 125 | } |
-
Please register or login to post a comment