react-native-acoustic-connect-beta 18.0.43 → 19.0.1
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/CHANGELOG.md +2 -0
- package/android/config.gradle +11 -1
- package/android/src/main/assets/ConnectBasicConfig.properties +1 -1
- package/lib/commonjs/components/Connect.js +53 -4
- package/lib/commonjs/components/Connect.js.map +1 -1
- package/lib/module/components/Connect.js +54 -5
- package/lib/module/components/Connect.js.map +1 -1
- package/lib/typescript/src/components/Connect.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/gradleParser.js +23 -5
- package/src/components/Connect.tsx +67 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
## [19.0.1](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/compare/18.0.44...19.0.1) (2026-06-29)
|
|
2
|
+
## [18.0.44](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/compare/18.0.43...18.0.44) (2026-06-26)
|
|
1
3
|
## [18.0.43](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/compare/18.0.42...18.0.43) (2026-06-26)
|
|
2
4
|
## [18.0.42](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/compare/18.0.41...18.0.42) (2026-06-25)
|
|
3
5
|
## [18.0.41](https://github.com/aipoweredmarketer/react-native-acoustic-connect-beta/compare/18.0.40...18.0.41) (2026-06-25)
|
package/android/config.gradle
CHANGED
|
@@ -355,7 +355,17 @@ def updateGradle(mp, json){
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
try {
|
|
358
|
-
|
|
358
|
+
// Resolve the SDK's android/ directory WITHOUT relying on a Gradle
|
|
359
|
+
// subproject named ':react-native-acoustic-connect-beta'. RN 0.82 + new
|
|
360
|
+
// architecture does not guarantee that autolinking registers third-party
|
|
361
|
+
// libraries as named Gradle subprojects, so `project(':...')` can throw
|
|
362
|
+
// "Project with path ... could not be found" during sync. Resolving the
|
|
363
|
+
// package via Node (the same mechanism the injected `apply from:` entry
|
|
364
|
+
// point uses) works regardless of how/whether the library was autolinked.
|
|
365
|
+
// See CA-144314.
|
|
366
|
+
def sdkPackageJson = ["node", "--print", "require.resolve('react-native-acoustic-connect-beta/package.json')"]
|
|
367
|
+
.execute(null, project.rootDir).text.trim()
|
|
368
|
+
def module_path = new File(sdkPackageJson).getParentFile().getAbsolutePath() + "/android"
|
|
359
369
|
|
|
360
370
|
println("**Acoustic Integration***********************************************************************")
|
|
361
371
|
println("Executing $module_path/config.gradle")
|
|
@@ -43,22 +43,71 @@ const Connect = ({
|
|
|
43
43
|
const shouldInjectRef = !navigationRef && !childProvidedRef && /*#__PURE__*/_react.default.isValidElement(child);
|
|
44
44
|
const currentRoute = (0, _react.useRef)(undefined);
|
|
45
45
|
const initial = (0, _react.useRef)(false);
|
|
46
|
+
// Tracks whether the resolved navigation ref has actually attached. See the
|
|
47
|
+
// readiness effect below for why a one-shot mount check is insufficient.
|
|
48
|
+
const [navReady, setNavReady] = (0, _react.useState)(false);
|
|
46
49
|
(0, _react.useEffect)(() => {
|
|
47
50
|
_TLTRN.default.interceptKeyboardEvents(captureKeyboardEvents);
|
|
48
51
|
}, [captureKeyboardEvents]);
|
|
49
52
|
(0, _react.useEffect)(() => {
|
|
50
53
|
_TLTRN.default.interceptDialogEvents(captureDialogEvents);
|
|
51
54
|
}, [captureDialogEvents]);
|
|
55
|
+
|
|
56
|
+
// Wait for the NavigationContainer ref to actually attach before declaring
|
|
57
|
+
// it usable. When <Connect> wraps the container indirectly — intermediate
|
|
58
|
+
// providers (AppProvider, SafeAreaProvider, …), or any provider that defers
|
|
59
|
+
// rendering its subtree (async init, splash gate) — the container mounts
|
|
60
|
+
// AFTER <Connect>'s effects run, so `navigation.current` is still null at
|
|
61
|
+
// first paint. A one-shot mount check would warn and permanently disable
|
|
62
|
+
// tracking, because the effect's only dependency is the stable ref object
|
|
63
|
+
// and `.current` mutations don't retrigger effects. So we poll until the
|
|
64
|
+
// ref is usable, then flip `navReady` to subscribe. The direct-child case
|
|
65
|
+
// resolves on the first synchronous check (no polling, no warning). If the
|
|
66
|
+
// ref never attaches within the grace window we warn once, as before.
|
|
67
|
+
// See CA-144314.
|
|
68
|
+
(0, _react.useEffect)(() => {
|
|
69
|
+
// Reset readiness whenever the resolved ref changes. Without this, a
|
|
70
|
+
// `navigationRef` prop swap leaves `navReady` stale-true, so the
|
|
71
|
+
// subscription effect below re-runs and attaches `addListener` to the
|
|
72
|
+
// old container (whose `.current` is still non-null mid-transition)
|
|
73
|
+
// before the new ref is validated. Resetting forces re-validation
|
|
74
|
+
// through `isUsable()` before tracking re-enables. See CA-144314.
|
|
75
|
+
setNavReady(false);
|
|
76
|
+
const isUsable = () => !!navigation && !!navigation.current && typeof navigation.current.addListener === "function" && typeof navigation.current.getCurrentRoute === "function";
|
|
77
|
+
if (isUsable()) {
|
|
78
|
+
setNavReady(true);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
let attempts = 0;
|
|
82
|
+
const POLL_INTERVAL_MS = 100;
|
|
83
|
+
const MAX_ATTEMPTS = 100; // ~10s grace for deferred/async provider init
|
|
84
|
+
let timer;
|
|
85
|
+
const poll = () => {
|
|
86
|
+
if (isUsable()) {
|
|
87
|
+
setNavReady(true);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (attempts++ >= MAX_ATTEMPTS) {
|
|
91
|
+
console.warn("Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " + "Pass `navigationRef` (from useNavigationContainerRef()) or ensure a NavigationContainer is rendered under <Connect>.");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
95
|
+
};
|
|
96
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
97
|
+
return () => {
|
|
98
|
+
if (timer) {
|
|
99
|
+
clearTimeout(timer);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}, [navigation]);
|
|
52
103
|
(0, _react.useEffect)(() => {
|
|
53
|
-
if (!
|
|
54
|
-
console.warn("Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " + "Pass `navigationRef` (from useNavigationContainerRef()) or ensure the direct child is a NavigationContainer.");
|
|
104
|
+
if (!navReady || !navigation?.current) {
|
|
55
105
|
return;
|
|
56
106
|
}
|
|
57
107
|
|
|
58
108
|
// Listen for the 'state' event to track navigation state changes
|
|
59
109
|
const unsubscribeState = navigation.current.addListener("state", () => {
|
|
60
110
|
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
|
|
61
|
-
console.log("State change - ", currentRoute.current);
|
|
62
111
|
if (_reactNative.Platform.OS === "ios" && currentRoute && currentRoute.current) {
|
|
63
112
|
_TLTRN.default.logScreenViewPageName(currentRoute.current);
|
|
64
113
|
} else if (_reactNative.Platform.OS === "android") {
|
|
@@ -71,7 +120,7 @@ const Connect = ({
|
|
|
71
120
|
return () => {
|
|
72
121
|
unsubscribeState();
|
|
73
122
|
};
|
|
74
|
-
}, [navigation]);
|
|
123
|
+
}, [navReady, navigation]);
|
|
75
124
|
const onStartShouldSetResponderCapture = (0, _react.useCallback)(event => {
|
|
76
125
|
if (navigation?.current?.getCurrentRoute) {
|
|
77
126
|
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_TLTRN","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","useRef","navigation","shouldInjectRef","React","isValidElement","currentRoute","undefined","initial","useEffect","TLTRN","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_TLTRN","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","useRef","navigation","shouldInjectRef","React","isValidElement","currentRoute","undefined","initial","navReady","setNavReady","useState","useEffect","TLTRN","interceptKeyboardEvents","interceptDialogEvents","isUsable","current","addListener","getCurrentRoute","attempts","POLL_INTERVAL_MS","MAX_ATTEMPTS","timer","poll","console","warn","setTimeout","clearTimeout","unsubscribeState","extractName","name","Platform","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","useCallback","event","logClickEvent","onLayout","_event","jsx","View","style","styles","connect_main","cloneElement","routeParams","params","_default","exports","StyleSheet","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
10
10
|
* prohibited.
|
|
11
11
|
********************************************************************************************/
|
|
12
|
-
import React, { useCallback, useEffect, useRef } from "react";
|
|
12
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
13
13
|
import { View, StyleSheet, Platform } from "react-native";
|
|
14
14
|
// Use type-only import for LayoutChangeEvent
|
|
15
15
|
import TLTRN from '../TLTRN';
|
|
@@ -35,22 +35,71 @@ const Connect = ({
|
|
|
35
35
|
const shouldInjectRef = !navigationRef && !childProvidedRef && /*#__PURE__*/React.isValidElement(child);
|
|
36
36
|
const currentRoute = useRef(undefined);
|
|
37
37
|
const initial = useRef(false);
|
|
38
|
+
// Tracks whether the resolved navigation ref has actually attached. See the
|
|
39
|
+
// readiness effect below for why a one-shot mount check is insufficient.
|
|
40
|
+
const [navReady, setNavReady] = useState(false);
|
|
38
41
|
useEffect(() => {
|
|
39
42
|
TLTRN.interceptKeyboardEvents(captureKeyboardEvents);
|
|
40
43
|
}, [captureKeyboardEvents]);
|
|
41
44
|
useEffect(() => {
|
|
42
45
|
TLTRN.interceptDialogEvents(captureDialogEvents);
|
|
43
46
|
}, [captureDialogEvents]);
|
|
47
|
+
|
|
48
|
+
// Wait for the NavigationContainer ref to actually attach before declaring
|
|
49
|
+
// it usable. When <Connect> wraps the container indirectly — intermediate
|
|
50
|
+
// providers (AppProvider, SafeAreaProvider, …), or any provider that defers
|
|
51
|
+
// rendering its subtree (async init, splash gate) — the container mounts
|
|
52
|
+
// AFTER <Connect>'s effects run, so `navigation.current` is still null at
|
|
53
|
+
// first paint. A one-shot mount check would warn and permanently disable
|
|
54
|
+
// tracking, because the effect's only dependency is the stable ref object
|
|
55
|
+
// and `.current` mutations don't retrigger effects. So we poll until the
|
|
56
|
+
// ref is usable, then flip `navReady` to subscribe. The direct-child case
|
|
57
|
+
// resolves on the first synchronous check (no polling, no warning). If the
|
|
58
|
+
// ref never attaches within the grace window we warn once, as before.
|
|
59
|
+
// See CA-144314.
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
// Reset readiness whenever the resolved ref changes. Without this, a
|
|
62
|
+
// `navigationRef` prop swap leaves `navReady` stale-true, so the
|
|
63
|
+
// subscription effect below re-runs and attaches `addListener` to the
|
|
64
|
+
// old container (whose `.current` is still non-null mid-transition)
|
|
65
|
+
// before the new ref is validated. Resetting forces re-validation
|
|
66
|
+
// through `isUsable()` before tracking re-enables. See CA-144314.
|
|
67
|
+
setNavReady(false);
|
|
68
|
+
const isUsable = () => !!navigation && !!navigation.current && typeof navigation.current.addListener === "function" && typeof navigation.current.getCurrentRoute === "function";
|
|
69
|
+
if (isUsable()) {
|
|
70
|
+
setNavReady(true);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
let attempts = 0;
|
|
74
|
+
const POLL_INTERVAL_MS = 100;
|
|
75
|
+
const MAX_ATTEMPTS = 100; // ~10s grace for deferred/async provider init
|
|
76
|
+
let timer;
|
|
77
|
+
const poll = () => {
|
|
78
|
+
if (isUsable()) {
|
|
79
|
+
setNavReady(true);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (attempts++ >= MAX_ATTEMPTS) {
|
|
83
|
+
console.warn("Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " + "Pass `navigationRef` (from useNavigationContainerRef()) or ensure a NavigationContainer is rendered under <Connect>.");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
87
|
+
};
|
|
88
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
89
|
+
return () => {
|
|
90
|
+
if (timer) {
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}, [navigation]);
|
|
44
95
|
useEffect(() => {
|
|
45
|
-
if (!
|
|
46
|
-
console.warn("Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " + "Pass `navigationRef` (from useNavigationContainerRef()) or ensure the direct child is a NavigationContainer.");
|
|
96
|
+
if (!navReady || !navigation?.current) {
|
|
47
97
|
return;
|
|
48
98
|
}
|
|
49
99
|
|
|
50
100
|
// Listen for the 'state' event to track navigation state changes
|
|
51
101
|
const unsubscribeState = navigation.current.addListener("state", () => {
|
|
52
102
|
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
|
|
53
|
-
console.log("State change - ", currentRoute.current);
|
|
54
103
|
if (Platform.OS === "ios" && currentRoute && currentRoute.current) {
|
|
55
104
|
TLTRN.logScreenViewPageName(currentRoute.current);
|
|
56
105
|
} else if (Platform.OS === "android") {
|
|
@@ -63,7 +112,7 @@ const Connect = ({
|
|
|
63
112
|
return () => {
|
|
64
113
|
unsubscribeState();
|
|
65
114
|
};
|
|
66
|
-
}, [navigation]);
|
|
115
|
+
}, [navReady, navigation]);
|
|
67
116
|
const onStartShouldSetResponderCapture = useCallback(event => {
|
|
68
117
|
if (navigation?.current?.getCurrentRoute) {
|
|
69
118
|
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useRef","View","StyleSheet","Platform","TLTRN","jsx","_jsx","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","navigation","shouldInjectRef","isValidElement","currentRoute","undefined","initial","interceptKeyboardEvents","interceptDialogEvents","current","addListener","getCurrentRoute","console","warn","unsubscribeState","extractName","name","
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useRef","useState","View","StyleSheet","Platform","TLTRN","jsx","_jsx","Connect","children","captureKeyboardEvents","captureDialogEvents","navigationRef","child","childProvidedRef","props","ref","internalRef","navigation","shouldInjectRef","isValidElement","currentRoute","undefined","initial","navReady","setNavReady","interceptKeyboardEvents","interceptDialogEvents","isUsable","current","addListener","getCurrentRoute","attempts","POLL_INTERVAL_MS","MAX_ATTEMPTS","timer","poll","console","warn","setTimeout","clearTimeout","unsubscribeState","extractName","name","OS","logScreenViewPageName","logScreenLayout","onStartShouldSetResponderCapture","event","logClickEvent","onLayout","_event","style","styles","connect_main","cloneElement","routeParams","params","create","flex"],"sourceRoot":"../../../src","sources":["components/Connect.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Connect.d.ts","sourceRoot":"","sources":["../../../../src/components/Connect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;6FAQ6F;AAC7F,OAAO,
|
|
1
|
+
{"version":3,"file":"Connect.d.ts","sourceRoot":"","sources":["../../../../src/components/Connect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;6FAQ6F;AAC7F,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;CACxC;AAED,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA8JnC,CAAC;AAWF,eAAe,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
"source": "src/index",
|
|
215
215
|
"summary": "react-native ios android tealeaf connect cxa wxca er enhanced-replay",
|
|
216
216
|
"types": "./lib/typescript/src/index.d.ts",
|
|
217
|
-
"version": "
|
|
217
|
+
"version": "19.0.1",
|
|
218
218
|
"workspaces": [
|
|
219
219
|
"example",
|
|
220
220
|
"Examples/bare-workflow"
|
package/scripts/gradleParser.js
CHANGED
|
@@ -15,7 +15,17 @@ const directoryPath = path.join(__dirname,"..","..","..")
|
|
|
15
15
|
|
|
16
16
|
console.log("Run gradleParser.js");
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// Resolve config.gradle via Node rather than a Gradle subproject lookup.
|
|
19
|
+
// `project(':react-native-acoustic-connect-beta')` only works if RN
|
|
20
|
+
// autolinking registered a subproject with that exact name — which RN 0.82 +
|
|
21
|
+
// new architecture does not guarantee — and fails the Gradle sync with
|
|
22
|
+
// "Project with path ':react-native-acoustic-connect-beta' could not be
|
|
23
|
+
// found" otherwise. `require.resolve` walks up node_modules from the Android
|
|
24
|
+
// rootDir and finds the package regardless of autolinking. See CA-144314.
|
|
25
|
+
const gradleCode = `apply from: new File(["node", "--print", "require.resolve('react-native-acoustic-connect-beta/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/android/config.gradle"`
|
|
26
|
+
// Matches the legacy `apply from: project(':react-native-acoustic-connect-beta')...`
|
|
27
|
+
// line so an existing integration is upgraded in place on the next install.
|
|
28
|
+
const legacyGradleCodeRe = /^.*apply from:\s*project\(':react-native-acoustic-connect-beta'\).*config\.gradle".*$/m
|
|
19
29
|
const filePath = `${directoryPath}/android/app/build.gradle`
|
|
20
30
|
|
|
21
31
|
if(!isValid(filePath)){
|
|
@@ -28,12 +38,20 @@ try {
|
|
|
28
38
|
gradleData = fs.readFileSync(filePath, 'utf8');
|
|
29
39
|
console.log("Read: " + filePath);
|
|
30
40
|
console.log(gradleData);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
|
|
42
|
+
if (gradleData.includes(gradleCode)) {
|
|
43
|
+
// Already integrated with the current (Node-resolved) form — no-op.
|
|
44
|
+
console.log("config.gradle apply-from already present, skipping:", filePath)
|
|
45
|
+
} else if (legacyGradleCodeRe.test(gradleData)) {
|
|
46
|
+
// Upgrade an existing integration that still uses the brittle
|
|
47
|
+
// project(':react-native-acoustic-connect-beta') subproject lookup.
|
|
48
|
+
gradleData = gradleData.replace(legacyGradleCodeRe, gradleCode)
|
|
49
|
+
fs.writeFileSync(filePath, gradleData);
|
|
50
|
+
console.log("Upgraded legacy config.gradle apply-from line in:", filePath)
|
|
51
|
+
} else {
|
|
35
52
|
gradleData = `${gradleData}\n${gradleCode}\n`
|
|
36
53
|
fs.writeFileSync(filePath, gradleData);
|
|
54
|
+
console.log("Added config.gradle apply-from line to:", filePath)
|
|
37
55
|
}
|
|
38
56
|
|
|
39
57
|
} catch (err) {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
8
|
* prohibited.
|
|
9
9
|
********************************************************************************************/
|
|
10
|
-
import React, { useCallback, useEffect, useRef } from "react";
|
|
10
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
11
11
|
import { View, StyleSheet, Platform } from "react-native";
|
|
12
12
|
import type { LayoutChangeEvent } from "react-native"; // Use type-only import for LayoutChangeEvent
|
|
13
13
|
import TLTRN from '../TLTRN';
|
|
@@ -53,6 +53,9 @@ const Connect: React.FC<ConnectProps> = ({
|
|
|
53
53
|
|
|
54
54
|
const currentRoute = useRef<string | undefined>(undefined);
|
|
55
55
|
const initial = useRef<boolean>(false);
|
|
56
|
+
// Tracks whether the resolved navigation ref has actually attached. See the
|
|
57
|
+
// readiness effect below for why a one-shot mount check is insufficient.
|
|
58
|
+
const [navReady, setNavReady] = useState<boolean>(false);
|
|
56
59
|
|
|
57
60
|
useEffect(() => {
|
|
58
61
|
TLTRN.interceptKeyboardEvents(captureKeyboardEvents);
|
|
@@ -62,25 +65,75 @@ const Connect: React.FC<ConnectProps> = ({
|
|
|
62
65
|
TLTRN.interceptDialogEvents(captureDialogEvents);
|
|
63
66
|
}, [captureDialogEvents]);
|
|
64
67
|
|
|
68
|
+
// Wait for the NavigationContainer ref to actually attach before declaring
|
|
69
|
+
// it usable. When <Connect> wraps the container indirectly — intermediate
|
|
70
|
+
// providers (AppProvider, SafeAreaProvider, …), or any provider that defers
|
|
71
|
+
// rendering its subtree (async init, splash gate) — the container mounts
|
|
72
|
+
// AFTER <Connect>'s effects run, so `navigation.current` is still null at
|
|
73
|
+
// first paint. A one-shot mount check would warn and permanently disable
|
|
74
|
+
// tracking, because the effect's only dependency is the stable ref object
|
|
75
|
+
// and `.current` mutations don't retrigger effects. So we poll until the
|
|
76
|
+
// ref is usable, then flip `navReady` to subscribe. The direct-child case
|
|
77
|
+
// resolves on the first synchronous check (no polling, no warning). If the
|
|
78
|
+
// ref never attaches within the grace window we warn once, as before.
|
|
79
|
+
// See CA-144314.
|
|
65
80
|
useEffect(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
// Reset readiness whenever the resolved ref changes. Without this, a
|
|
82
|
+
// `navigationRef` prop swap leaves `navReady` stale-true, so the
|
|
83
|
+
// subscription effect below re-runs and attaches `addListener` to the
|
|
84
|
+
// old container (whose `.current` is still non-null mid-transition)
|
|
85
|
+
// before the new ref is validated. Resetting forces re-validation
|
|
86
|
+
// through `isUsable()` before tracking re-enables. See CA-144314.
|
|
87
|
+
setNavReady(false);
|
|
88
|
+
|
|
89
|
+
const isUsable = () =>
|
|
90
|
+
!!navigation &&
|
|
91
|
+
!!navigation.current &&
|
|
92
|
+
typeof navigation.current.addListener === "function" &&
|
|
93
|
+
typeof navigation.current.getCurrentRoute === "function";
|
|
94
|
+
|
|
95
|
+
if (isUsable()) {
|
|
96
|
+
setNavReady(true);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let attempts = 0;
|
|
101
|
+
const POLL_INTERVAL_MS = 100;
|
|
102
|
+
const MAX_ATTEMPTS = 100; // ~10s grace for deferred/async provider init
|
|
103
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
104
|
+
|
|
105
|
+
const poll = () => {
|
|
106
|
+
if (isUsable()) {
|
|
107
|
+
setNavReady(true);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (attempts++ >= MAX_ATTEMPTS) {
|
|
111
|
+
console.warn(
|
|
112
|
+
"Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " +
|
|
113
|
+
"Pass `navigationRef` (from useNavigationContainerRef()) or ensure a NavigationContainer is rendered under <Connect>."
|
|
114
|
+
);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
118
|
+
};
|
|
119
|
+
timer = setTimeout(poll, POLL_INTERVAL_MS);
|
|
120
|
+
|
|
121
|
+
return () => {
|
|
122
|
+
if (timer) {
|
|
123
|
+
clearTimeout(timer);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}, [navigation]);
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!navReady || !navigation?.current) {
|
|
76
130
|
return;
|
|
77
131
|
}
|
|
78
132
|
|
|
79
133
|
// Listen for the 'state' event to track navigation state changes
|
|
80
134
|
const unsubscribeState = navigation.current.addListener("state", () => {
|
|
81
135
|
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
|
|
82
|
-
|
|
83
|
-
|
|
136
|
+
|
|
84
137
|
if (Platform.OS === "ios" && currentRoute && currentRoute.current) {
|
|
85
138
|
TLTRN.logScreenViewPageName(currentRoute.current);
|
|
86
139
|
} else if (Platform.OS === "android") {
|
|
@@ -93,7 +146,7 @@ const Connect: React.FC<ConnectProps> = ({
|
|
|
93
146
|
return () => {
|
|
94
147
|
unsubscribeState();
|
|
95
148
|
};
|
|
96
|
-
}, [navigation]);
|
|
149
|
+
}, [navReady, navigation]);
|
|
97
150
|
|
|
98
151
|
const onStartShouldSetResponderCapture = useCallback((event: any) => {
|
|
99
152
|
if (navigation?.current?.getCurrentRoute) {
|