react-native-acoustic-connect-beta 18.0.13 → 18.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/Examples/SampleUI/.detoxrc.js +83 -0
  2. package/Examples/SampleUI/ConnectConfig.json +2 -2
  3. package/Examples/SampleUI/android/app/build.gradle +3 -0
  4. package/Examples/SampleUI/android/app/src/main/java/com/sampleui/MainActivity.kt +0 -35
  5. package/Examples/SampleUI/android/settings.gradle +1 -1
  6. package/Examples/SampleUI/package.json +8 -6
  7. package/Examples/SampleUI/scripts/integration-test-android.sh +292 -0
  8. package/Examples/SampleUI/src/Examples/DialogExample.tsx +88 -2
  9. package/Examples/SampleUI/src/Examples/Dialogs/DialogTrackingTest.tsx +307 -0
  10. package/Examples/SampleUI/src/Examples/Dialogs/index.tsx +37 -0
  11. package/Examples/SampleUI/src/index.native.tsx +5 -5
  12. package/android/build.gradle +2 -2
  13. package/android/src/main/assets/ConnectAdvancedConfig.json +1 -1
  14. package/android/src/main/assets/TealeafAdvancedConfig.json +1 -1
  15. package/android/src/main/java/com/acousticconnectrn/HybridAcousticConnectRN.kt +787 -490
  16. package/ios/HybridAcousticConnectRN.swift +79 -4
  17. package/lib/commonjs/TLTRN.js +69 -0
  18. package/lib/commonjs/TLTRN.js.map +1 -1
  19. package/lib/commonjs/components/Connect.js +31 -29
  20. package/lib/commonjs/components/Connect.js.map +1 -1
  21. package/lib/commonjs/docs/DialogTracking.md +252 -0
  22. package/lib/commonjs/docs/NativeImplementation.md +176 -0
  23. package/lib/commonjs/examples/DialogTrackingExample.js +175 -0
  24. package/lib/commonjs/examples/DialogTrackingExample.js.map +1 -0
  25. package/lib/commonjs/examples/HOCDialogExample.js +296 -0
  26. package/lib/commonjs/examples/HOCDialogExample.js.map +1 -0
  27. package/lib/commonjs/index.js +28 -0
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/utils/DialogDebugger.js +216 -0
  30. package/lib/commonjs/utils/DialogDebugger.js.map +1 -0
  31. package/lib/commonjs/utils/DialogListener.js +203 -0
  32. package/lib/commonjs/utils/DialogListener.js.map +1 -0
  33. package/lib/commonjs/utils/useDialogTracking.js +107 -0
  34. package/lib/commonjs/utils/useDialogTracking.js.map +1 -0
  35. package/lib/commonjs/utils/withAcousticAutoDialog.js +282 -0
  36. package/lib/commonjs/utils/withAcousticAutoDialog.js.map +1 -0
  37. package/lib/module/TLTRN.js +69 -0
  38. package/lib/module/TLTRN.js.map +1 -1
  39. package/lib/module/components/Connect.js +32 -31
  40. package/lib/module/components/Connect.js.map +1 -1
  41. package/lib/module/docs/DialogTracking.md +252 -0
  42. package/lib/module/docs/NativeImplementation.md +176 -0
  43. package/lib/module/examples/DialogTrackingExample.js +172 -0
  44. package/lib/module/examples/DialogTrackingExample.js.map +1 -0
  45. package/lib/module/examples/HOCDialogExample.js +292 -0
  46. package/lib/module/examples/HOCDialogExample.js.map +1 -0
  47. package/lib/module/index.js +5 -1
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/utils/DialogDebugger.js +211 -0
  50. package/lib/module/utils/DialogDebugger.js.map +1 -0
  51. package/lib/module/utils/DialogListener.js +199 -0
  52. package/lib/module/utils/DialogListener.js.map +1 -0
  53. package/lib/module/utils/useDialogTracking.js +102 -0
  54. package/lib/module/utils/useDialogTracking.js.map +1 -0
  55. package/lib/module/utils/withAcousticAutoDialog.js +275 -0
  56. package/lib/module/utils/withAcousticAutoDialog.js.map +1 -0
  57. package/lib/typescript/src/TLTRN.d.ts +7 -0
  58. package/lib/typescript/src/TLTRN.d.ts.map +1 -1
  59. package/lib/typescript/src/components/Connect.d.ts +2 -2
  60. package/lib/typescript/src/components/Connect.d.ts.map +1 -1
  61. package/lib/typescript/src/examples/DialogTrackingExample.d.ts +17 -0
  62. package/lib/typescript/src/examples/DialogTrackingExample.d.ts.map +1 -0
  63. package/lib/typescript/src/examples/HOCDialogExample.d.ts +21 -0
  64. package/lib/typescript/src/examples/HOCDialogExample.d.ts.map +1 -0
  65. package/lib/typescript/src/index.d.ts +5 -1
  66. package/lib/typescript/src/index.d.ts.map +1 -1
  67. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts +4 -0
  68. package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts.map +1 -1
  69. package/lib/typescript/src/utils/DialogDebugger.d.ts +58 -0
  70. package/lib/typescript/src/utils/DialogDebugger.d.ts.map +1 -0
  71. package/lib/typescript/src/utils/DialogListener.d.ts +85 -0
  72. package/lib/typescript/src/utils/DialogListener.d.ts.map +1 -0
  73. package/lib/typescript/src/utils/useDialogTracking.d.ts +25 -0
  74. package/lib/typescript/src/utils/useDialogTracking.d.ts.map +1 -0
  75. package/lib/typescript/src/utils/withAcousticAutoDialog.d.ts +37 -0
  76. package/lib/typescript/src/utils/withAcousticAutoDialog.d.ts.map +1 -0
  77. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.cpp +26 -0
  78. package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.hpp +4 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/HybridAcousticConnectRNSpec.kt +16 -0
  80. package/nitrogen/generated/ios/c++/HybridAcousticConnectRNSpecSwift.hpp +32 -0
  81. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec.swift +4 -0
  82. package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec_cxx.swift +71 -0
  83. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.cpp +4 -0
  84. package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.hpp +4 -0
  85. package/package.json +1 -1
  86. package/scripts/ConnectConfig.json +1 -1
  87. package/src/TLTRN.ts +75 -0
  88. package/src/components/Connect.tsx +92 -101
  89. package/src/docs/DialogTracking.md +252 -0
  90. package/src/docs/NativeImplementation.md +176 -0
  91. package/src/examples/DialogTrackingExample.tsx +163 -0
  92. package/src/examples/HOCDialogExample.tsx +253 -0
  93. package/src/index.ts +5 -1
  94. package/src/specs/react-native-acoustic-connect.nitro.ts +5 -0
  95. package/src/utils/DialogDebugger.ts +224 -0
  96. package/src/utils/DialogListener.ts +238 -0
  97. package/src/utils/useDialogTracking.ts +102 -0
  98. package/src/utils/withAcousticAutoDialog.tsx +312 -0
