@dynatrace/react-native-plugin 2.343.1 → 2.347.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/README.md +674 -656
- package/android/build.gradle +6 -2
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +24 -0
- package/files/plugin-runtime.gradle +17 -33
- package/files/plugin.gradle +1 -1
- package/instrumentation/BabelPluginDynatrace.js +1 -1
- package/instrumentation/libs/UserInteraction.js +20 -6
- package/instrumentation/libs/react-native/Lists.js +94 -0
- package/instrumentation/libs/react-native/index.js +4 -1
- package/instrumentation/libs/react-native.js +3 -0
- package/instrumentation/libs/react-navigation/ReactNavigation.js +14 -58
- package/instrumentation/libs/withOnPressMonitoring.js +3 -54
- package/internal.d.ts +2 -0
- package/internal.js +5 -1
- package/ios/DynatraceRNBridge.mm +37 -1
- package/lib/core/configuration/ConfigurationHandler.js +0 -21
- package/lib/core/logging/LogMessages.js +50 -0
- package/lib/dynatrace-reporter.js +1 -30
- package/lib/dynatrace-transformer.js +6 -34
- package/lib/next/configuration/INativeRuntimeConfiguration.js +0 -1
- package/lib/next/configuration/RuntimeConfigurationObserver.js +1 -6
- package/lib/next/events/spec/EventSpecContstants.js +1 -1
- package/lib/next/navigation/NavigationTracker.js +101 -0
- package/lib/next/navigation/useNavigationTracking.js +54 -0
- package/lib/next/triggers/TableReloadTracker.js +23 -0
- package/package.json +11 -21
- package/public.js +3 -1
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Android.js +1 -20
- package/scripts/Config.js +0 -4
- package/scripts/Deprecations.js +18 -0
- package/scripts/Install.js +13 -0
- package/scripts/PathsConstants.js +0 -4
- package/scripts/Uninstall.js +0 -15
- package/scripts/core/InstrumentCall.js +2 -3
- package/scripts/util/DeprecationReport.js +24 -0
- package/types.d.ts +212 -10
- package/instrumentation/DynatraceInstrumentation.js +0 -1
- package/instrumentation/libs/community/Picker.InstrInfo.js +0 -20
- package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +0 -25
- package/instrumentation/libs/react-native/RefreshControl.InstrInfo.js +0 -12
- package/instrumentation/libs/react-native/Switch.InstrInfo.js +0 -12
- package/instrumentation/libs/react-native/Touchables.InstrInfo.js +0 -25
- package/instrumentation/model/Reference.js +0 -2
- package/instrumentation/parser/Babel.js +0 -60
- package/instrumentation/parser/ParserUtil.js +0 -11
- package/lib/features/ui-interaction/Config.js +0 -42
- package/lib/features/ui-interaction/IUserInteractionEvent.js +0 -16
- package/lib/features/ui-interaction/Plugin.Fragment.Test.js +0 -170
- package/lib/features/ui-interaction/Plugin.js +0 -289
- package/lib/features/ui-interaction/RootDetection.js +0 -51
- package/lib/features/ui-interaction/RootWrapper.js +0 -236
- package/lib/features/ui-interaction/Run.js +0 -38
- package/lib/features/ui-interaction/Runtime.js +0 -843
- package/lib/features/ui-interaction/TouchMetaResolver.js +0 -493
- package/lib/features/ui-interaction/Types.js +0 -14
- package/lib/metro/getSourceMapInfo.js +0 -26
- package/scripts/LineOffsetAnalyze.js +0 -25
- package/scripts/core/LineOffsetAnalyzeCall.js +0 -165
- package/scripts/util/SourceMapUtil.js +0 -68
package/android/build.gradle
CHANGED
|
@@ -29,7 +29,9 @@ buildscript {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
apply plugin: 'com.android.library'
|
|
32
|
-
|
|
32
|
+
if (!project.extensions.findByName('kotlin')) {
|
|
33
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
34
|
+
}
|
|
33
35
|
|
|
34
36
|
if (isNewArchitectureEnabled()) {
|
|
35
37
|
apply plugin: 'com.facebook.react'
|
|
@@ -68,8 +70,10 @@ android {
|
|
|
68
70
|
main {
|
|
69
71
|
if (isNewArchitectureEnabled()) {
|
|
70
72
|
java.srcDirs += ['src/new']
|
|
73
|
+
kotlin.srcDirs += ['src/new']
|
|
71
74
|
} else {
|
|
72
75
|
java.srcDirs += ['src/old']
|
|
76
|
+
kotlin.srcDirs += ['src/old']
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
}
|
|
@@ -81,7 +85,7 @@ repositories {
|
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
dependencies {
|
|
84
|
-
implementation 'com.dynatrace.agent:agent-android:8.
|
|
88
|
+
implementation 'com.dynatrace.agent:agent-android:8.347.1.1003'
|
|
85
89
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
|
|
86
90
|
}
|
|
87
91
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
package com.dynatrace.android.agent
|
|
2
2
|
|
|
3
3
|
import android.location.Location
|
|
4
|
+
import android.os.Handler
|
|
5
|
+
import android.os.Looper
|
|
6
|
+
import android.view.Choreographer
|
|
4
7
|
import com.dynatrace.android.agent.conf.DataCollectionLevel
|
|
5
8
|
import com.dynatrace.android.agent.conf.DynatraceConfigurationBuilder
|
|
6
9
|
import com.dynatrace.android.agent.conf.UserPrivacyOptions
|
|
@@ -46,6 +49,7 @@ class DynatraceRNBridgeImpl(
|
|
|
46
49
|
private var lastConfiguration: MutableMap<String, Any>? = null
|
|
47
50
|
private var hasInternalListener: Boolean = false
|
|
48
51
|
private var listenersCount: Int = 0
|
|
52
|
+
private val navGeneration = java.util.concurrent.atomic.AtomicInteger(0)
|
|
49
53
|
|
|
50
54
|
fun getConstants(): Map<String, Any> {
|
|
51
55
|
return constants;
|
|
@@ -472,8 +476,28 @@ class DynatraceRNBridgeImpl(
|
|
|
472
476
|
}
|
|
473
477
|
}
|
|
474
478
|
|
|
479
|
+
// NOTE: This callback is observational only — it measures the first rendered frame for
|
|
480
|
+
// diagnostic tooling (LOAD TIME display). It does not defer stopView(); deferring the
|
|
481
|
+
// view-end to the rendered frame to fix TTID under-reporting (DEM-32277) is a separate task.
|
|
475
482
|
fun startViewInternal(fields: ReadableMap) {
|
|
483
|
+
val imNanos = System.nanoTime()
|
|
484
|
+
val gen = navGeneration.incrementAndGet()
|
|
476
485
|
HybridBridge.startView(JSONObject(DynatraceUtils.toHashMap(fields)))
|
|
486
|
+
Handler(Looper.getMainLooper()).post {
|
|
487
|
+
Choreographer.getInstance().postFrameCallback { frameTimeNanos ->
|
|
488
|
+
// Discard stale callbacks superseded by a newer navigation.
|
|
489
|
+
if (navGeneration.get() != gen) return@postFrameCallback
|
|
490
|
+
val frameEpochMs = System.currentTimeMillis()
|
|
491
|
+
val deltaMs = (frameTimeNanos - imNanos) / 1_000_000.0
|
|
492
|
+
val params = Arguments.createMap().apply {
|
|
493
|
+
putDouble("frameEndMs", frameEpochMs.toDouble())
|
|
494
|
+
putDouble("deltaMs", deltaMs)
|
|
495
|
+
}
|
|
496
|
+
reactApplicationContext
|
|
497
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
498
|
+
.emit("DTNavigationFrame", params)
|
|
499
|
+
}
|
|
500
|
+
}
|
|
477
501
|
}
|
|
478
502
|
|
|
479
503
|
fun stopViewInternal() {
|
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
commandLine 'npx', 'lineOffsetDynatrace'
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
android.applicationVariants.all { variant ->
|
|
25
|
-
if (variant.buildType.name == "release") {
|
|
26
|
-
def lineOffsetTask = tasks.register("runLineOffset${variant.name.capitalize()}", RunLineOffsetTask) {
|
|
27
|
-
workingDirectory = layout.projectDirectory
|
|
28
|
-
}
|
|
29
|
-
variant.mergeAssetsProvider.configure { task ->
|
|
30
|
-
task.dependsOn(lineOffsetTask)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
1
|
+
// Intentionally left empty. DO NOT DELETE THIS FILE.
|
|
2
|
+
//
|
|
3
|
+
// Apps instrumented with an older version of this plugin have the following
|
|
4
|
+
// line hard-coded in their android/app/build.gradle:
|
|
5
|
+
//
|
|
6
|
+
// apply from: "../../node_modules/@dynatrace/react-native-plugin/files/plugin-runtime.gradle"
|
|
7
|
+
//
|
|
8
|
+
// That line lives in the customer's own build.gradle, so we cannot reliably
|
|
9
|
+
// remove it on upgrade. If this file were missing, the `apply from:` above
|
|
10
|
+
// would fail the Gradle build for every app that still has that line.
|
|
11
|
+
//
|
|
12
|
+
// Previously this script registered a release-build Gradle task that ran
|
|
13
|
+
// `npx lineOffsetDynatrace` for line-offset analysis. That is no longer needed:
|
|
14
|
+
// auto-instrumentation moved to a Babel plugin and capturing moved to native,
|
|
15
|
+
// so the script is now a no-op kept purely for backward compatibility.
|
|
16
|
+
//
|
|
17
|
+
// New installs no longer add the `apply from:` line at all.
|
package/files/plugin.gradle
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var _templateObject,_templateObject2,_templateObject3,_templateObject4,_templateObject5,_templateObject6,_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_taggedTemplateLiteral2=_interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));function _createForOfIteratorHelper(e,t){var n,r,a,i,o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(o)return a=!(r=!0),{s:function(){o=o.call(e)},n:function(){var e=o.next();return r=e.done,e},e:function(e){a=!0,n=e},f:function(){try{r||null==o.return||o.return()}finally{if(a)throw n}}};if(Array.isArray(e)||(o=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return o&&(e=o),i=0,{s:t=function(){},n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:t};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0});var reactOptions,fspath=require("path"),fs=require("fs"),core_1=require("@babel/core"),generator_1=require("@babel/generator"),PathsConstants_1=require("../scripts/PathsConstants"),Config_1=require("../scripts/Config"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),Types_1=require("./model/Types"),INSTRUMENTATION_LIBS="@dynatrace/react-native-plugin/instrumentation/libs",COMPONENTS_EXCLUDED_FROM_UIA=new Set(["Fragment","React.Fragment"]),hasJSX=function(e){var t=!1;return e.traverse({"JSXElement|JSXFragment":function(){t=!0}}),t},instrumentUserInteraction=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"registerComponent"})&&(t="".concat(INSTRUMENTATION_LIBS,"/UserInteraction"),e.body.body.unshift(core_1.template.statement('componentProvider = require("'.concat(t,'").wrapProvider(componentProvider);'))()))}})},instrumentAppRegistry=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"runApplication"})&&e.body.body.unshift(core_1.template.statement(_templateObject=_templateObject||(0,_taggedTemplateLiteral2.default)(['require("@dynatrace/react-native-plugin").ApplicationHandler.startup();']))())}})},instrumentExceptionsManager=function(e){var t,n=null!=(t=null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.reportFatalErrorAsCrash)&&t,r=(null==reactOptions?void 0:reactOptions.autoStart)&&(null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.enabled);e.traverse({FunctionDeclaration:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"handleException"})&&(t=core_1.template.statement(_templateObject2=_templateObject2||(0,_taggedTemplateLiteral2.default)(['\n setTimeout(() => BODY, require("@dynatrace/react-native-plugin/lib/core/ErrorHandler")\n .reportErrorToDynatrace(e, isFatal, CRASH, AUTO));\n ']))({BODY:core_1.types.cloneNode(e.node.body),CRASH:core_1.types.booleanLiteral(n),AUTO:core_1.types.booleanLiteral(!!r)}),e.node.body.body=[t])}})},instrumentCssInterop=function(e){e.traverse({CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&("react/jsx-runtime"===e.value?e.value="@dynatrace/react-native-plugin/jsx-runtime":"react/jsx-dev-runtime"===e.value&&(e.value="@dynatrace/react-native-plugin/jsx-dev-runtime"))}})},instrumentNavigation=function(e){e.traverse({VariableDeclarator:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"getRootState"})&&(t=core_1.template.statement(_templateObject3=_templateObject3||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).monitorNavigation(getRootState);\n "]))({PATH:core_1.types.stringLiteral("".concat(INSTRUMENTATION_LIBS,"/react-navigation/ReactNavigation"))}),e.parentPath.insertAfter(t))}})},instrumentReactCreateElement=function(e){var t=core_1.template.statement(_templateObject4=_templateObject4||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).instrumentCreateElement(module.exports);\n "]))({PATH:core_1.types.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")});e.pushContainer("body",t)},instrumentComponents=function(e,n){e.traverse({FunctionDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.FunctionalComponent))},ClassDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.ClassComponent))},"FunctionExpression|ArrowFunctionExpression":function(e){var t;hasJSX(e)&&(t=e.parent,void 0!==(t=core_1.types.isVariableDeclarator(t)&&core_1.types.isIdentifier(t.id)?t.id.name:core_1.types.isAssignmentExpression(t)&&core_1.types.isIdentifier(t.left)?t.left.name:void 0))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t,Types_1.Types.FunctionalComponent))}})},instrumentLifecycle=function(e){instrumentComponents(e,function(e,t){return core_1.template.statement(_templateObject5=_templateObject5||(0,_taggedTemplateLiteral2.default)(["NAME._dtInfo = { type: TYPE, name: 'NAME_STR' }"]))({NAME:core_1.types.identifier(e),TYPE:core_1.types.numericLiteral(t),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentComponentNames=function(e){instrumentComponents(e,function(e){return core_1.template.statement(_templateObject6=_templateObject6||(0,_taggedTemplateLiteral2.default)(["NAME.dtName = 'NAME_STR'"]))({NAME:core_1.types.identifier(e),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentInput=function(e){var u=new Map([["react-native",{proxy:"".concat(INSTRUMENTATION_LIBS,"/react-native/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","Button","RefreshControl","Text","Pressable","Switch"])}],["react-native-gesture-handler",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/gesture-handler/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","RectButton","BorderlessButton","BaseButton"])}],["@react-native-picker/picker",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/Picker"),components:new Set(["Picker","PickerIOS"])}]]);e.traverse({ImportDeclaration:function(e){if(void 0===e.node.processed){var t=e.node.source;if(u.has(t.value)){var r=u.get(t.value),n=e.node.specifiers,a=[],i=[];if(n.forEach(function(e,t){var n;core_1.types.isImportSpecifier(e)&&(n=core_1.types.isIdentifier(e.imported)?e.imported.name:e.imported.value,r.components.has(n)||(a.push(e),i.push(t)))}),a.length!==n.length){var o,s=_createForOfIteratorHelper([].concat(i).reverse());try{for(s.s();!(o=s.n()).done;){var c=o.value;n.splice(c,1)}}catch(e){s.e(e)}finally{s.f()}0<a.length&&((t=core_1.types.importDeclaration(a,core_1.types.stringLiteral(t.value))).processed=!0,e.insertBefore(t)),e.node.source=core_1.types.stringLiteral(r.proxy),e.scope.crawl()}}}},CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&u.has(e.value)&&(e.value=u.get(e.value).proxy)}})},instrumentJsxNames=function(e){e.traverse({JSXOpeningElement:function(e){var t=e.node.name,t=core_1.types.isJSXIdentifier(t)?t.name:core_1.types.isJSXMemberExpression(t)?(0,generator_1.default)(t).code:void 0;t&&!COMPONENTS_EXCLUDED_FROM_UIA.has(t)&&e.node.attributes.unshift(core_1.types.jsxAttribute(core_1.types.jsxIdentifier("dtName"),core_1.types.stringLiteral(t)))}})},instrumentConfigurationPreset=function(e){var t,n=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),r={getLifecycleUpdate:reactOptions.lifecycle.includeUpdate,getLogLevel:reactOptions.debug?0:1,getBundleName:null!=(t=reactOptions.bundleName)?t:null==n?void 0:n.name,getBundleVersion:null!=(t=reactOptions.bundleVersion)?t:null==n?void 0:n.version,getActionNamePrivacy:reactOptions.input.actionNamePrivacy,getActionNamePreference:reactOptions.input.actionNamePreference,getActionNameAlgorithm:reactOptions.input.actionNameAlgorithm,isErrorHandlerEnabled:reactOptions.errorHandler.enabled,isReportFatalErrorAsCrash:reactOptions.errorHandler.reportFatalErrorAsCrash,isAutoStartupEnabled:reactOptions.autoStart};e.traverse({ClassMethod:function(e){var t;core_1.types.isIdentifier(e.node.key)&&void 0!==(t=r[e.node.key.name])&&(e=e.node.body.body[0],core_1.types.isReturnStatement(e))&&(e.argument=core_1.types.valueToNode(t))}})},createFilenameMatcher=function(r){return{isModule:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return r.includes(fspath.join("node_modules",e)+fspath.sep)})},isFile:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return r.endsWith(e)})}}},captureOriginalCode=function(e){return!0!==reactOptions.debugBabelPlugin?"":(0,generator_1.default)(e.node).code},isConfigurationPresetTarget=function(e){return e.isModule("@dynatrace")&&e.isFile("ConfigurationPreset.js")},isAppRegistryTarget=function(e){return e.isModule("react-native")&&e.isFile("AppRegistry.js","AppRegistryImpl.js")},isExceptionsManagerTarget=function(e){return e.isModule("react-native")&&e.isFile("ExceptionsManager.js")},isCssInteropTarget=function(e){return e.isModule("react-native-css-interop")&&e.isFile("jsx-runtime.js","jsx-dev-runtime.js")},isNavigationTarget=function(e){return reactOptions.navigation.enabled&&e.isModule("@react-navigation")&&e.isFile("BaseNavigationContainer.js","BaseNavigationContainer.tsx")},isReactIndexTarget=function(e){return e.isModule("react")&&e.isFile("index.js")},shouldInstrumentLifecycleForFile=function(e,t,n){var r,a,n=n.isModule("react-native")&&n.isFile("renderApplication.js");return(null==(a=null==(r=reactOptions.lifecycle)?void 0:r.instrument)?void 0:a.call(r,t))&&(!t.includes("node_modules")||n)&&hasJSX(e)},shouldInstrumentInputForFile=function(e,t){var n,r,t=t.isModule("@react-navigation","react-native-drawer-layout");return(null==(r=null==(n=reactOptions.input)?void 0:n.instrument)?void 0:r.call(n,e))&&(!e.includes("node_modules")||t)},shouldInstrumentUserInteractionNames=function(e){return reactOptions.userInteraction&&!e.includes("node_modules")},instrumentByModuleAndFile=function(e,t,n){isConfigurationPresetTarget(n)&&instrumentConfigurationPreset(e),isAppRegistryTarget(n)&&(reactOptions.autoStart&&instrumentAppRegistry(e),reactOptions.userInteraction)&&instrumentUserInteraction(e),isExceptionsManagerTarget(n)&&instrumentExceptionsManager(e),isCssInteropTarget(n)&&instrumentCssInterop(e),isNavigationTarget(n)&&instrumentNavigation(e),isReactIndexTarget(n)&&instrumentReactCreateElement(e),shouldInstrumentLifecycleForFile(e,t,n)&&instrumentLifecycle(e),shouldInstrumentInputForFile(t,n)&&instrumentInput(e),shouldInstrumentUserInteractionNames(t)&&(instrumentJsxNames(e),instrumentComponentNames(e))},writeDebugOutputIfChanged=function(e,t,n,r){!0===reactOptions.debugBabelPlugin&&(e=(0,generator_1.default)(e.node).code)!==r&&(r=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),n)+".dtx"),fs.mkdirSync(fspath.dirname(r),{recursive:!0}),fs.writeFileSync(r,e),t.set("fileDidChange",!0))};exports.default=function(){return{visitor:{Program:function(e,t){reactOptions=(0,Config_1.readConfigDefault)().react;var n,r,a=t.filename;void 0!==a&&(n=createFilenameMatcher(a),r=captureOriginalCode(e),instrumentByModuleAndFile(e,a,n),writeDebugOutputIfChanged(e,t,a,r))}},post:function(e){var t;!0===reactOptions.debugBabelPlugin&&!0===this.get("fileDidChange")&&(t=(0,generator_1.default)(e.ast).code,e=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),e.opts.filename)+".dtx.downstream"),fs.mkdirSync(fspath.dirname(e),{recursive:!0}),fs.writeFileSync(e,t))}}};
|
|
1
|
+
var _templateObject,_templateObject2,_templateObject3,_templateObject4,_templateObject5,_templateObject6,_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_taggedTemplateLiteral2=_interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));function _createForOfIteratorHelper(e,t){var n,r,a,i,o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(o)return a=!(r=!0),{s:function(){o=o.call(e)},n:function(){var e=o.next();return r=e.done,e},e:function(e){a=!0,n=e},f:function(){try{r||null==o.return||o.return()}finally{if(a)throw n}}};if(Array.isArray(e)||(o=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return o&&(e=o),i=0,{s:t=function(){},n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:t};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0});var reactOptions,fspath=require("path"),fs=require("fs"),core_1=require("@babel/core"),generator_1=require("@babel/generator"),PathsConstants_1=require("../scripts/PathsConstants"),Config_1=require("../scripts/Config"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),Types_1=require("./model/Types"),INSTRUMENTATION_LIBS="@dynatrace/react-native-plugin/instrumentation/libs",COMPONENTS_EXCLUDED_FROM_UIA=new Set(["Fragment","React.Fragment"]),hasJSX=function(e){var t=!1;return e.traverse({"JSXElement|JSXFragment":function(){t=!0}}),t},instrumentUserInteraction=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"registerComponent"})&&(t="".concat(INSTRUMENTATION_LIBS,"/UserInteraction"),e.body.body.unshift(core_1.template.statement('componentProvider = require("'.concat(t,'").wrapProvider(componentProvider);'))()))}})},instrumentAppRegistry=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"runApplication"})&&e.body.body.unshift(core_1.template.statement(_templateObject=_templateObject||(0,_taggedTemplateLiteral2.default)(['require("@dynatrace/react-native-plugin").ApplicationHandler.startup();']))())}})},instrumentExceptionsManager=function(e){var t,n=null!=(t=null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.reportFatalErrorAsCrash)&&t,r=(null==reactOptions?void 0:reactOptions.autoStart)&&(null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.enabled);e.traverse({FunctionDeclaration:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"handleException"})&&(t=core_1.template.statement(_templateObject2=_templateObject2||(0,_taggedTemplateLiteral2.default)(['\n setTimeout(() => BODY, require("@dynatrace/react-native-plugin/lib/core/ErrorHandler")\n .reportErrorToDynatrace(e, isFatal, CRASH, AUTO));\n ']))({BODY:core_1.types.cloneNode(e.node.body),CRASH:core_1.types.booleanLiteral(n),AUTO:core_1.types.booleanLiteral(!!r)}),e.node.body.body=[t])}})},instrumentCssInterop=function(e){e.traverse({CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&("react/jsx-runtime"===e.value?e.value="@dynatrace/react-native-plugin/jsx-runtime":"react/jsx-dev-runtime"===e.value&&(e.value="@dynatrace/react-native-plugin/jsx-dev-runtime"))}})},instrumentNavigation=function(e){e.traverse({VariableDeclarator:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"getRootState"})&&(t=core_1.template.statement(_templateObject3=_templateObject3||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).useNavigationMonitor(getRootState);\n "]))({PATH:core_1.types.stringLiteral("".concat(INSTRUMENTATION_LIBS,"/react-navigation/ReactNavigation"))}),e.parentPath.insertAfter(t))}})},instrumentReactCreateElement=function(e){var t=core_1.template.statement(_templateObject4=_templateObject4||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).instrumentCreateElement(module.exports);\n "]))({PATH:core_1.types.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")});e.pushContainer("body",t)},instrumentComponents=function(e,n){e.traverse({FunctionDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.FunctionalComponent))},ClassDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.ClassComponent))},"FunctionExpression|ArrowFunctionExpression":function(e){var t;hasJSX(e)&&(t=e.parent,void 0!==(t=core_1.types.isVariableDeclarator(t)&&core_1.types.isIdentifier(t.id)?t.id.name:core_1.types.isAssignmentExpression(t)&&core_1.types.isIdentifier(t.left)?t.left.name:void 0))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t,Types_1.Types.FunctionalComponent))}})},instrumentLifecycle=function(e){instrumentComponents(e,function(e,t){return core_1.template.statement(_templateObject5=_templateObject5||(0,_taggedTemplateLiteral2.default)(["NAME._dtInfo = { type: TYPE, name: 'NAME_STR' }"]))({NAME:core_1.types.identifier(e),TYPE:core_1.types.numericLiteral(t),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentComponentNames=function(e){instrumentComponents(e,function(e){return core_1.template.statement(_templateObject6=_templateObject6||(0,_taggedTemplateLiteral2.default)(["NAME.dtName = 'NAME_STR'"]))({NAME:core_1.types.identifier(e),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentInput=function(e){var u=new Map([["react-native",{proxy:"".concat(INSTRUMENTATION_LIBS,"/react-native/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","Button","RefreshControl","Text","Pressable","Switch","FlatList","SectionList"])}],["react-native-gesture-handler",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/gesture-handler/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","RectButton","BorderlessButton","BaseButton"])}],["@react-native-picker/picker",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/Picker"),components:new Set(["Picker","PickerIOS"])}]]);e.traverse({ImportDeclaration:function(e){if(void 0===e.node.processed){var t=e.node.source;if(u.has(t.value)){var r=u.get(t.value),n=e.node.specifiers,a=[],i=[];if(n.forEach(function(e,t){var n;core_1.types.isImportSpecifier(e)&&(n=core_1.types.isIdentifier(e.imported)?e.imported.name:e.imported.value,r.components.has(n)||(a.push(e),i.push(t)))}),a.length!==n.length){var o,s=_createForOfIteratorHelper([].concat(i).reverse());try{for(s.s();!(o=s.n()).done;){var c=o.value;n.splice(c,1)}}catch(e){s.e(e)}finally{s.f()}0<a.length&&((t=core_1.types.importDeclaration(a,core_1.types.stringLiteral(t.value))).processed=!0,e.insertBefore(t)),e.node.source=core_1.types.stringLiteral(r.proxy),e.scope.crawl()}}}},CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&u.has(e.value)&&(e.value=u.get(e.value).proxy)}})},instrumentJsxNames=function(e){e.traverse({JSXOpeningElement:function(e){var t=e.node.name,t=core_1.types.isJSXIdentifier(t)?t.name:core_1.types.isJSXMemberExpression(t)?(0,generator_1.default)(t).code:void 0;t&&!COMPONENTS_EXCLUDED_FROM_UIA.has(t)&&e.node.attributes.unshift(core_1.types.jsxAttribute(core_1.types.jsxIdentifier("dtName"),core_1.types.stringLiteral(t)))}})},instrumentConfigurationPreset=function(e){var t,n=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),r={getLifecycleUpdate:reactOptions.lifecycle.includeUpdate,getLogLevel:reactOptions.debug?0:1,getBundleName:null!=(t=reactOptions.bundleName)?t:null==n?void 0:n.name,getBundleVersion:null!=(t=reactOptions.bundleVersion)?t:null==n?void 0:n.version,getActionNamePrivacy:reactOptions.input.actionNamePrivacy,getActionNamePreference:reactOptions.input.actionNamePreference,getActionNameAlgorithm:reactOptions.input.actionNameAlgorithm,isErrorHandlerEnabled:reactOptions.errorHandler.enabled,isReportFatalErrorAsCrash:reactOptions.errorHandler.reportFatalErrorAsCrash,isAutoStartupEnabled:reactOptions.autoStart};e.traverse({ClassMethod:function(e){var t;core_1.types.isIdentifier(e.node.key)&&void 0!==(t=r[e.node.key.name])&&(e=e.node.body.body[0],core_1.types.isReturnStatement(e))&&(e.argument=core_1.types.valueToNode(t))}})},createFilenameMatcher=function(r){return{isModule:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return r.includes(fspath.join("node_modules",e)+fspath.sep)})},isFile:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return r.endsWith(e)})}}},captureOriginalCode=function(e){return!0!==reactOptions.debugBabelPlugin?"":(0,generator_1.default)(e.node).code},isConfigurationPresetTarget=function(e){return e.isModule("@dynatrace")&&e.isFile("ConfigurationPreset.js")},isAppRegistryTarget=function(e){return e.isModule("react-native")&&e.isFile("AppRegistry.js","AppRegistryImpl.js")},isExceptionsManagerTarget=function(e){return e.isModule("react-native")&&e.isFile("ExceptionsManager.js")},isCssInteropTarget=function(e){return e.isModule("react-native-css-interop")&&e.isFile("jsx-runtime.js","jsx-dev-runtime.js")},isNavigationTarget=function(e){return reactOptions.navigation.enabled&&e.isModule("@react-navigation")&&e.isFile("BaseNavigationContainer.js","BaseNavigationContainer.tsx")},isReactIndexTarget=function(e){return e.isModule("react")&&e.isFile("index.js")},shouldInstrumentLifecycleForFile=function(e,t,n){var r,a,n=n.isModule("react-native")&&n.isFile("renderApplication.js");return(null==(a=null==(r=reactOptions.lifecycle)?void 0:r.instrument)?void 0:a.call(r,t))&&(!t.includes("node_modules")||n)&&hasJSX(e)},shouldInstrumentInputForFile=function(e,t){var n,r,t=t.isModule("@react-navigation","react-native-drawer-layout");return(null==(r=null==(n=reactOptions.input)?void 0:n.instrument)?void 0:r.call(n,e))&&(!e.includes("node_modules")||t)},shouldInstrumentUserInteractionNames=function(e){return reactOptions.userInteraction&&!e.includes("node_modules")},instrumentByModuleAndFile=function(e,t,n){isConfigurationPresetTarget(n)&&instrumentConfigurationPreset(e),isAppRegistryTarget(n)&&(reactOptions.autoStart&&instrumentAppRegistry(e),reactOptions.userInteraction)&&instrumentUserInteraction(e),isExceptionsManagerTarget(n)&&instrumentExceptionsManager(e),isCssInteropTarget(n)&&instrumentCssInterop(e),isNavigationTarget(n)&&instrumentNavigation(e),isReactIndexTarget(n)&&instrumentReactCreateElement(e),shouldInstrumentLifecycleForFile(e,t,n)&&instrumentLifecycle(e),shouldInstrumentInputForFile(t,n)&&instrumentInput(e),shouldInstrumentUserInteractionNames(t)&&(instrumentJsxNames(e),instrumentComponentNames(e))},writeDebugOutputIfChanged=function(e,t,n,r){!0===reactOptions.debugBabelPlugin&&(e=(0,generator_1.default)(e.node).code)!==r&&(r=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),n)+".dtx"),fs.mkdirSync(fspath.dirname(r),{recursive:!0}),fs.writeFileSync(r,e),t.set("fileDidChange",!0))};exports.default=function(){return{visitor:{Program:function(e,t){reactOptions=(0,Config_1.readConfigDefault)().react;var n,r,a=t.filename;void 0!==a&&(n=createFilenameMatcher(a),r=captureOriginalCode(e),instrumentByModuleAndFile(e,a,n),writeDebugOutputIfChanged(e,t,a,r))}},post:function(e){var t;!0===reactOptions.debugBabelPlugin&&!0===this.get("fileDidChange")&&(t=(0,generator_1.default)(e.ast).code,e=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),e.opts.filename)+".dtx.downstream"),fs.mkdirSync(fspath.dirname(e),{recursive:!0}),fs.writeFileSync(e,t))}}};
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RootWrapper = exports.wrapProvider = exports.notifyPress = void 0;
|
|
3
|
+
exports.RootWrapper = exports.wrapProvider = exports.notifyPress = exports.UserInteractionEventKey = void 0;
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const react_native_1 = require("react-native");
|
|
6
|
-
const ConfigurationHandler_1 = require("../../lib/core/configuration/ConfigurationHandler");
|
|
7
6
|
const EventPipeline_1 = require("../../lib/next/events/EventPipeline");
|
|
8
7
|
const EventTimestamp_1 = require("../../lib/next/events/EventTimestamp");
|
|
9
8
|
const TimestampProvider_1 = require("../../lib/next/provider/TimestampProvider");
|
|
9
|
+
const ConfigurationHandler_1 = require("../../lib/core/configuration/ConfigurationHandler");
|
|
10
|
+
var UserInteractionEventKey;
|
|
11
|
+
(function (UserInteractionEventKey) {
|
|
12
|
+
UserInteractionEventKey["EventHasUserInteraction"] = "characteristics.has_user_interaction";
|
|
13
|
+
UserInteractionEventKey["UiElementDetectedName"] = "ui_element.detected_name";
|
|
14
|
+
UserInteractionEventKey["UiElementComponents"] = "ui_element.components";
|
|
15
|
+
UserInteractionEventKey["UiElementId"] = "ui_element.id";
|
|
16
|
+
UserInteractionEventKey["UiElementNameOrigin"] = "ui_element.name_origin";
|
|
17
|
+
UserInteractionEventKey["InteractionType"] = "interaction.type";
|
|
18
|
+
UserInteractionEventKey["UiElementResponderDetectedName"] = "ui_element.responder.detected_name";
|
|
19
|
+
UserInteractionEventKey["UiElementResponderComponents"] = "ui_element.responder.components";
|
|
20
|
+
UserInteractionEventKey["UiElementResponderOriginName"] = "ui_element.responder.name_origin";
|
|
21
|
+
UserInteractionEventKey["UiElementResponderId"] = "ui_element.responder.id";
|
|
22
|
+
})(UserInteractionEventKey = exports.UserInteractionEventKey || (exports.UserInteractionEventKey = {}));
|
|
10
23
|
const TOUCH_FLUSH_DELAY = 250;
|
|
11
24
|
let pendingTouch = null;
|
|
12
25
|
const getFiberPath = (fiber) => {
|
|
@@ -43,7 +56,7 @@ function findRCTTextChild(fiber) {
|
|
|
43
56
|
return null;
|
|
44
57
|
}
|
|
45
58
|
const getHostComponentInfo = (event) => {
|
|
46
|
-
var _a, _b;
|
|
59
|
+
var _a, _b, _c, _d, _e;
|
|
47
60
|
let fiber = event._targetInst;
|
|
48
61
|
if (!fiber) {
|
|
49
62
|
console.warn('Assumption violated: _targetInst not found');
|
|
@@ -64,7 +77,7 @@ const getHostComponentInfo = (event) => {
|
|
|
64
77
|
let detectedName;
|
|
65
78
|
if (fiber.type !== 'RCTText') {
|
|
66
79
|
nameOrigin = 'component';
|
|
67
|
-
detectedName = (_b = fiber.memoizedProps.accessibilityLabel) !== null &&
|
|
80
|
+
detectedName = (_c = (_b = fiber.memoizedProps) === null || _b === void 0 ? void 0 : _b.accessibilityLabel) !== null && _c !== void 0 ? _c : leaf;
|
|
68
81
|
}
|
|
69
82
|
else if (anyParentMasked) {
|
|
70
83
|
nameOrigin = 'masked';
|
|
@@ -72,7 +85,7 @@ const getHostComponentInfo = (event) => {
|
|
|
72
85
|
}
|
|
73
86
|
else {
|
|
74
87
|
nameOrigin = 'text';
|
|
75
|
-
detectedName = flatten(fiber.memoizedProps.children);
|
|
88
|
+
detectedName = flatten((_e = (_d = fiber.memoizedProps) === null || _d === void 0 ? void 0 : _d.children) !== null && _e !== void 0 ? _e : '');
|
|
76
89
|
}
|
|
77
90
|
return { id, components, detectedName, nameOrigin };
|
|
78
91
|
};
|
|
@@ -92,8 +105,9 @@ const flushTouch = (responderComponentInfo) => {
|
|
|
92
105
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
93
106
|
};
|
|
94
107
|
const onTouch = (e) => {
|
|
95
|
-
if (!ConfigurationHandler_1.ConfigurationHandler.
|
|
108
|
+
if (!ConfigurationHandler_1.ConfigurationHandler.getThirdGenDataReportingDecision().allowed) {
|
|
96
109
|
return;
|
|
110
|
+
}
|
|
97
111
|
flushTouch();
|
|
98
112
|
const touchedComponentInfo = getHostComponentInfo(e);
|
|
99
113
|
if (!touchedComponentInfo)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SectionList = exports.FlatList = exports.useTableReloadOnChange = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
const TableReloadTracker_1 = require("../../../lib/next/triggers/TableReloadTracker");
|
|
7
|
+
const ConsoleLogger_1 = require("../../../lib/core/logging/ConsoleLogger");
|
|
8
|
+
const LogMessages_1 = require("../../../lib/core/logging/LogMessages");
|
|
9
|
+
const DEBOUNCE_MS = 100;
|
|
10
|
+
const logger = new ConsoleLogger_1.ConsoleLogger('TableReload');
|
|
11
|
+
const _useIsFocused = (() => {
|
|
12
|
+
try {
|
|
13
|
+
return require('@react-navigation/native').useIsFocused;
|
|
14
|
+
}
|
|
15
|
+
catch (_a) {
|
|
16
|
+
return () => true;
|
|
17
|
+
}
|
|
18
|
+
})();
|
|
19
|
+
function useTableReloadOnChange(value, label) {
|
|
20
|
+
const isFocused = _useIsFocused();
|
|
21
|
+
const isFocusedRef = React.useRef(isFocused);
|
|
22
|
+
const isMounted = React.useRef(false);
|
|
23
|
+
const pendingReload = React.useRef(false);
|
|
24
|
+
const timer = React.useRef(null);
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
isFocusedRef.current = isFocused;
|
|
27
|
+
}, [isFocused]);
|
|
28
|
+
const fireAfterDebounce = React.useCallback(() => {
|
|
29
|
+
if (timer.current !== null)
|
|
30
|
+
clearTimeout(timer.current);
|
|
31
|
+
timer.current = setTimeout(() => {
|
|
32
|
+
timer.current = null;
|
|
33
|
+
if (!isFocusedRef.current) {
|
|
34
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_DEBOUNCE_LOST_FOCUS, {
|
|
35
|
+
label,
|
|
36
|
+
});
|
|
37
|
+
pendingReload.current = true;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_DEBOUNCE_ELAPSED, { label });
|
|
41
|
+
(0, TableReloadTracker_1.callTableReloadTrigger)(Date.now());
|
|
42
|
+
}, DEBOUNCE_MS);
|
|
43
|
+
}, [label]);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (!isMounted.current) {
|
|
46
|
+
isMounted.current = true;
|
|
47
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_MOUNTED, {
|
|
48
|
+
label,
|
|
49
|
+
length: Array.isArray(value) ? String(value.length) : 'null',
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const length = Array.isArray(value) ? String(value.length) : 'null';
|
|
54
|
+
if (!isFocused) {
|
|
55
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_DATA_CHANGED_NOT_FOCUSED, {
|
|
56
|
+
label,
|
|
57
|
+
length,
|
|
58
|
+
});
|
|
59
|
+
pendingReload.current = true;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_DATA_CHANGED, { label, length });
|
|
63
|
+
pendingReload.current = false;
|
|
64
|
+
fireAfterDebounce();
|
|
65
|
+
return () => {
|
|
66
|
+
if (timer.current !== null) {
|
|
67
|
+
clearTimeout(timer.current);
|
|
68
|
+
timer.current = null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}, [value]);
|
|
72
|
+
React.useEffect(() => {
|
|
73
|
+
if (!isFocused || !pendingReload.current)
|
|
74
|
+
return;
|
|
75
|
+
pendingReload.current = false;
|
|
76
|
+
logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_FOCUS_RESTORED, { label });
|
|
77
|
+
fireAfterDebounce();
|
|
78
|
+
return () => {
|
|
79
|
+
if (timer.current !== null) {
|
|
80
|
+
clearTimeout(timer.current);
|
|
81
|
+
timer.current = null;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}, [isFocused, fireAfterDebounce, label]);
|
|
85
|
+
}
|
|
86
|
+
exports.useTableReloadOnChange = useTableReloadOnChange;
|
|
87
|
+
exports.FlatList = React.forwardRef(function DynatraceFlatList(props, ref) {
|
|
88
|
+
useTableReloadOnChange(props.data, 'FlatList');
|
|
89
|
+
return React.createElement(react_native_1.FlatList, Object.assign({ ref: ref }, props));
|
|
90
|
+
});
|
|
91
|
+
exports.SectionList = React.forwardRef(function DynatraceSectionList(props, ref) {
|
|
92
|
+
useTableReloadOnChange(props.sections, 'SectionList');
|
|
93
|
+
return React.createElement(react_native_1.SectionList, Object.assign({ ref: ref }, props));
|
|
94
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Switch = exports.Pressable = exports.Text = exports.Button = exports.TouchableWithoutFeedback = exports.TouchableOpacity = exports.TouchableNativeFeedback = exports.TouchableHighlight = exports.RefreshControl = void 0;
|
|
3
|
+
exports.SectionList = exports.FlatList = exports.Switch = exports.Pressable = exports.Text = exports.Button = exports.TouchableWithoutFeedback = exports.TouchableOpacity = exports.TouchableNativeFeedback = exports.TouchableHighlight = exports.RefreshControl = void 0;
|
|
4
4
|
var RefreshControl_1 = require("./RefreshControl");
|
|
5
5
|
Object.defineProperty(exports, "RefreshControl", { enumerable: true, get: function () { return RefreshControl_1.RefreshControl; } });
|
|
6
6
|
var Touchables_1 = require("./Touchables");
|
|
@@ -13,3 +13,6 @@ Object.defineProperty(exports, "Text", { enumerable: true, get: function () { re
|
|
|
13
13
|
Object.defineProperty(exports, "Pressable", { enumerable: true, get: function () { return Touchables_1.Pressable; } });
|
|
14
14
|
var Switch_1 = require("./Switch");
|
|
15
15
|
Object.defineProperty(exports, "Switch", { enumerable: true, get: function () { return Switch_1.Switch; } });
|
|
16
|
+
var Lists_1 = require("./Lists");
|
|
17
|
+
Object.defineProperty(exports, "FlatList", { enumerable: true, get: function () { return Lists_1.FlatList; } });
|
|
18
|
+
Object.defineProperty(exports, "SectionList", { enumerable: true, get: function () { return Lists_1.SectionList; } });
|
|
@@ -5,6 +5,7 @@ const reactNative = require("react-native");
|
|
|
5
5
|
const Touchables_1 = require("./react-native/Touchables");
|
|
6
6
|
const RefreshControl_1 = require("./react-native/RefreshControl");
|
|
7
7
|
const Switch_1 = require("./react-native/Switch");
|
|
8
|
+
const Lists_1 = require("./react-native/Lists");
|
|
8
9
|
const dynatraceInstrument = {
|
|
9
10
|
TouchableHighlight: Touchables_1.TouchableHighlight,
|
|
10
11
|
TouchableNativeFeedback: Touchables_1.TouchableNativeFeedback,
|
|
@@ -15,6 +16,8 @@ const dynatraceInstrument = {
|
|
|
15
16
|
Text: Touchables_1.Text,
|
|
16
17
|
Pressable: Touchables_1.Pressable,
|
|
17
18
|
Switch: Switch_1.Switch,
|
|
19
|
+
FlatList: Lists_1.FlatList,
|
|
20
|
+
SectionList: Lists_1.SectionList,
|
|
18
21
|
};
|
|
19
22
|
const dynatraceProxy = new Proxy(reactNative, {
|
|
20
23
|
get: (target, property) => {
|
|
@@ -1,74 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.useNavigationMonitor = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const react_native_1 = require("react-native");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const DynatraceBridge_1 = require("../../../lib/core/DynatraceBridge");
|
|
9
|
-
const BaseDataEventModifier_1 = require("../../../lib/next/events/modifier/BaseDataEventModifier");
|
|
10
|
-
const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
|
|
11
|
-
const logger = new ConsoleLogger_1.ConsoleLogger('ReactNavigation');
|
|
12
|
-
let activePath = '';
|
|
13
|
-
let appState = react_native_1.AppState.currentState;
|
|
14
|
-
const monitorNavigation = (getRootState) => {
|
|
6
|
+
const NavigationTracker_1 = require("../../../lib/next/navigation/NavigationTracker");
|
|
7
|
+
const useNavigationMonitor = (getRootState) => {
|
|
15
8
|
(0, react_1.useEffect)(() => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let newPath = '';
|
|
19
|
-
while (currentState === null || currentState === void 0 ? void 0 : currentState.routes[(_a = currentState.index) !== null && _a !== void 0 ? _a : 0]) {
|
|
20
|
-
const currentRoute = currentState === null || currentState === void 0 ? void 0 : currentState.routes[(_b = currentState.index) !== null && _b !== void 0 ? _b : 0];
|
|
21
|
-
newPath += `/${currentRoute.name}`;
|
|
22
|
-
currentState = currentRoute.state;
|
|
23
|
-
}
|
|
24
|
-
if (newPath !== activePath) {
|
|
25
|
-
if (activePath !== '') {
|
|
26
|
-
stopView();
|
|
27
|
-
}
|
|
28
|
-
startView(newPath);
|
|
29
|
-
activePath = newPath;
|
|
30
|
-
}
|
|
9
|
+
const newPath = (0, NavigationTracker_1.buildPathFromState)(getRootState());
|
|
10
|
+
(0, NavigationTracker_1.reportScreenChange)(newPath);
|
|
31
11
|
});
|
|
12
|
+
const appStateRef = (0, react_1.useRef)(react_native_1.AppState.currentState);
|
|
32
13
|
(0, react_1.useEffect)(() => {
|
|
33
14
|
const subscription = react_native_1.AppState.addEventListener('change', (nextAppState) => {
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
const prevAppState = appStateRef.current;
|
|
16
|
+
appStateRef.current = nextAppState;
|
|
17
|
+
if (nextAppState !== 'active' && prevAppState === 'active') {
|
|
18
|
+
(0, NavigationTracker_1.reportScreenBackground)();
|
|
36
19
|
}
|
|
37
|
-
else if (nextAppState === 'active' &&
|
|
38
|
-
|
|
20
|
+
else if (nextAppState === 'active' &&
|
|
21
|
+
prevAppState !== 'active') {
|
|
22
|
+
(0, NavigationTracker_1.reportScreenResume)();
|
|
39
23
|
}
|
|
40
|
-
appState = nextAppState;
|
|
41
24
|
});
|
|
42
25
|
return () => {
|
|
43
26
|
subscription.remove();
|
|
44
27
|
};
|
|
45
28
|
}, []);
|
|
46
29
|
};
|
|
47
|
-
exports.
|
|
48
|
-
const startView = (newPath) => {
|
|
49
|
-
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
50
|
-
logger.info(LogMessages_1.LogMessage.NAVIGATION_NOT_STARTED);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const startViewInternalEvent = new BaseDataEventModifier_1.BaseDataEventModifier().modifyEvent(Object.assign({ 'view.detected_name': newPath }, (activePath && {
|
|
54
|
-
'view.source.detected_name': activePath,
|
|
55
|
-
})));
|
|
56
|
-
const fn = DynatraceBridge_1.DynatraceNative === null || DynatraceBridge_1.DynatraceNative === void 0 ? void 0 : DynatraceBridge_1.DynatraceNative.startViewInternal;
|
|
57
|
-
if (typeof fn === 'function') {
|
|
58
|
-
fn(startViewInternalEvent);
|
|
59
|
-
}
|
|
60
|
-
logger.debug(LogMessages_1.LogMessage.START_VIEW_INTERNAL, {
|
|
61
|
-
event: JSON.stringify(startViewInternalEvent),
|
|
62
|
-
});
|
|
63
|
-
};
|
|
64
|
-
const stopView = () => {
|
|
65
|
-
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
66
|
-
logger.info(LogMessages_1.LogMessage.NAVIGATION_NOT_STARTED);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const fn = DynatraceBridge_1.DynatraceNative === null || DynatraceBridge_1.DynatraceNative === void 0 ? void 0 : DynatraceBridge_1.DynatraceNative.stopViewInternal;
|
|
70
|
-
if (typeof fn === 'function') {
|
|
71
|
-
fn();
|
|
72
|
-
}
|
|
73
|
-
logger.debug(LogMessages_1.LogMessage.STOP_VIEW_INTERNAL);
|
|
74
|
-
};
|
|
30
|
+
exports.useNavigationMonitor = useNavigationMonitor;
|
|
@@ -15,68 +15,18 @@ function withOnPressMonitoring(Component, fallbackName) {
|
|
|
15
15
|
const { onPress, onLongPress } = props;
|
|
16
16
|
const touchableName = (0, exports.chooseTouchableName)(props, fallbackName);
|
|
17
17
|
const dynatraceIgnored = (0, ComponentUtil_1.isDynatraceIgnored)(props);
|
|
18
|
-
const isRNButton = 'title' in props && typeof props.title === 'string';
|
|
19
|
-
const isRectButton = fallbackName === 'Button';
|
|
20
|
-
const isButtonLike = isRNButton || isRectButton;
|
|
21
|
-
const buttonLabel = isRNButton ? String(props.title) : null;
|
|
22
18
|
const propsWithoutRef = Object.assign(Object.assign(Object.assign({}, props), (!dynatraceIgnored &&
|
|
23
19
|
onPress && {
|
|
24
|
-
onPress: (0, exports.wrapOnPress)(onPress, touchableName
|
|
20
|
+
onPress: (0, exports.wrapOnPress)(onPress, touchableName),
|
|
25
21
|
})), (!dynatraceIgnored &&
|
|
26
22
|
onLongPress && {
|
|
27
|
-
onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName
|
|
23
|
+
onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName),
|
|
28
24
|
}));
|
|
29
25
|
const propsWithRef = Object.assign(Object.assign({}, propsWithoutRef), { ref });
|
|
30
26
|
return React.createElement(Component, Object.assign({}, propsWithRef));
|
|
31
27
|
});
|
|
32
28
|
}
|
|
33
29
|
exports.withOnPressMonitoring = withOnPressMonitoring;
|
|
34
|
-
const dtGetUiBridge = () => {
|
|
35
|
-
var _a;
|
|
36
|
-
const g = globalThis;
|
|
37
|
-
return (_a = g === null || g === void 0 ? void 0 : g.__DT_UII_BRIDGE) !== null && _a !== void 0 ? _a : null;
|
|
38
|
-
};
|
|
39
|
-
const dtBuildPressPath = (startPath, touchableName) => {
|
|
40
|
-
var _a;
|
|
41
|
-
const base = (_a = startPath === null || startPath === void 0 ? void 0 : startPath.toString()) !== null && _a !== void 0 ? _a : '';
|
|
42
|
-
if (!base)
|
|
43
|
-
return `Touchable(${touchableName})`;
|
|
44
|
-
const cut1 = base.lastIndexOf('/Text');
|
|
45
|
-
const cut2 = base.lastIndexOf('/Text(');
|
|
46
|
-
const cut = Math.max(cut1, cut2);
|
|
47
|
-
const parent = cut > 0 ? base.slice(0, cut) : base;
|
|
48
|
-
return parent + `/Touchable(${touchableName})`;
|
|
49
|
-
};
|
|
50
|
-
const registerPressOnBridge = (args, touchableName, isButtonLike, buttonLabel) => {
|
|
51
|
-
const bridge = dtGetUiBridge();
|
|
52
|
-
if (!bridge || typeof bridge.registerPress !== 'function') {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
const e = args === null || args === void 0 ? void 0 : args[0];
|
|
57
|
-
const ne = e === null || e === void 0 ? void 0 : e.nativeEvent;
|
|
58
|
-
const x = Number(ne === null || ne === void 0 ? void 0 : ne.pageX);
|
|
59
|
-
const y = Number(ne === null || ne === void 0 ? void 0 : ne.pageY);
|
|
60
|
-
const pos = Number.isFinite(x) && Number.isFinite(y) ? { x, y } : undefined;
|
|
61
|
-
const startPath = typeof bridge.getStartPath === 'function'
|
|
62
|
-
? bridge.getStartPath()
|
|
63
|
-
: null;
|
|
64
|
-
const nameForBridge = isButtonLike
|
|
65
|
-
? buttonLabel || touchableName
|
|
66
|
-
: touchableName;
|
|
67
|
-
bridge.registerPress({
|
|
68
|
-
path: dtBuildPressPath(startPath, nameForBridge),
|
|
69
|
-
elementName: nameForBridge,
|
|
70
|
-
pos,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
75
|
-
Logger.debug(LogMessages_1.LogMessage.REGISTER_PRESS_HOOK_FAILED, {
|
|
76
|
-
errorMsg,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
30
|
const notifyPressFromEvent = (args) => {
|
|
81
31
|
if (args[0] && typeof args[0] === 'object' && 'nativeEvent' in args[0]) {
|
|
82
32
|
(0, UserInteraction_1.notifyPress)(args[0]);
|
|
@@ -104,9 +54,8 @@ const invokeOnPressWithAction = (onPress, args, touchableName) => {
|
|
|
104
54
|
}
|
|
105
55
|
}
|
|
106
56
|
};
|
|
107
|
-
const wrapOnPress = (onPress, touchableName
|
|
57
|
+
const wrapOnPress = (onPress, touchableName) => {
|
|
108
58
|
return (...args) => {
|
|
109
|
-
registerPressOnBridge(args, touchableName, isButtonLike, buttonLabel);
|
|
110
59
|
notifyPressFromEvent(args);
|
|
111
60
|
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
112
61
|
invokeOnPressWithoutConfiguration(onPress, args);
|
package/internal.d.ts
ADDED
package/internal.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createElement = exports.ApplicationHandler = void 0;
|
|
3
|
+
exports.registerTableReloadTrigger = exports.registerNavigationEventTrigger = exports.createElement = exports.ApplicationHandler = void 0;
|
|
4
4
|
var Application_1 = require("./lib/core/Application");
|
|
5
5
|
Object.defineProperty(exports, "ApplicationHandler", { enumerable: true, get: function () { return Application_1.ApplicationHandler; } });
|
|
6
6
|
var CreateElement_1 = require("./instrumentation/jsx/CreateElement");
|
|
7
7
|
Object.defineProperty(exports, "createElement", { enumerable: true, get: function () { return CreateElement_1.createElement; } });
|
|
8
|
+
var NavigationTracker_1 = require("./lib/next/navigation/NavigationTracker");
|
|
9
|
+
Object.defineProperty(exports, "registerNavigationEventTrigger", { enumerable: true, get: function () { return NavigationTracker_1.registerNavigationEventTrigger; } });
|
|
10
|
+
var TableReloadTracker_1 = require("./lib/next/triggers/TableReloadTracker");
|
|
11
|
+
Object.defineProperty(exports, "registerTableReloadTrigger", { enumerable: true, get: function () { return TableReloadTracker_1.registerTableReloadTrigger; } });
|