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.
- package/Examples/SampleUI/.detoxrc.js +83 -0
- package/Examples/SampleUI/ConnectConfig.json +2 -2
- package/Examples/SampleUI/android/app/build.gradle +3 -0
- package/Examples/SampleUI/android/app/src/main/java/com/sampleui/MainActivity.kt +0 -35
- package/Examples/SampleUI/android/settings.gradle +1 -1
- package/Examples/SampleUI/package.json +8 -6
- package/Examples/SampleUI/scripts/integration-test-android.sh +292 -0
- package/Examples/SampleUI/src/Examples/DialogExample.tsx +88 -2
- package/Examples/SampleUI/src/Examples/Dialogs/DialogTrackingTest.tsx +307 -0
- package/Examples/SampleUI/src/Examples/Dialogs/index.tsx +37 -0
- package/Examples/SampleUI/src/index.native.tsx +5 -5
- package/android/build.gradle +2 -2
- package/android/src/main/assets/ConnectAdvancedConfig.json +1 -1
- package/android/src/main/assets/TealeafAdvancedConfig.json +1 -1
- package/android/src/main/java/com/acousticconnectrn/HybridAcousticConnectRN.kt +787 -490
- package/ios/HybridAcousticConnectRN.swift +79 -4
- package/lib/commonjs/TLTRN.js +69 -0
- package/lib/commonjs/TLTRN.js.map +1 -1
- package/lib/commonjs/components/Connect.js +31 -29
- package/lib/commonjs/components/Connect.js.map +1 -1
- package/lib/commonjs/docs/DialogTracking.md +252 -0
- package/lib/commonjs/docs/NativeImplementation.md +176 -0
- package/lib/commonjs/examples/DialogTrackingExample.js +175 -0
- package/lib/commonjs/examples/DialogTrackingExample.js.map +1 -0
- package/lib/commonjs/examples/HOCDialogExample.js +296 -0
- package/lib/commonjs/examples/HOCDialogExample.js.map +1 -0
- package/lib/commonjs/index.js +28 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/DialogDebugger.js +216 -0
- package/lib/commonjs/utils/DialogDebugger.js.map +1 -0
- package/lib/commonjs/utils/DialogListener.js +203 -0
- package/lib/commonjs/utils/DialogListener.js.map +1 -0
- package/lib/commonjs/utils/useDialogTracking.js +107 -0
- package/lib/commonjs/utils/useDialogTracking.js.map +1 -0
- package/lib/commonjs/utils/withAcousticAutoDialog.js +282 -0
- package/lib/commonjs/utils/withAcousticAutoDialog.js.map +1 -0
- package/lib/module/TLTRN.js +69 -0
- package/lib/module/TLTRN.js.map +1 -1
- package/lib/module/components/Connect.js +32 -31
- package/lib/module/components/Connect.js.map +1 -1
- package/lib/module/docs/DialogTracking.md +252 -0
- package/lib/module/docs/NativeImplementation.md +176 -0
- package/lib/module/examples/DialogTrackingExample.js +172 -0
- package/lib/module/examples/DialogTrackingExample.js.map +1 -0
- package/lib/module/examples/HOCDialogExample.js +292 -0
- package/lib/module/examples/HOCDialogExample.js.map +1 -0
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/DialogDebugger.js +211 -0
- package/lib/module/utils/DialogDebugger.js.map +1 -0
- package/lib/module/utils/DialogListener.js +199 -0
- package/lib/module/utils/DialogListener.js.map +1 -0
- package/lib/module/utils/useDialogTracking.js +102 -0
- package/lib/module/utils/useDialogTracking.js.map +1 -0
- package/lib/module/utils/withAcousticAutoDialog.js +275 -0
- package/lib/module/utils/withAcousticAutoDialog.js.map +1 -0
- package/lib/typescript/src/TLTRN.d.ts +7 -0
- package/lib/typescript/src/TLTRN.d.ts.map +1 -1
- package/lib/typescript/src/components/Connect.d.ts +2 -2
- package/lib/typescript/src/components/Connect.d.ts.map +1 -1
- package/lib/typescript/src/examples/DialogTrackingExample.d.ts +17 -0
- package/lib/typescript/src/examples/DialogTrackingExample.d.ts.map +1 -0
- package/lib/typescript/src/examples/HOCDialogExample.d.ts +21 -0
- package/lib/typescript/src/examples/HOCDialogExample.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts +4 -0
- package/lib/typescript/src/specs/react-native-acoustic-connect.nitro.d.ts.map +1 -1
- package/lib/typescript/src/utils/DialogDebugger.d.ts +58 -0
- package/lib/typescript/src/utils/DialogDebugger.d.ts.map +1 -0
- package/lib/typescript/src/utils/DialogListener.d.ts +85 -0
- package/lib/typescript/src/utils/DialogListener.d.ts.map +1 -0
- package/lib/typescript/src/utils/useDialogTracking.d.ts +25 -0
- package/lib/typescript/src/utils/useDialogTracking.d.ts.map +1 -0
- package/lib/typescript/src/utils/withAcousticAutoDialog.d.ts +37 -0
- package/lib/typescript/src/utils/withAcousticAutoDialog.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.cpp +26 -0
- package/nitrogen/generated/android/c++/JHybridAcousticConnectRNSpec.hpp +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/acousticconnectrn/HybridAcousticConnectRNSpec.kt +16 -0
- package/nitrogen/generated/ios/c++/HybridAcousticConnectRNSpecSwift.hpp +32 -0
- package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridAcousticConnectRNSpec_cxx.swift +71 -0
- package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridAcousticConnectRNSpec.hpp +4 -0
- package/package.json +1 -1
- package/scripts/ConnectConfig.json +1 -1
- package/src/TLTRN.ts +75 -0
- package/src/components/Connect.tsx +92 -101
- package/src/docs/DialogTracking.md +252 -0
- package/src/docs/NativeImplementation.md +176 -0
- package/src/examples/DialogTrackingExample.tsx +163 -0
- package/src/examples/HOCDialogExample.tsx +253 -0
- package/src/index.ts +5 -1
- package/src/specs/react-native-acoustic-connect.nitro.ts +5 -0
- package/src/utils/DialogDebugger.ts +224 -0
- package/src/utils/DialogListener.ts +238 -0
- package/src/utils/useDialogTracking.ts +102 -0
- package/src/utils/withAcousticAutoDialog.tsx +312 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/********************************************************************************************
|
|
2
|
+
* Copyright (C) 2025 Acoustic, L.P. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* NOTICE: This file contains material that is confidential and proprietary to
|
|
5
|
+
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
|
|
6
|
+
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
|
|
7
|
+
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
|
+
* prohibited.
|
|
9
|
+
********************************************************************************************/
|
|
10
|
+
|
|
11
|
+
import { Alert } from 'react-native';
|
|
12
|
+
import DialogListener from './DialogListener';
|
|
13
|
+
import TLTRN from '../TLTRN';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Debug utility for dialog event tracking
|
|
17
|
+
* Helps identify issues with dialog event interception and logging
|
|
18
|
+
*/
|
|
19
|
+
export class DialogDebugger {
|
|
20
|
+
private static instance: DialogDebugger;
|
|
21
|
+
private isEnabled: boolean = false;
|
|
22
|
+
private originalAlert: typeof Alert.alert;
|
|
23
|
+
|
|
24
|
+
private constructor() {
|
|
25
|
+
this.originalAlert = Alert.alert;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static getInstance(): DialogDebugger {
|
|
29
|
+
if (!DialogDebugger.instance) {
|
|
30
|
+
DialogDebugger.instance = new DialogDebugger();
|
|
31
|
+
}
|
|
32
|
+
return DialogDebugger.instance;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Enable debug mode
|
|
37
|
+
*/
|
|
38
|
+
enable(): void {
|
|
39
|
+
this.isEnabled = true;
|
|
40
|
+
console.log('🔍 DialogDebugger: Debug mode enabled');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Disable debug mode
|
|
45
|
+
*/
|
|
46
|
+
disable(): void {
|
|
47
|
+
this.isEnabled = false;
|
|
48
|
+
console.log('🔍 DialogDebugger: Debug mode disabled');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Test the complete dialog event flow
|
|
53
|
+
*/
|
|
54
|
+
testDialogEventFlow(): void {
|
|
55
|
+
console.log('🔍 DialogDebugger: Testing dialog event flow...');
|
|
56
|
+
|
|
57
|
+
// Test 1: Check if DialogListener is working
|
|
58
|
+
this.testDialogListener();
|
|
59
|
+
|
|
60
|
+
// Test 2: Check if TLTRN methods are accessible
|
|
61
|
+
this.testTLTRNMethods();
|
|
62
|
+
|
|
63
|
+
// Test 3: Check if Alert.alert override is working
|
|
64
|
+
this.testAlertOverride();
|
|
65
|
+
|
|
66
|
+
// Test 4: Test native method calls
|
|
67
|
+
this.testNativeMethods();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Test DialogListener functionality
|
|
72
|
+
*/
|
|
73
|
+
private testDialogListener(): void {
|
|
74
|
+
console.log('🔍 DialogDebugger: Testing DialogListener...');
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const dialogListener = DialogListener.getInstance();
|
|
78
|
+
console.log('✅ DialogListener.getInstance() - SUCCESS');
|
|
79
|
+
|
|
80
|
+
// Test event listener
|
|
81
|
+
const unsubscribe = dialogListener.addEventListener((event) => {
|
|
82
|
+
console.log('🔍 DialogDebugger: DialogListener event received:', event);
|
|
83
|
+
});
|
|
84
|
+
console.log('✅ DialogListener.addEventListener() - SUCCESS');
|
|
85
|
+
|
|
86
|
+
// Test manual tracking
|
|
87
|
+
dialogListener.trackCustomDialogShow('test-dialog-id', 'Test Dialog', []);
|
|
88
|
+
console.log('✅ DialogListener.trackCustomDialogShow() - SUCCESS');
|
|
89
|
+
|
|
90
|
+
unsubscribe();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('❌ DialogDebugger: DialogListener test failed:', error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Test TLTRN methods
|
|
98
|
+
*/
|
|
99
|
+
private testTLTRNMethods(): void {
|
|
100
|
+
console.log('🔍 DialogDebugger: Testing TLTRN methods...');
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
// Test if TLTRN methods exist
|
|
104
|
+
if (typeof TLTRN.logDialogShowEvent === 'function') {
|
|
105
|
+
console.log('✅ TLTRN.logDialogShowEvent - EXISTS');
|
|
106
|
+
} else {
|
|
107
|
+
console.error('❌ TLTRN.logDialogShowEvent - NOT FOUND');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (typeof TLTRN.interceptDialogEvents === 'function') {
|
|
111
|
+
console.log('✅ TLTRN.interceptDialogEvents - EXISTS');
|
|
112
|
+
} else {
|
|
113
|
+
console.error('❌ TLTRN.interceptDialogEvents - NOT FOUND');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Test method call
|
|
117
|
+
TLTRN.logDialogShowEvent('test-dialog-id', 'Test Dialog', 'test');
|
|
118
|
+
console.log('✅ TLTRN.logDialogShowEvent() - CALLED');
|
|
119
|
+
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('❌ DialogDebugger: TLTRN test failed:', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Test Alert.alert override
|
|
127
|
+
*/
|
|
128
|
+
private testAlertOverride(): void {
|
|
129
|
+
console.log('🔍 DialogDebugger: Testing Alert.alert override...');
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
// Check if Alert.alert is overridden
|
|
133
|
+
if (Alert.alert !== this.originalAlert) {
|
|
134
|
+
console.log('✅ Alert.alert is overridden');
|
|
135
|
+
} else {
|
|
136
|
+
console.error('❌ Alert.alert is NOT overridden');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Test Alert.alert call
|
|
140
|
+
Alert.alert('Debug Test', 'This is a test alert', [
|
|
141
|
+
{ text: 'OK', onPress: () => console.log('🔍 DialogDebugger: Alert OK pressed') }
|
|
142
|
+
]);
|
|
143
|
+
console.log('✅ Alert.alert() - CALLED');
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('❌ DialogDebugger: Alert.alert test failed:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Test native method calls
|
|
152
|
+
*/
|
|
153
|
+
private testNativeMethods(): void {
|
|
154
|
+
console.log('🔍 DialogDebugger: Testing native method calls...');
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
// Import AcousticConnectRN to test native calls
|
|
158
|
+
const AcousticConnectRN = require('../index').default;
|
|
159
|
+
|
|
160
|
+
if (AcousticConnectRN && typeof AcousticConnectRN.logDialogShowEvent === 'function') {
|
|
161
|
+
console.log('✅ AcousticConnectRN.logDialogShowEvent - EXISTS');
|
|
162
|
+
|
|
163
|
+
// Test native call
|
|
164
|
+
const result = AcousticConnectRN.logDialogShowEvent('test-dialog-id', 'Test Dialog', 'test');
|
|
165
|
+
console.log('✅ AcousticConnectRN.logDialogShowEvent() - CALLED, result:', result);
|
|
166
|
+
} else {
|
|
167
|
+
console.error('❌ AcousticConnectRN.logDialogShowEvent - NOT FOUND');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error('❌ DialogDebugger: Native method test failed:', error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Check if dialog tracking is properly enabled
|
|
177
|
+
*/
|
|
178
|
+
checkDialogTrackingStatus(): void {
|
|
179
|
+
console.log('🔍 DialogDebugger: Checking dialog tracking status...');
|
|
180
|
+
|
|
181
|
+
// Check DialogListener status
|
|
182
|
+
const dialogListener = DialogListener.getInstance();
|
|
183
|
+
console.log('DialogListener status:', {
|
|
184
|
+
isIntercepting: (dialogListener as any).isIntercepting,
|
|
185
|
+
eventCallbacksCount: (dialogListener as any).eventCallbacks?.length || 0
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Check if Alert.alert is overridden
|
|
189
|
+
console.log('Alert.alert override status:', {
|
|
190
|
+
isOverridden: Alert.alert !== this.originalAlert,
|
|
191
|
+
originalAlert: this.originalAlert,
|
|
192
|
+
currentAlert: Alert.alert
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Check TLTRN methods
|
|
196
|
+
console.log('TLTRN methods status:', {
|
|
197
|
+
logDialogShowEvent: typeof TLTRN.logDialogShowEvent,
|
|
198
|
+
interceptDialogEvents: typeof TLTRN.interceptDialogEvents
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Force enable dialog tracking for testing
|
|
204
|
+
*/
|
|
205
|
+
forceEnableDialogTracking(): void {
|
|
206
|
+
console.log('🔍 DialogDebugger: Force enabling dialog tracking...');
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
// Force enable DialogListener
|
|
210
|
+
const dialogListener = DialogListener.getInstance();
|
|
211
|
+
(dialogListener as any).isIntercepting = true;
|
|
212
|
+
console.log('✅ DialogListener interception forced enabled');
|
|
213
|
+
|
|
214
|
+
// Force enable TLTRN dialog events
|
|
215
|
+
TLTRN.interceptDialogEvents(true);
|
|
216
|
+
console.log('✅ TLTRN dialog events forced enabled');
|
|
217
|
+
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.error('❌ DialogDebugger: Force enable failed:', error);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export default DialogDebugger;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/********************************************************************************************
|
|
2
|
+
* Copyright (C) 2025 Acoustic, L.P. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* NOTICE: This file contains material that is confidential and proprietary to
|
|
5
|
+
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
|
|
6
|
+
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
|
|
7
|
+
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
|
+
* prohibited.
|
|
9
|
+
********************************************************************************************/
|
|
10
|
+
|
|
11
|
+
import { Alert, Platform } from 'react-native';
|
|
12
|
+
import type { AlertButton, AlertOptions } from 'react-native';
|
|
13
|
+
|
|
14
|
+
export interface DialogEvent {
|
|
15
|
+
dialogId: string;
|
|
16
|
+
dialogTitle: string;
|
|
17
|
+
dialogType: 'alert' | 'custom' | 'modal';
|
|
18
|
+
timestamp: number;
|
|
19
|
+
buttons?: AlertButton[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DialogButtonClickEvent {
|
|
23
|
+
dialogId: string;
|
|
24
|
+
buttonText: string;
|
|
25
|
+
buttonIndex: number;
|
|
26
|
+
timestamp: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface DialogDismissEvent {
|
|
30
|
+
dialogId: string;
|
|
31
|
+
dialogTitle: string;
|
|
32
|
+
dialogType: 'alert' | 'custom' | 'modal';
|
|
33
|
+
dismissReason: string;
|
|
34
|
+
timestamp: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Simple ID generator
|
|
38
|
+
function generateId(): string {
|
|
39
|
+
return Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class DialogListener {
|
|
43
|
+
private static instance: DialogListener;
|
|
44
|
+
private activeDialogs: Map<string, DialogEvent> = new Map();
|
|
45
|
+
private originalAlert: typeof Alert.alert;
|
|
46
|
+
private isIntercepting: boolean = false;
|
|
47
|
+
private eventCallbacks: Array<(event: DialogEvent | DialogButtonClickEvent | DialogDismissEvent) => void> = [];
|
|
48
|
+
|
|
49
|
+
private constructor() {
|
|
50
|
+
this.originalAlert = Alert.alert;
|
|
51
|
+
this.interceptAlertAPI();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static getInstance(): DialogListener {
|
|
55
|
+
if (!DialogListener.instance) {
|
|
56
|
+
DialogListener.instance = new DialogListener();
|
|
57
|
+
}
|
|
58
|
+
return DialogListener.instance;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Start intercepting dialog events
|
|
63
|
+
*/
|
|
64
|
+
startIntercepting(): void {
|
|
65
|
+
if (this.isIntercepting) return;
|
|
66
|
+
this.isIntercepting = true;
|
|
67
|
+
console.log('DialogListener: Started intercepting dialog events');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Stop intercepting dialog events
|
|
72
|
+
*/
|
|
73
|
+
stopIntercepting(): void {
|
|
74
|
+
if (!this.isIntercepting) return;
|
|
75
|
+
this.isIntercepting = false;
|
|
76
|
+
console.log('DialogListener: Stopped intercepting dialog events');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Add event callback for dialog events
|
|
81
|
+
*/
|
|
82
|
+
addEventListener(callback: (event: DialogEvent | DialogButtonClickEvent | DialogDismissEvent) => void): () => void {
|
|
83
|
+
this.eventCallbacks.push(callback);
|
|
84
|
+
return () => {
|
|
85
|
+
const index = this.eventCallbacks.indexOf(callback);
|
|
86
|
+
if (index > -1) {
|
|
87
|
+
this.eventCallbacks.splice(index, 1);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Intercept React Native's Alert.alert API
|
|
94
|
+
*/
|
|
95
|
+
private interceptAlertAPI(): void {
|
|
96
|
+
const self = this;
|
|
97
|
+
Alert.alert = function(
|
|
98
|
+
title: string,
|
|
99
|
+
message?: string,
|
|
100
|
+
buttons?: AlertButton[],
|
|
101
|
+
options?: AlertOptions
|
|
102
|
+
): void {
|
|
103
|
+
if (self.isIntercepting) {
|
|
104
|
+
const dialogId = generateId();
|
|
105
|
+
const dialogEvent: DialogEvent = {
|
|
106
|
+
dialogId,
|
|
107
|
+
dialogTitle: title,
|
|
108
|
+
dialogType: 'alert',
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
buttons: buttons || []
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
self.activeDialogs.set(dialogId, dialogEvent);
|
|
114
|
+
self.emitEvent(dialogEvent);
|
|
115
|
+
|
|
116
|
+
// Create wrapped buttons that log events
|
|
117
|
+
const wrappedButtons = buttons?.map((button, index) => ({
|
|
118
|
+
...button,
|
|
119
|
+
onPress: () => {
|
|
120
|
+
const buttonClickEvent: DialogButtonClickEvent = {
|
|
121
|
+
dialogId,
|
|
122
|
+
buttonText: button.text || '',
|
|
123
|
+
buttonIndex: index,
|
|
124
|
+
timestamp: Date.now()
|
|
125
|
+
};
|
|
126
|
+
self.emitEvent(buttonClickEvent);
|
|
127
|
+
self.activeDialogs.delete(dialogId);
|
|
128
|
+
|
|
129
|
+
// Call original onPress if it exists
|
|
130
|
+
if (button.onPress) {
|
|
131
|
+
button.onPress();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}));
|
|
135
|
+
|
|
136
|
+
// Call original Alert.alert with wrapped buttons
|
|
137
|
+
self.originalAlert.call(Alert, title, message, wrappedButtons, options);
|
|
138
|
+
} else {
|
|
139
|
+
// Call original Alert.alert without interception
|
|
140
|
+
self.originalAlert.call(Alert, title, message, buttons, options);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Manually track custom dialog show event
|
|
147
|
+
*/
|
|
148
|
+
trackCustomDialogShow(dialogId: string, title: string, buttons?: AlertButton[]): void {
|
|
149
|
+
if (!this.isIntercepting) return;
|
|
150
|
+
|
|
151
|
+
const dialogEvent: DialogEvent = {
|
|
152
|
+
dialogId,
|
|
153
|
+
dialogTitle: title,
|
|
154
|
+
dialogType: 'custom',
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
buttons: buttons || []
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
this.activeDialogs.set(dialogId, dialogEvent);
|
|
160
|
+
this.emitEvent(dialogEvent);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Manually track custom dialog dismiss event
|
|
165
|
+
*/
|
|
166
|
+
trackCustomDialogDismiss(dialogId: string, reason: string = 'manual'): void {
|
|
167
|
+
if (!this.isIntercepting) return;
|
|
168
|
+
|
|
169
|
+
const dialogEvent = this.activeDialogs.get(dialogId);
|
|
170
|
+
if (dialogEvent) {
|
|
171
|
+
this.activeDialogs.delete(dialogId);
|
|
172
|
+
// Emit proper dismiss event
|
|
173
|
+
const dismissEvent: DialogDismissEvent = {
|
|
174
|
+
dialogId,
|
|
175
|
+
dialogTitle: dialogEvent.dialogTitle,
|
|
176
|
+
dialogType: dialogEvent.dialogType,
|
|
177
|
+
dismissReason: reason,
|
|
178
|
+
timestamp: Date.now()
|
|
179
|
+
};
|
|
180
|
+
this.emitEvent(dismissEvent);
|
|
181
|
+
|
|
182
|
+
// Log the dismiss reason for debugging
|
|
183
|
+
console.log(`Dialog ${dialogId} dismissed with reason: ${reason}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Manually track custom dialog button click event
|
|
189
|
+
*/
|
|
190
|
+
trackCustomDialogButtonClick(dialogId: string, buttonText: string, buttonIndex: number): void {
|
|
191
|
+
if (!this.isIntercepting) return;
|
|
192
|
+
|
|
193
|
+
const buttonClickEvent: DialogButtonClickEvent = {
|
|
194
|
+
dialogId,
|
|
195
|
+
buttonText,
|
|
196
|
+
buttonIndex,
|
|
197
|
+
timestamp: Date.now()
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
this.emitEvent(buttonClickEvent);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get currently active dialogs
|
|
205
|
+
*/
|
|
206
|
+
getActiveDialogs(): DialogEvent[] {
|
|
207
|
+
return Array.from(this.activeDialogs.values());
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Clear all active dialogs
|
|
212
|
+
*/
|
|
213
|
+
clearActiveDialogs(): void {
|
|
214
|
+
this.activeDialogs.clear();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Emit event to all registered callbacks
|
|
219
|
+
*/
|
|
220
|
+
private emitEvent(event: DialogEvent | DialogButtonClickEvent | DialogDismissEvent): void {
|
|
221
|
+
this.eventCallbacks.forEach(callback => {
|
|
222
|
+
try {
|
|
223
|
+
callback(event);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error('DialogListener: Error in event callback:', error);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Restore original Alert.alert API
|
|
232
|
+
*/
|
|
233
|
+
restoreOriginalAlert(): void {
|
|
234
|
+
Alert.alert = this.originalAlert;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export default DialogListener;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/********************************************************************************************
|
|
2
|
+
* Copyright (C) 2025 Acoustic, L.P. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* NOTICE: This file contains material that is confidential and proprietary to
|
|
5
|
+
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
|
|
6
|
+
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
|
|
7
|
+
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
|
+
* prohibited.
|
|
9
|
+
********************************************************************************************/
|
|
10
|
+
|
|
11
|
+
import { useCallback, useRef } from 'react';
|
|
12
|
+
import type { AlertButton } from 'react-native';
|
|
13
|
+
import DialogListener from './DialogListener';
|
|
14
|
+
import TLTRN from '../TLTRN';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* React hook for tracking custom dialog events
|
|
18
|
+
* Provides utilities to track dialog show, dismiss, and button click events
|
|
19
|
+
*/
|
|
20
|
+
export const useDialogTracking = () => {
|
|
21
|
+
const dialogIds = useRef<Set<string>>(new Set());
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generate a unique dialog ID
|
|
25
|
+
*/
|
|
26
|
+
const generateDialogId = useCallback((): string => {
|
|
27
|
+
const id = Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
|
|
28
|
+
dialogIds.current.add(id);
|
|
29
|
+
return id;
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Track a custom dialog show event
|
|
34
|
+
*/
|
|
35
|
+
const trackDialogShow = useCallback((dialogId: string, title: string, buttons?: AlertButton[]) => {
|
|
36
|
+
DialogListener.getInstance().trackCustomDialogShow(dialogId, title, buttons);
|
|
37
|
+
// Note: The actual native call is handled by the DialogListener event system
|
|
38
|
+
// No need to call TLTRN.logDialogShowEvent directly here
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Track a custom dialog dismiss event
|
|
43
|
+
*/
|
|
44
|
+
const trackDialogDismiss = useCallback((dialogId: string, reason: string = 'manual') => {
|
|
45
|
+
DialogListener.getInstance().trackCustomDialogDismiss(dialogId, reason);
|
|
46
|
+
// Note: The actual native call is handled by the DialogListener event system
|
|
47
|
+
// No need to call TLTRN.logDialogDismissEvent directly here
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Track a custom dialog button click event
|
|
52
|
+
*/
|
|
53
|
+
const trackDialogButtonClick = useCallback((dialogId: string, buttonText: string, buttonIndex: number) => {
|
|
54
|
+
DialogListener.getInstance().trackCustomDialogButtonClick(dialogId, buttonText, buttonIndex);
|
|
55
|
+
// Note: The actual native call is handled by the DialogListener event system
|
|
56
|
+
// No need to call TLTRN.logDialogButtonClickEvent directly here
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Track a custom dialog event
|
|
61
|
+
*/
|
|
62
|
+
const trackDialogCustomEvent = useCallback((dialogId: string, eventName: string, values: Record<string, string | number | boolean>) => {
|
|
63
|
+
TLTRN.logDialogCustomEvent(dialogId, eventName, values);
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a wrapped button with automatic tracking
|
|
68
|
+
*/
|
|
69
|
+
const createTrackedButton = useCallback((dialogId: string, button: AlertButton, buttonIndex: number): AlertButton => {
|
|
70
|
+
return {
|
|
71
|
+
...button,
|
|
72
|
+
onPress: () => {
|
|
73
|
+
// Track the button click
|
|
74
|
+
trackDialogButtonClick(dialogId, button.text || '', buttonIndex);
|
|
75
|
+
|
|
76
|
+
// Call the original onPress if it exists
|
|
77
|
+
if (button.onPress) {
|
|
78
|
+
button.onPress();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}, [trackDialogButtonClick]);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Clean up dialog tracking
|
|
86
|
+
*/
|
|
87
|
+
const cleanup = useCallback(() => {
|
|
88
|
+
dialogIds.current.clear();
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
generateDialogId,
|
|
93
|
+
trackDialogShow,
|
|
94
|
+
trackDialogDismiss,
|
|
95
|
+
trackDialogButtonClick,
|
|
96
|
+
trackDialogCustomEvent,
|
|
97
|
+
createTrackedButton,
|
|
98
|
+
cleanup
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default useDialogTracking;
|