UNPKG

@dynatrace/react-native-plugin

Version:

This plugin gives you the ability to use the Dynatrace Mobile agent in your react native application.

122 lines (121 loc) 4.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.findTouchableName = exports.chooseTouchableName = exports.wrapOnPress = exports.withOnPressMonitoring = void 0; const ReactNative = require("react-native"); const React = require("react"); const ConsoleLogger_1 = require("../../lib/core/logging/ConsoleLogger"); const ConfigurationHandler_1 = require("../../lib/core/configuration/ConfigurationHandler"); const Dynatrace_1 = require("../../lib/core/Dynatrace"); const ComponentUtil_1 = require("../jsx/components/ComponentUtil"); const Logger = new ConsoleLogger_1.ConsoleLogger('TouchableHelper'); function withOnPressMonitoring(Component, fallbackName) { return React.forwardRef((props, ref) => { const { onPress, onLongPress } = props; const touchableName = (0, exports.chooseTouchableName)(props, fallbackName); const dynatraceIgnored = (0, ComponentUtil_1.isDynatraceIgnored)(props); const propsWithoutRef = Object.assign(Object.assign(Object.assign({}, props), (!dynatraceIgnored && onPress && { onPress: (0, exports.wrapOnPress)(onPress, touchableName), })), (!dynatraceIgnored && onLongPress && { onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName), })); const propsWithRef = Object.assign(Object.assign({}, propsWithoutRef), { ref }); return React.createElement(Component, Object.assign({}, propsWithRef)); }); } exports.withOnPressMonitoring = withOnPressMonitoring; const wrapOnPress = (onPress, touchableName) => { return (...args) => { if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) { Logger.info('React Native plugin has not been started yet! Touch will not be reported!'); onPress(...args); } else { const action = Dynatrace_1.Dynatrace.enterAutoAction(`Touch on ${touchableName}`); let isSync = true; try { const returnValue = onPress(...args); if (returnValue instanceof Promise) { isSync = false; return Promise.resolve(returnValue).finally(() => { action.leaveAction(); }); } } finally { if (isSync) { action.leaveAction(); } } } }; }; exports.wrapOnPress = wrapOnPress; const chooseTouchableName = (props, fallbackName) => { if (props.dtActionName) { return props.dtActionName; } if (ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable() && ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled()) { return fallbackName; } return (0, exports.findTouchableName)(props) || fallbackName; }; exports.chooseTouchableName = chooseTouchableName; const findTouchableName = (props) => { if ('title' in props) { return props.title; } if (props.accessibilityLabel !== undefined) { return props.accessibilityLabel; } if (typeof props.children === 'function') { return null; } return findTouchableNameRecursive(props.children); }; exports.findTouchableName = findTouchableName; function findTouchableNameRecursive(node) { if (typeof node === 'string') { return node; } if (isReactNodeIterable(node)) { for (const child of node) { const result = findTouchableNameRecursive(child); if (result !== null) return result; } } if (React.isValidElement(node)) { if (isReactNativeImage(node)) { const uri = getUriFromSource(node.props.source); return uri ? 'Image Button: ' + uri : 'Image Button'; } if (isCustomIcon(node)) { return node.props.name; } if (hasReactNodeChildren(node)) return findTouchableNameRecursive(node.props.children); } return null; } function getUriFromSource(source) { if (typeof source === 'object' && 'uri' in source && source.uri !== undefined) { return source.uri; } return null; } const isReactNodeIterable = (node) => typeof node === 'object' && node !== null && Symbol.iterator in node; const isReactNativeImage = (element) => element.type === ReactNative.Image; const isCustomIcon = (element) => typeof element.type === 'function' && element.type.name === 'Icon' && typeof element.props === 'object' && element.props !== null && 'name' in element.props && typeof element.props.name === 'string'; const hasReactNodeChildren = (element) => typeof element.props === 'object' && element.props !== null && 'children' in element.props;