package/src/TLTRN.ts CHANGED
@@ -12,6 +12,8 @@
12
12
  import MessageQueue from "react-native/Libraries/BatchedBridge/MessageQueue.js";
13
13
  import { Platform } from "react-native";
14
14
  import KeyboardListener from "./utils/KeyboardListener";
15
+ import DialogListener from "./utils/DialogListener";
16
+ import type { DialogEvent, DialogButtonClickEvent, DialogDismissEvent } from "./utils/DialogListener";
15
17
  import AcousticConnectRN from './index';
16
18
 
17
19
  // @ts-ignore
@@ -153,6 +155,79 @@ class TLTRN {
153
155
  return result;
154
156
  };
155
157
 
158
+ // New dialog event logging methods
159
+ static logDialogShowEvent = async (dialogId: string, dialogTitle: string, dialogType: string) => {
160
+ let result = false
161
+ try {
162
+ result = AcousticConnectRN.logDialogShowEvent(dialogId, dialogTitle, dialogType);
163
+ } catch (error: Error | any) {
164
+ console.log('LogDialogShowEvent error: ', error.message);
165
+ }
166
+ return result;
167
+ };
168
+
169
+ static logDialogDismissEvent = async (dialogId: string, dismissReason: string) => {
170
+ let result = false
171
+ try {
172
+ result = AcousticConnectRN.logDialogDismissEvent(dialogId, dismissReason);
173
+ } catch (error: Error | any) {
174
+ console.log('LogDialogDismissEvent error: ', error.message);
175
+ }
176
+ return result;
177
+ };
178
+
179
+ static logDialogButtonClickEvent = async (dialogId: string, buttonText: string, buttonIndex: number) => {
180
+ let result = false
181
+ try {
182
+ result = AcousticConnectRN.logDialogButtonClickEvent(dialogId, buttonText, buttonIndex);
183
+ } catch (error: Error | any) {
184
+ console.log('LogDialogButtonClickEvent error: ', error.message);
185
+ }
186
+ return result;
187
+ };
188
+
189
+ static logDialogCustomEvent = async (dialogId: string, eventName: string, values: Record<string, string | number | boolean>) => {
190
+ let result = false
191
+ try {
192
+ result = AcousticConnectRN.logDialogCustomEvent(dialogId, eventName, values);
193
+ } catch (error: Error | any) {
194
+ console.log('LogDialogCustomEvent error: ', error.message);
195
+ }
196
+ return result;
197
+ };
198
+
199
+ // Dialog event interceptor methods
200
+ static eventListenerRegistered = false;
201
+ static eventListenerUnsubscribe: (() => void) | null = null;
202
+
203
+ static interceptDialogEvents = (enable: boolean) => {
204
+ const dialogListener = DialogListener.getInstance();
205
+
206
+ if (enable && !TLTRN.eventListenerRegistered) {
207
+ dialogListener.startIntercepting();
208
+ TLTRN.eventListenerUnsubscribe = dialogListener.addEventListener((event: DialogEvent | DialogButtonClickEvent | DialogDismissEvent) => {
209
+ if ('buttonText' in event) {
210
+ // This is a button click event
211
+ TLTRN.logDialogButtonClickEvent(event.dialogId, event.buttonText, event.buttonIndex);
212
+ } else if ('dismissReason' in event) {
213
+ // This is a dialog dismiss event
214
+ TLTRN.logDialogDismissEvent(event.dialogId, event.dismissReason);
215
+ } else {
216
+ // This is a dialog show event
217
+ TLTRN.logDialogShowEvent(event.dialogId, event.dialogTitle, event.dialogType);
218
+ }
219
+ });
220
+ TLTRN.eventListenerRegistered = true;
221
+ } else if (!enable && TLTRN.eventListenerRegistered) {
222
+ dialogListener.stopIntercepting();
223
+ if (TLTRN.eventListenerUnsubscribe) {
224
+ TLTRN.eventListenerUnsubscribe();
225
+ TLTRN.eventListenerUnsubscribe = null;
226
+ }
227
+ TLTRN.eventListenerRegistered = false;
228
+ }
229
+ };
230
+
156
231
  static listenToBridge = (message: any) => {
157
232
  if (TLTRN.displayDebug) {
158
233
  console.log(
@@ -9,118 +9,109 @@
9
9
  ********************************************************************************************/
10
10
  import React, { useCallback, useEffect, useRef, forwardRef } from "react";
11
11
  import { View, StyleSheet, Platform, NativeModules, findNodeHandle } from "react-native";
12
- import type { LayoutChangeEvent } from "react-native";
13
- import TLTRN from "../TLTRN";
12
+ import type { LayoutChangeEvent } from "react-native"; // Use type-only import for LayoutChangeEvent
13
+ import TLTRN from '../TLTRN';
14
14
 
15
15
  interface ConnectProps {
16
16
  children: React.ReactNode;
17
17
  captureKeyboardEvents: boolean;
18
- navigationRef?: React.RefObject<any>;
18
+ captureDialogEvents?: boolean; // New prop for dialog event capture
19
19
  }
20
20
 
21
- const Connect = forwardRef<any, ConnectProps>(
22
- ({ children, captureKeyboardEvents, navigationRef }, ref) => {
23
- const navigation = navigationRef || useRef(null);
24
-
25
- // Handle forwarded ref
26
- useEffect(() => {
27
- if (ref && typeof ref === "object" && ref !== null) {
28
- navigation.current = ref.current;
29
- } else if (typeof ref === "function") {
30
- ref(navigation.current);
31
- }
32
- }, [ref]);
33
-
34
- const currentRoute = useRef<string | undefined>(undefined);
35
- const initial = useRef<boolean>(false);
36
-
37
- useEffect(() => {
38
- TLTRN.interceptKeyboardEvents(captureKeyboardEvents);
39
- }, [captureKeyboardEvents]);
40
-
41
- useEffect(() => {
42
- if (
43
- !navigation.current ||
44
- typeof navigation.current.addListener !== "function" ||
45
- typeof navigation.current.getCurrentRoute !== "function"
46
- ) {
47
- console.warn(
48
- "Connect: The Connect component's ref must be a NavigationContainer with a ref."
49
- );
50
- return;
51
- }
52
-
53
- const unsubscribe = navigation.current.addListener("state", () => {
54
- currentRoute.current = extractName(navigation);
55
- console.log("State change - ", currentRoute.current);
56
-
57
- if (Platform.OS === "ios" && currentRoute.current) {
58
- TLTRN.logScreenViewPageName(currentRoute.current);
59
- } else if (Platform.OS === "android") {
60
- TLTRN.logScreenViewPageName(currentRoute.current);
61
- TLTRN.logScreenLayout(currentRoute.current);
62
- }
63
- });
64
-
65
- return unsubscribe;
66
- }, [navigation]);
67
-
68
- const onStartShouldSetResponderCapture = useCallback(
69
- (event: any) => {
70
- currentRoute.current = extractName(navigation);
71
- if (currentRoute.current) {
72
- TLTRN.logScreenViewPageName(currentRoute.current);
73
- }
74
- TLTRN.logClickEvent(event);
75
- return false;
76
- },
77
- [navigation]
78
- );
79
-
80
- const onLayout = useCallback(
81
- (event: LayoutChangeEvent) => {
82
- if (initial.current) {
83
- return false;
84
- }
85
- initial.current = true;
86
-
87
- console.log("event - ", event.nativeEvent);
88
-
89
- currentRoute.current = navigation.current?.getCurrentRoute()?.name;
90
- if (Platform.OS === "ios" && currentRoute.current) {
91
- TLTRN.logScreenViewPageName(currentRoute.current);
92
- } else if (Platform.OS === "android") {
93
- TLTRN.logScreenLayout(currentRoute.current);
94
- }
95
- return true;
96
- },
97
- [navigation]
98
- );
99
-
100
- return (
101
- <View
102
- style={styles.connect_main}
103
- onLayout={onLayout}
104
- onStartShouldSetResponderCapture={onStartShouldSetResponderCapture}
105
- >
106
- {children}
107
- </View>
108
- );
109
- });
21
+ const Connect: React.FC<ConnectProps> = ({ children, captureKeyboardEvents, captureDialogEvents = false }) => {
22
+ const navigation = (children as any).ref; // Type assertion for children with ref
23
+ const currentRoute = useRef<string | undefined>(undefined);
24
+ const initial = useRef<boolean>(false);
25
+
26
+ useEffect(() => {
27
+ TLTRN.interceptKeyboardEvents(captureKeyboardEvents);
28
+ }, [captureKeyboardEvents]);
29
+
30
+ useEffect(() => {
31
+ TLTRN.interceptDialogEvents(captureDialogEvents);
32
+ }, [captureDialogEvents]);
33
+
34
+ useEffect(() => {
35
+ if (
36
+ !navigation ||
37
+ typeof navigation.current.addListener !== "function" ||
38
+ typeof navigation.current.getCurrentRoute !== "function"
39
+ ) {
40
+ console.warn(
41
+ "Connect: The Connect component's first child must be a NavigationContainer with a ref."
42
+ );
43
+ return;
44
+ }
45
+
46
+ // Listen for the 'state' event to track navigation state changes
47
+ const unsubscribeState = navigation.current.addListener("state", () => {
48
+ currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
49
+ console.log("State change - ", currentRoute.current);
50
+
51
+ if (Platform.OS === "ios" && currentRoute && currentRoute.current) {
52
+ TLTRN.logScreenViewPageName(currentRoute.current);
53
+ } else if (Platform.OS === "android") {
54
+ TLTRN.logScreenViewPageName(currentRoute.current);
55
+ TLTRN.logScreenLayout(currentRoute.current);
56
+ }
57
+ });
58
+
59
+ // Cleanup listeners when the component unmounts or dependencies change
60
+ return () => {
61
+ unsubscribeState();
62
+ };
63
+ }, [navigation]);
64
+
65
+ const onStartShouldSetResponderCapture = useCallback((event: any) => {
66
+ currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
67
+ if (currentRoute && currentRoute.current) {
68
+ TLTRN.logScreenViewPageName(currentRoute.current);
69
+ }
70
+ TLTRN.logClickEvent(event);
71
+ return false; // Must be false; true means this component becomes the touch responder and events don't bubble
72
+ }, []);
73
+
74
+ const onLayout = useCallback((event: LayoutChangeEvent) => {
75
+ if (initial.current) {
76
+ return false;
77
+ }
78
+ initial.current = true;
79
+
80
+ console.log("event - ", event.nativeEvent);
81
+
82
+ currentRoute.current = navigation.current.getCurrentRoute()?.name;
83
+ if (Platform.OS === "ios" && currentRoute && currentRoute.current) {
84
+ TLTRN.logScreenViewPageName(currentRoute.current);
85
+ } else if (Platform.OS === "android") {
86
+ TLTRN.logScreenLayout(currentRoute.current);
87
+ }
88
+ return true
89
+ }, [navigation]);
90
+
91
+ return (
92
+ <View
93
+ style={styles.connect_main}
94
+ onLayout={onLayout}
95
+ onStartShouldSetResponderCapture={onStartShouldSetResponderCapture}
96
+ >
97
+ {children}
98
+ </View>
99
+ );
100
+ };
110
101
 
111
102
  function extractName(navigation: any): string {
112
- const routeParams = navigation.current?.getCurrentRoute()?.params;
113
- if (routeParams) {
114
- const { name } = routeParams;
115
- return name || "";
116
- }
117
- return navigation.current?.getCurrentRoute()?.name || "";
103
+ const routeParams = navigation.current.getCurrentRoute()?.params;
104
+ if (routeParams) {
105
+ const { name } = routeParams;
106
+ return name ? name : navigation.current?.getCurrentRoute()?.name || "";
107
+ }
108
+ return "";
118
109
  }
119
110
 
120
111
  export default Connect;
121
112
 
122
113
  const styles = StyleSheet.create({
123
- connect_main: {
124
- flex: 1,
125
- },
114
+ connect_main: {
115
+ flex: 1,
116
+ },
126
117
  });
@@ -0,0 +1,252 @@
1
+ # Dialog Event Tracking
2
+
3
+ This document describes the dialog event tracking functionality added to the Acoustic Connect React Native SDK.
4
+
5
+ ## Overview
6
+
7
+ The dialog tracking system provides automatic and manual tracking of dialog popup events and user interactions. It supports:
8
+
9
+ - **Automatic tracking** of React Native's `Alert.alert()` calls
10
+ - **Manual tracking** of custom dialog components
11
+ - **Button click tracking** for both automatic and custom dialogs
12
+ - **Event logging** to the Acoustic Connect backend
13
+
14
+ ## Features
15
+
16
+ ### 1. Automatic Alert.alert Interception
17
+
18
+ The system automatically intercepts and tracks all `Alert.alert()` calls without requiring any code changes:
19
+
20
+ ```typescript
21
+ // This will be automatically tracked
22
+ Alert.alert(
23
+ 'Confirmation',
24
+ 'Are you sure?',
25
+ [
26
+ { text: 'Cancel', style: 'cancel' },
27
+ { text: 'OK', onPress: () => console.log('OK pressed') }
28
+ ]
29
+ );
30
+ ```
31
+
32
+ ### 2. Manual Custom Dialog Tracking
33
+
34
+ For custom dialog components, you can manually track events:
35
+
36
+ ```typescript
37
+ import { useDialogTracking } from 'react-native-acoustic-connect-beta';
38
+
39
+ const MyComponent = () => {
40
+ const { generateDialogId, trackDialogShow, trackDialogDismiss } = useDialogTracking();
41
+
42
+ const showDialog = () => {
43
+ const dialogId = generateDialogId();
44
+ trackDialogShow(dialogId, 'My Custom Dialog', [
45
+ { text: 'Cancel', style: 'cancel' },
46
+ { text: 'OK' }
47
+ ]);
48
+ // Show your custom dialog
49
+ };
50
+
51
+ const hideDialog = () => {
52
+ const dialogId = generateDialogId(); // Store this in your component state
53
+ trackDialogDismiss(dialogId, 'user_dismiss');
54
+ // Hide your custom dialog
55
+ };
56
+ };
57
+ ```
58
+
59
+ ### 3. Button Click Tracking
60
+
61
+ Track button clicks in custom dialogs:
62
+
63
+ ```typescript
64
+ const { createTrackedButton } = useDialogTracking();
65
+
66
+ const showDialogWithTrackedButtons = () => {
67
+ const dialogId = generateDialogId();
68
+ const originalButtons = [
69
+ { text: 'No', style: 'cancel' },
70
+ { text: 'Yes', onPress: () => console.log('Yes pressed') }
71
+ ];
72
+
73
+ // Create tracked buttons
74
+ const trackedButtons = originalButtons.map((button, index) =>
75
+ createTrackedButton(dialogId, button, index)
76
+ );
77
+
78
+ trackDialogShow(dialogId, 'Confirmation', trackedButtons);
79
+ };
80
+ ```
81
+
82
+ ### 4. HOC-Based Automatic Tracking
83
+
84
+ For the easiest integration, use the HOC (Higher-Order Component) approach:
85
+
86
+ ```typescript
87
+ import { withAcousticAutoDialog } from 'react-native-acoustic-connect-beta';
88
+ import { Dialog } from 'react-native-paper';
89
+
90
+ // Create tracked version of your dialog component
91
+ const TrackedDialog = withAcousticAutoDialog(Dialog);
92
+
93
+ // Use normally - all events automatically tracked!
94
+ <TrackedDialog
95
+ visible={dialogVisible}
96
+ onDismiss={hideDialog}
97
+ title="My Dialog"
98
+ >
99
+ <Dialog.Content>
100
+ <Text>Dialog content</Text>
101
+ </Dialog.Content>
102
+ <Dialog.Actions>
103
+ <Button onPress={hideDialog}>Cancel</Button>
104
+ <Button onPress={confirmAction}>Confirm</Button>
105
+ </Dialog.Actions>
106
+ </TrackedDialog>
107
+ ```
108
+
109
+ The HOC automatically tracks:
110
+ - Dialog show events
111
+ - Dialog dismiss events
112
+ - Button click events within the dialog
113
+ - Recursively scans dialog children for buttons
114
+
115
+ ## Setup
116
+
117
+ ### 1. Enable Dialog Tracking in Connect Component
118
+
119
+ ```typescript
120
+ import { Connect } from 'react-native-acoustic-connect-beta';
121
+
122
+ <Connect
123
+ captureKeyboardEvents={true}
124
+ captureDialogEvents={true} // Enable dialog tracking
125
+ >
126
+ <NavigationContainer ref={navigationRef}>
127
+ {/* Your app content */}
128
+ </NavigationContainer>
129
+ </Connect>
130
+ ```
131
+
132
+ ### 2. Use the useDialogTracking Hook
133
+
134
+ ```typescript
135
+ import { useDialogTracking } from 'react-native-acoustic-connect-beta';
136
+
137
+ const MyComponent = () => {
138
+ const dialogTracking = useDialogTracking();
139
+
140
+ // Use dialogTracking methods...
141
+ };
142
+ ```
143
+
144
+ ## API Reference
145
+
146
+ ### Connect Component Props
147
+
148
+ | Prop | Type | Default | Description |
149
+ |------|------|---------|-------------|
150
+ | `captureDialogEvents` | `boolean` | `false` | Enable automatic dialog event tracking |
151
+
152
+ ### useDialogTracking Hook
153
+
154
+ Returns an object with the following methods:
155
+
156
+ #### `generateDialogId(): string`
157
+ Generates a unique dialog identifier.
158
+
159
+ #### `trackDialogShow(dialogId: string, title: string, buttons?: AlertButton[]): void`
160
+ Tracks a dialog show event.
161
+
162
+ #### `trackDialogDismiss(dialogId: string, reason: string): void`
163
+ Tracks a dialog dismiss event.
164
+
165
+ #### `trackDialogButtonClick(dialogId: string, buttonText: string, buttonIndex: number): void`
166
+ Tracks a dialog button click event.
167
+
168
+ #### `trackDialogCustomEvent(dialogId: string, eventName: string, values: Record<string, string \| number \| boolean>): void`
169
+ Tracks a custom dialog event.
170
+
171
+ #### `createTrackedButton(dialogId: string, button: AlertButton, buttonIndex: number): AlertButton`
172
+ Creates a button with automatic click tracking.
173
+
174
+ #### `cleanup(): void`
175
+ Cleans up dialog tracking state.
176
+
177
+ ### DialogListener Class
178
+
179
+ For advanced usage, you can directly use the DialogListener class:
180
+
181
+ ```typescript
182
+ import { DialogListener } from 'react-native-acoustic-connect-beta';
183
+
184
+ const dialogListener = DialogListener.getInstance();
185
+ dialogListener.startIntercepting();
186
+ dialogListener.addEventListener((event) => {
187
+ console.log('Dialog event:', event);
188
+ });
189
+ ```
190
+
191
+ ## Event Types
192
+
193
+ ### DialogEvent
194
+ ```typescript
195
+ interface DialogEvent {
196
+ dialogId: string;
197
+ dialogTitle: string;
198
+ dialogType: 'alert' | 'custom' | 'modal';
199
+ timestamp: number;
200
+ buttons?: AlertButton[];
201
+ }
202
+ ```
203
+
204
+ ### DialogButtonClickEvent
205
+ ```typescript
206
+ interface DialogButtonClickEvent {
207
+ dialogId: string;
208
+ buttonText: string;
209
+ buttonIndex: number;
210
+ timestamp: number;
211
+ }
212
+ ```
213
+
214
+ ## Native Interface Methods
215
+
216
+ The following methods are added to the AcousticConnectRN interface:
217
+
218
+ - `logDialogShowEvent(dialogId: string, dialogTitle: string, dialogType: string): boolean`
219
+ - `logDialogDismissEvent(dialogId: string, dismissReason: string): boolean`
220
+ - `logDialogButtonClickEvent(dialogId: string, buttonText: string, buttonIndex: number): boolean`
221
+ - `logDialogCustomEvent(dialogId: string, eventName: string, values: Record<string, string \| number \| boolean>): boolean`
222
+
223
+ ## Best Practices
224
+
225
+ 1. **Store Dialog IDs**: When manually tracking custom dialogs, store the dialog ID in your component state to properly track dismiss events.
226
+
227
+ 2. **Use Consistent Naming**: Use descriptive dialog titles and button text for better analytics.
228
+
229
+ 3. **Handle Errors**: Wrap dialog tracking calls in try-catch blocks to prevent app crashes.
230
+
231
+ 4. **Clean Up**: Call the cleanup method when components unmount to prevent memory leaks.
232
+
233
+ ## Example Implementation
234
+
235
+ See `src/examples/DialogTrackingExample.tsx` for a complete example showing all features.
236
+
237
+ ## Troubleshooting
238
+
239
+ ### Dialog events not being tracked
240
+ 1. Ensure `captureDialogEvents={true}` is set on the Connect component
241
+ 2. Check that the DialogListener is properly initialized
242
+ 3. Verify that the native AcousticConnectRN interface is available
243
+
244
+ ### Custom dialog tracking not working
245
+ 1. Make sure you're calling `trackDialogShow` before showing the dialog
246
+ 2. Store the dialog ID and use it consistently for dismiss events
247
+ 3. Use `createTrackedButton` for automatic button click tracking
248
+
249
+ ### Performance considerations
250
+ - Dialog tracking is lightweight and shouldn't impact app performance
251
+ - The system uses efficient event delegation and cleanup
252
+ - Dialog IDs are generated using a simple algorithm to avoid external dependencies