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