react-native-acoustic-connect-beta
Version:
BETA: React native plugin for Acoustic Connect
117 lines (113 loc) • 4.95 kB
JavaScript
;
/********************************************************************************************
* Copyright (C) 2025 Acoustic, L.P. All rights reserved.
*
* NOTICE: This file contains material that is confidential and proprietary to
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
* prohibited.
********************************************************************************************/
import React, { useCallback, useEffect, useRef } from "react";
import { View, StyleSheet, Platform } from "react-native";
// Use type-only import for LayoutChangeEvent
import TLTRN from '../TLTRN';
import { jsx as _jsx } from "react/jsx-runtime";
const Connect = ({
children,
captureKeyboardEvents,
captureDialogEvents = false,
navigationRef
}) => {
const child = children;
// CA-138631: React 19 moved the ref off `element.ref` onto `element.props.ref`.
// Read `props.ref` first; the legacy `child.ref` fallback is a defensive
// guard from the React 18 era — kept to avoid a behavioural change.
const childProvidedRef = child?.props?.ref ?? child?.ref;
const internalRef = useRef(null);
// Resolution order (explicit → legacy child ref → auto-injected fallback).
// The chosen ref flows through the same mount-effect / touch / layout
// guards, so any path that fails to resolve a usable navigation container
// simply disables tracking rather than breaking host-app gestures.
const navigation = navigationRef ?? childProvidedRef ?? internalRef;
const shouldInjectRef = !navigationRef && !childProvidedRef && /*#__PURE__*/React.isValidElement(child);
const currentRoute = useRef(undefined);
const initial = useRef(false);
useEffect(() => {
TLTRN.interceptKeyboardEvents(captureKeyboardEvents);
}, [captureKeyboardEvents]);
useEffect(() => {
TLTRN.interceptDialogEvents(captureDialogEvents);
}, [captureDialogEvents]);
useEffect(() => {
if (!navigation || !navigation.current || typeof navigation.current.addListener !== "function" || typeof navigation.current.getCurrentRoute !== "function") {
console.warn("Connect: navigation tracking disabled — no usable NavigationContainer ref resolved. " + "Pass `navigationRef` (from useNavigationContainerRef()) or ensure the direct child is a NavigationContainer.");
return;
}
// Listen for the 'state' event to track navigation state changes
const unsubscribeState = navigation.current.addListener("state", () => {
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
console.log("State change - ", currentRoute.current);
if (Platform.OS === "ios" && currentRoute && currentRoute.current) {
TLTRN.logScreenViewPageName(currentRoute.current);
} else if (Platform.OS === "android") {
TLTRN.logScreenViewPageName(currentRoute.current);
TLTRN.logScreenLayout(currentRoute.current);
}
});
// Cleanup listeners when the component unmounts or dependencies change
return () => {
unsubscribeState();
};
}, [navigation]);
const onStartShouldSetResponderCapture = useCallback(event => {
if (navigation?.current?.getCurrentRoute) {
currentRoute.current = extractName(navigation) || navigation.current.getCurrentRoute()?.name;
if (currentRoute.current) {
TLTRN.logScreenViewPageName(currentRoute.current);
}
}
TLTRN.logClickEvent(event);
return false; // Must remain false so events bubble to the host app's handlers
}, [navigation]);
const onLayout = useCallback(_event => {
if (initial.current) {
return false;
}
initial.current = true;
if (navigation?.current?.getCurrentRoute) {
currentRoute.current = navigation.current.getCurrentRoute()?.name;
if (Platform.OS === "ios" && currentRoute.current) {
TLTRN.logScreenViewPageName(currentRoute.current);
} else if (Platform.OS === "android") {
TLTRN.logScreenLayout(currentRoute.current);
}
}
return true;
}, [navigation]);
return /*#__PURE__*/_jsx(View, {
style: styles.connect_main,
onLayout: onLayout,
onStartShouldSetResponderCapture: onStartShouldSetResponderCapture,
children: shouldInjectRef ? /*#__PURE__*/React.cloneElement(child, {
ref: internalRef
}) : children
});
};
function extractName(navigation) {
const routeParams = navigation?.current?.getCurrentRoute?.()?.params;
if (routeParams) {
const {
name
} = routeParams;
return name ? name : navigation.current?.getCurrentRoute()?.name || "";
}
return "";
}
export default Connect;
const styles = StyleSheet.create({
connect_main: {
flex: 1
}
});
//# sourceMappingURL=Connect.js.map