@scalebun-release/react-native 2.5.0
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/LICENSE +21 -0
- package/README.md +154 -0
- package/android/build.gradle +94 -0
- package/android/consumer-rules.pro +28 -0
- package/android/src/androidTest/java/com/scalebun/rn/ota/ScaleBunOtaVerifierInstrumentedTest.kt +112 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/java/com/scalebun/core/crash/CrashStorage.kt +155 -0
- package/android/src/main/java/com/scalebun/core/crash/NativeCrashHandler.kt +93 -0
- package/android/src/main/java/com/scalebun/core/performance/ANRWatchdog.kt +100 -0
- package/android/src/main/java/com/scalebun/core/performance/AppStartCollector.kt +180 -0
- package/android/src/main/java/com/scalebun/core/performance/FrameMetricsCollector.kt +230 -0
- package/android/src/main/java/com/scalebun/core/performance/PerformanceCore.kt +165 -0
- package/android/src/main/java/com/scalebun/profiler/ProfilerModule.kt +398 -0
- package/android/src/main/java/com/scalebun/profiler/ProfilerPackage.kt +24 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/CpuCollector.kt +161 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/IncidentDetector.kt +223 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/MemoryCollector.kt +157 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/RenderCollector.kt +194 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/SamplerScheduler.kt +218 -0
- package/android/src/main/java/com/scalebun/profiler/collectors/ThreadCollector.kt +142 -0
- package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkModule.kt +1117 -0
- package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkPackage.kt +24 -0
- package/android/src/main/java/com/scalebun/replaysdk/capture/CaptureReason.kt +47 -0
- package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureManager.kt +574 -0
- package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureScheduler.kt +187 -0
- package/android/src/main/java/com/scalebun/replaysdk/capture/UiStabilityDetector.kt +214 -0
- package/android/src/main/java/com/scalebun/replaysdk/core/ReplayConfig.kt +144 -0
- package/android/src/main/java/com/scalebun/replaysdk/core/ReplayLogger.kt +31 -0
- package/android/src/main/java/com/scalebun/replaysdk/core/SessionIdGenerator.kt +15 -0
- package/android/src/main/java/com/scalebun/replaysdk/models/ReplayModels.kt +94 -0
- package/android/src/main/java/com/scalebun/replaysdk/outbox/NativeOutbox.kt +574 -0
- package/android/src/main/java/com/scalebun/replaysdk/outbox/OutboxUploader.kt +559 -0
- package/android/src/main/java/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.kt +126 -0
- package/android/src/main/java/com/scalebun/replaysdk/session/SessionManager.kt +322 -0
- package/android/src/main/java/com/scalebun/replaysdk/storage/ReplayStorage.kt +136 -0
- package/android/src/main/java/com/scalebun/replaysdk/timeline/TimelineCollector.kt +28 -0
- package/android/src/main/java/com/scalebun/replaysdk/tracking/InteractionTracker.kt +470 -0
- package/android/src/main/java/com/scalebun/replaysdk/tracking/ScreenTracker.kt +20 -0
- package/android/src/main/java/com/scalebun/replaysdk/tracking/ScrollContextProbe.kt +188 -0
- package/android/src/main/java/com/scalebun/replaysdk/transport/ReplayTransport.kt +99 -0
- package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceRecorder.kt +121 -0
- package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceTranscriber.kt +170 -0
- package/android/src/main/java/com/scalebun/rn/ScaleBunPackage.kt +113 -0
- package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashModule.kt +188 -0
- package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashPackage.kt +22 -0
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngageModule.kt +579 -0
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngagePackage.kt +22 -0
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunNotificationPresenter.kt +110 -0
- package/android/src/main/java/com/scalebun/rn/ota/BsPatch.kt +240 -0
- package/android/src/main/java/com/scalebun/rn/ota/BundleDownloader.kt +195 -0
- package/android/src/main/java/com/scalebun/rn/ota/DeviceIntegrity.kt +81 -0
- package/android/src/main/java/com/scalebun/rn/ota/DownloadFailure.kt +55 -0
- package/android/src/main/java/com/scalebun/rn/ota/OtaProtocol.kt +244 -0
- package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaKeyRegistry.kt +100 -0
- package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaModule.kt +683 -0
- package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaReleaseVerifier.kt +136 -0
- package/android/src/main/java/com/scalebun/rn/ota/SlotManager.kt +578 -0
- package/android/src/main/java/com/scalebun/rn/ota/TlsPinning.kt +118 -0
- package/android/src/main/java/com/scalebun/rn/performance/PerformanceModule.kt +217 -0
- package/android/src/main/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.kt +77 -0
- package/android/src/main/java/com/scalebun/rn/storage/ScaleBunStorageModule.kt +68 -0
- package/android/src/main/java/com/scalebun/storage/KvFileStore.kt +174 -0
- package/android/src/newarch/java/com/scalebun/profiler/ProfilerSpec.kt +12 -0
- package/android/src/newarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +12 -0
- package/android/src/newarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +15 -0
- package/android/src/newarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +16 -0
- package/android/src/newarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +12 -0
- package/android/src/newarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +14 -0
- package/android/src/newarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +16 -0
- package/android/src/oldarch/java/com/scalebun/profiler/ProfilerSpec.kt +34 -0
- package/android/src/oldarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +77 -0
- package/android/src/oldarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +40 -0
- package/android/src/oldarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +42 -0
- package/android/src/oldarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +27 -0
- package/android/src/oldarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +18 -0
- package/android/src/oldarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +26 -0
- package/bin/lib/androidCodemod.js +370 -0
- package/bin/lib/iosCodemod.js +343 -0
- package/bin/scalebun.js +1004 -0
- package/dist/scalebun.full.js +37348 -0
- package/dist/scalebun.slim.js +34137 -0
- package/ios/Capture/InteractionTracker.swift +237 -0
- package/ios/Capture/PrivacyMaskProcessor.swift +158 -0
- package/ios/Capture/ScreenshotCaptureManager.swift +398 -0
- package/ios/Capture/WindowResolver.swift +63 -0
- package/ios/Core/DeviceIdentity.swift +50 -0
- package/ios/Core/ReplayConfig.swift +100 -0
- package/ios/Core/ReplayLogger.swift +22 -0
- package/ios/Core/SessionIdGenerator.swift +18 -0
- package/ios/Crash/ScaleBunCrashBridge.mm +74 -0
- package/ios/Crash/ScaleBunCrashHandler.swift +84 -0
- package/ios/Crash/ScaleBunCrashModule.swift +98 -0
- package/ios/Crash/ScaleBunCrashSignalBridge.h +49 -0
- package/ios/Crash/ScaleBunCrashSignalBridge.m +296 -0
- package/ios/Crash/ScaleBunCrashSignalStress.c +137 -0
- package/ios/Crash/ScaleBunCrashStorage.swift +121 -0
- package/ios/Crash/ScaleBunExceptionChain.swift +71 -0
- package/ios/CrashTests/ScaleBunExceptionChainTests.swift +144 -0
- package/ios/Engage/ScaleBunEngageBridge.m +32 -0
- package/ios/Engage/ScaleBunEngageModule.swift +250 -0
- package/ios/Engage/ScaleBunPushNotificationCenter.swift +185 -0
- package/ios/Ota/BsPatch.swift +203 -0
- package/ios/Ota/BundleDownloader.swift +249 -0
- package/ios/Ota/DeviceIntegrity.swift +112 -0
- package/ios/Ota/DownloadFailure.swift +56 -0
- package/ios/Ota/OtaProtocol.swift +246 -0
- package/ios/Ota/OtaSlotManager.swift +613 -0
- package/ios/Ota/ScaleBunOtaBridge.mm +92 -0
- package/ios/Ota/ScaleBunOtaEventsModule.swift +61 -0
- package/ios/Ota/ScaleBunOtaKeyRegistry.swift +147 -0
- package/ios/Ota/ScaleBunOtaModule.swift +587 -0
- package/ios/Ota/ScaleBunOtaReleaseVerifier.swift +119 -0
- package/ios/Ota/TlsPinning.swift +222 -0
- package/ios/OtaTests/DownloadFailureTests.swift +78 -0
- package/ios/OtaTests/ScaleBunOtaVerifierTests.swift +548 -0
- package/ios/Outbox/NativeOutbox.swift +632 -0
- package/ios/Outbox/OutboxUploader.swift +578 -0
- package/ios/Performance/ScaleBunPerformanceBridge.m +32 -0
- package/ios/Performance/ScaleBunPerformanceModule.swift +290 -0
- package/ios/PrivacyInfo.xcprivacy +97 -0
- package/ios/Profiler/ScaleBunProfilerBridge.m +55 -0
- package/ios/Profiler/ScaleBunProfilerModule.swift +966 -0
- package/ios/ReplaySdk-Bridging-Header.h +2 -0
- package/ios/ReplaySdk.swift +793 -0
- package/ios/ReplaySdkBridge.m +97 -0
- package/ios/Session/SessionManager.swift +273 -0
- package/ios/Skan/ScaleBunSkanBridge.m +14 -0
- package/ios/Skan/ScaleBunSkanModule.swift +61 -0
- package/ios/Storage/ReplayStorage.swift +61 -0
- package/ios/Storage/ScaleBunKvFileStore.swift +125 -0
- package/ios/Storage/ScaleBunStorageBridge.mm +72 -0
- package/ios/Storage/ScaleBunStorageModule.swift +57 -0
- package/ios/Transport/ReplayTransport.swift +70 -0
- package/ios/VoiceRecorder.swift +145 -0
- package/lib/commonjs/analytics/EventTracker.js +598 -0
- package/lib/commonjs/analytics/automaticEvents.js +71 -0
- package/lib/commonjs/analytics/batching.js +64 -0
- package/lib/commonjs/analytics/eventLane.js +55 -0
- package/lib/commonjs/analytics/revenue.js +125 -0
- package/lib/commonjs/analytics/subscription.js +94 -0
- package/lib/commonjs/bootstrap/FeatureRegistry.js +86 -0
- package/lib/commonjs/bootstrap/SDKBootstrapper.js +748 -0
- package/lib/commonjs/bucketing/fnv1a32.js +45 -0
- package/lib/commonjs/compat/codepush.js +153 -0
- package/lib/commonjs/config/ConfigManager.js +238 -0
- package/lib/commonjs/config/configTypes.js +16 -0
- package/lib/commonjs/config/otaPolicyState.js +85 -0
- package/lib/commonjs/config/quotaState.js +435 -0
- package/lib/commonjs/core/architecture.js +45 -0
- package/lib/commonjs/core/clock/now.js +13 -0
- package/lib/commonjs/core/config/defaults.js +2 -0
- package/lib/commonjs/core/config/schema.js +512 -0
- package/lib/commonjs/core/constants/endpoints.js +19 -0
- package/lib/commonjs/core/constants/protocol.js +31 -0
- package/lib/commonjs/core/constants/timings.js +39 -0
- package/lib/commonjs/core/constants/version.js +18 -0
- package/lib/commonjs/core/context/app.js +2 -0
- package/lib/commonjs/core/context/device.js +155 -0
- package/lib/commonjs/core/context/session.js +2 -0
- package/lib/commonjs/core/context/user.js +2 -0
- package/lib/commonjs/core/contracts/IFeature.js +2 -0
- package/lib/commonjs/core/di/container.js +29 -0
- package/lib/commonjs/core/encoding/base64.js +50 -0
- package/lib/commonjs/core/id/deviceId.js +52 -0
- package/lib/commonjs/core/id/installationId.js +55 -0
- package/lib/commonjs/core/id/sessionId.js +2 -0
- package/lib/commonjs/core/lifecycle/appLifecycle.js +31 -0
- package/lib/commonjs/core/lifecycle/crashSafe.js +33 -0
- package/lib/commonjs/core/logger/errorClassification.js +107 -0
- package/lib/commonjs/core/logger/internalLogger.js +63 -0
- package/lib/commonjs/core/logger/levels.js +2 -0
- package/lib/commonjs/crypto/hmacSha256.js +132 -0
- package/lib/commonjs/debug/bootstrap.js +429 -0
- package/lib/commonjs/debug/commands.js +732 -0
- package/lib/commonjs/debug/configBuilder.js +70 -0
- package/lib/commonjs/debug/exportBridge.js +155 -0
- package/lib/commonjs/debug/hostResolver.js +42 -0
- package/lib/commonjs/debug/index.js +141 -0
- package/lib/commonjs/debug/metrics.js +39 -0
- package/lib/commonjs/debug/perf.js +186 -0
- package/lib/commonjs/debug/perfWiring.js +109 -0
- package/lib/commonjs/debug/protocol.js +121 -0
- package/lib/commonjs/debug/redaction.js +422 -0
- package/lib/commonjs/debug/replayWiring.js +149 -0
- package/lib/commonjs/debug/screenTracking.js +60 -0
- package/lib/commonjs/debug/sessionWiring.js +48 -0
- package/lib/commonjs/debug/stream.js +542 -0
- package/lib/commonjs/debug/transport.js +368 -0
- package/lib/commonjs/features/bugreport/BugReportFeature.js +112 -0
- package/lib/commonjs/features/bugreport/buildPayload.js +97 -0
- package/lib/commonjs/features/bugreport/index.js +2 -0
- package/lib/commonjs/features/crash/CrashFeature.js +86 -0
- package/lib/commonjs/features/crash/CrashReporter.js +160 -0
- package/lib/commonjs/features/crash/NativeCrashFeature.js +42 -0
- package/lib/commonjs/features/crash/capture.js +48 -0
- package/lib/commonjs/features/crash/globalHandler.js +41 -0
- package/lib/commonjs/features/crash/index.js +14 -0
- package/lib/commonjs/features/crash/nativeCrashBridge.js +361 -0
- package/lib/commonjs/features/crash/rejectionHandler.js +180 -0
- package/lib/commonjs/features/crash/scrubCrash.js +158 -0
- package/lib/commonjs/features/engage/EngageAnchor.js +132 -0
- package/lib/commonjs/features/engage/EngageArchetypeRenderers.js +4292 -0
- package/lib/commonjs/features/engage/EngageInAppView.js +2670 -0
- package/lib/commonjs/features/engage/EngageInlinePlacement.js +133 -0
- package/lib/commonjs/features/engage/EngagePromptProvider.js +1063 -0
- package/lib/commonjs/features/engage/EngagePromptView.js +1252 -0
- package/lib/commonjs/features/engage/EngageTransport.js +608 -0
- package/lib/commonjs/features/engage/EngageVariantContent.js +1778 -0
- package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js +54 -0
- package/lib/commonjs/features/engage/attachmentCapture.js +48 -0
- package/lib/commonjs/features/engage/captureVoiceAttachment.js +88 -0
- package/lib/commonjs/features/engage/engageCoachmarkTour.js +106 -0
- package/lib/commonjs/features/engage/engageGameLogic.js +308 -0
- package/lib/commonjs/features/engage/engageMediaSizing.js +60 -0
- package/lib/commonjs/features/engage/engageMultiStepSheet.js +43 -0
- package/lib/commonjs/features/engage/engageOutcome.js +118 -0
- package/lib/commonjs/features/engage/engagePushTokenBridge.js +72 -0
- package/lib/commonjs/features/engage/engageShakeBridge.js +62 -0
- package/lib/commonjs/features/engage/engageSignals.js +39 -0
- package/lib/commonjs/features/engage/engageStoreReviewBridge.js +49 -0
- package/lib/commonjs/features/engage/engageTestSeenStore.js +99 -0
- package/lib/commonjs/features/engage/engageThrottle.js +404 -0
- package/lib/commonjs/features/engage/engageTriggerEngine.js +365 -0
- package/lib/commonjs/features/engage/engageTypes.js +116 -0
- package/lib/commonjs/features/engage/engageVariantResolver.js +143 -0
- package/lib/commonjs/features/engage/engageWindowInsets.js +98 -0
- package/lib/commonjs/features/engage/gestureTriggerDetector.js +85 -0
- package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js +55 -0
- package/lib/commonjs/features/install-referrer/installReferrer.js +113 -0
- package/lib/commonjs/features/journey/ScaleBunDebugRoot.js +1038 -0
- package/lib/commonjs/features/journey/ScaleBunFlatList.js +39 -0
- package/lib/commonjs/features/journey/ScaleBunImpression.js +113 -0
- package/lib/commonjs/features/journey/ScaleBunScrollView.js +102 -0
- package/lib/commonjs/features/journey/ScaleBunSectionList.js +39 -0
- package/lib/commonjs/features/journey/autoInstrumentScroll.js +161 -0
- package/lib/commonjs/features/journey/calibrationContext.js +42 -0
- package/lib/commonjs/features/journey/gestureBuffer.js +63 -0
- package/lib/commonjs/features/journey/gestureDetector.js +176 -0
- package/lib/commonjs/features/journey/impression.js +93 -0
- package/lib/commonjs/features/journey/interactionProtocol.js +168 -0
- package/lib/commonjs/features/journey/journeyManager.js +466 -0
- package/lib/commonjs/features/journey/journeyTypes.js +55 -0
- package/lib/commonjs/features/journey/nativeScroll.js +85 -0
- package/lib/commonjs/features/journey/navDetector.js +161 -0
- package/lib/commonjs/features/journey/screenshotHelper.js +136 -0
- package/lib/commonjs/features/journey/scrollContext.js +154 -0
- package/lib/commonjs/features/journey/targetGeometry.js +185 -0
- package/lib/commonjs/features/journey/targetRegistry.js +53 -0
- package/lib/commonjs/features/journey/touchTarget.js +249 -0
- package/lib/commonjs/features/journey/uiState.js +188 -0
- package/lib/commonjs/features/navigation/AutoScreenDetector.js +607 -0
- package/lib/commonjs/features/network/NetworkFeature.js +216 -0
- package/lib/commonjs/features/network/index.js +23 -0
- package/lib/commonjs/features/network/thirdParty.js +151 -0
- package/lib/commonjs/features/ota/OtaEventEmitter.js +129 -0
- package/lib/commonjs/features/ota/OtaOrchestrator.js +1309 -0
- package/lib/commonjs/features/ota/OtaTypes.js +6 -0
- package/lib/commonjs/features/ota/deviceAttributes.js +48 -0
- package/lib/commonjs/features/ota/environment.js +172 -0
- package/lib/commonjs/features/ota/geoCountry.js +93 -0
- package/lib/commonjs/features/ota/retry.js +96 -0
- package/lib/commonjs/features/ota/signedDownload.js +187 -0
- package/lib/commonjs/features/ota/useOtaUpdate.js +106 -0
- package/lib/commonjs/features/performance/PerformanceFeature.js +649 -0
- package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js +122 -0
- package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js +232 -0
- package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js +99 -0
- package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js +184 -0
- package/lib/commonjs/features/performance/collectors/JsStallCollector.js +165 -0
- package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js +59 -0
- package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js +78 -0
- package/lib/commonjs/features/performance/collectors/UiHangCollector.js +78 -0
- package/lib/commonjs/features/performance/config.js +58 -0
- package/lib/commonjs/features/performance/getNativePerformanceModule.js +44 -0
- package/lib/commonjs/features/performance/index.js +58 -0
- package/lib/commonjs/features/performance/metrics/MetricsEngine.js +148 -0
- package/lib/commonjs/features/performance/models.js +48 -0
- package/lib/commonjs/features/performance/transport/PerformanceTransport.js +168 -0
- package/lib/commonjs/features/profiler/ProfilerFeature.js +600 -0
- package/lib/commonjs/features/profiler/config.js +151 -0
- package/lib/commonjs/features/profiler/contracts.js +62 -0
- package/lib/commonjs/features/profiler/index.js +40 -0
- package/lib/commonjs/features/profiler/models.js +112 -0
- package/lib/commonjs/features/profiler/transport/ProfilerTransport.js +94 -0
- package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js +203 -0
- package/lib/commonjs/features/replay/bridge/eventEmitter.js +128 -0
- package/lib/commonjs/features/replay/bridge/nativeModule.js +95 -0
- package/lib/commonjs/features/replay/bridge/nativeQuota.js +121 -0
- package/lib/commonjs/features/replay/core/clock/clock.js +47 -0
- package/lib/commonjs/features/replay/core/config/defaults.js +88 -0
- package/lib/commonjs/features/replay/core/config/validator.js +109 -0
- package/lib/commonjs/features/replay/core/env/environmentDetector.js +28 -0
- package/lib/commonjs/features/replay/core/errors/safeCall.js +42 -0
- package/lib/commonjs/features/replay/core/ids/sessionId.js +53 -0
- package/lib/commonjs/features/replay/core/logger/logger.js +36 -0
- package/lib/commonjs/features/replay/core/privacy/privacyTypes.js +34 -0
- package/lib/commonjs/features/replay/core/queue/boundedQueue.js +71 -0
- package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js +259 -0
- package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js +139 -0
- package/lib/commonjs/features/replay/integrations/network/networkAdapter.js +77 -0
- package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js +88 -0
- package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js +103 -0
- package/lib/commonjs/features/replay/pipeline/batching/batchManager.js +119 -0
- package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js +52 -0
- package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js +53 -0
- package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js +67 -0
- package/lib/commonjs/features/replay/public/api.js +336 -0
- package/lib/commonjs/features/replay/public/enums.js +85 -0
- package/lib/commonjs/features/replay/public/types.js +6 -0
- package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js +119 -0
- package/lib/commonjs/features/replay/replay/frames/frameModels.js +40 -0
- package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js +279 -0
- package/lib/commonjs/features/replay/replay/timeline/timelineModels.js +120 -0
- package/lib/commonjs/features/replay/transport/BackendReplayTransport.js +175 -0
- package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js +75 -0
- package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js +124 -0
- package/lib/commonjs/features/replay/transport/ReplayTransport.js +2 -0
- package/lib/commonjs/features/session/BackendSessionAdapter.js +1915 -0
- package/lib/commonjs/features/session/DesktopSessionTransport.js +124 -0
- package/lib/commonjs/features/session/JourneyEventPipeline.js +244 -0
- package/lib/commonjs/features/session/ReplayCaptureManager.js +1253 -0
- package/lib/commonjs/features/session/ScrollTracker.js +147 -0
- package/lib/commonjs/features/session/SessionManager.js +1448 -0
- package/lib/commonjs/features/session/SyncDecisionEngine.js +95 -0
- package/lib/commonjs/features/session/frameLink.js +36 -0
- package/lib/commonjs/features/session/frameScrollState.js +41 -0
- package/lib/commonjs/features/session/index.js +84 -0
- package/lib/commonjs/features/session/nativeCapture.js +53 -0
- package/lib/commonjs/features/session/outboxFrameCapture.js +83 -0
- package/lib/commonjs/features/session/sessionTypes.js +230 -0
- package/lib/commonjs/features/session/viewportPlausibility.js +143 -0
- package/lib/commonjs/features/skan/skanBridge.js +54 -0
- package/lib/commonjs/features/skan/skanConversionManager.js +134 -0
- package/lib/commonjs/index.js +267 -0
- package/lib/commonjs/integrations/fetch/fetchInterceptor.js +174 -0
- package/lib/commonjs/integrations/navigation/screenTracker.js +2 -0
- package/lib/commonjs/integrations/network/bodyCapture.js +336 -0
- package/lib/commonjs/integrations/xhr/xhrInterceptor.js +224 -0
- package/lib/commonjs/metro/composeSourceMap.js +105 -0
- package/lib/commonjs/metro/featureModules.js +131 -0
- package/lib/commonjs/metro/index.js +230 -0
- package/lib/commonjs/metro/optionalDependencyStub.js +6 -0
- package/lib/commonjs/metro/optionalModules.js +31 -0
- package/lib/commonjs/metro/serializerCompose.js +161 -0
- package/lib/commonjs/pipeline/dispatcher/dispatcher.js +28 -0
- package/lib/commonjs/pipeline/envelope/envelope.js +17 -0
- package/lib/commonjs/pipeline/envelope/serializer.js +14 -0
- package/lib/commonjs/pipeline/processors/dedupe.js +2 -0
- package/lib/commonjs/pipeline/processors/enrich.js +16 -0
- package/lib/commonjs/pipeline/processors/sampling.js +2 -0
- package/lib/commonjs/pipeline/processors/sanitize.js +28 -0
- package/lib/commonjs/pipeline/queue/flushQueue.js +107 -0
- package/lib/commonjs/pipeline/queue/memoryQueue.js +31 -0
- package/lib/commonjs/pipeline/queue/persistentQueue.js +342 -0
- package/lib/commonjs/pipeline/queue/queuePolicy.js +2 -0
- package/lib/commonjs/pipeline/scheduler/flushScheduler.js +45 -0
- package/lib/commonjs/pipeline/scheduler/retryPolicy.js +15 -0
- package/lib/commonjs/public/ScaleBunErrorBoundary.js +91 -0
- package/lib/commonjs/public/ScaleBunFacade.js +2044 -0
- package/lib/commonjs/public/ScaleBunProvider.js +62 -0
- package/lib/commonjs/public/typedTracker.js +79 -0
- package/lib/commonjs/public/types.js +6 -0
- package/lib/commonjs/push/PushManager.js +270 -0
- package/lib/commonjs/push/adapters/ManualAdapter.js +86 -0
- package/lib/commonjs/push/adapters/NativeBridgeAdapter.js +131 -0
- package/lib/commonjs/push/adapters/NoopAdapter.js +45 -0
- package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js +248 -0
- package/lib/commonjs/push/adapters/loadMessaging.js +29 -0
- package/lib/commonjs/push/adapters/loadNotifee.js +36 -0
- package/lib/commonjs/push/adapters/selectAdapter.js +153 -0
- package/lib/commonjs/push/detect/capabilities.js +136 -0
- package/lib/commonjs/push/index.js +33 -0
- package/lib/commonjs/push/native/nativeNotifications.js +168 -0
- package/lib/commonjs/push/types.js +2 -0
- package/lib/commonjs/specs/NativeReplaySdk.js +28 -0
- package/lib/commonjs/specs/NativeScaleBunCrash.js +30 -0
- package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js +24 -0
- package/lib/commonjs/specs/NativeScaleBunOta.js +32 -0
- package/lib/commonjs/specs/NativeScaleBunPerformance.js +25 -0
- package/lib/commonjs/specs/NativeScaleBunProfiler.js +26 -0
- package/lib/commonjs/specs/NativeScaleBunStorage.js +40 -0
- package/lib/commonjs/storage/StorageBackend.js +240 -0
- package/lib/commonjs/storage/db/sqlite.js +2 -0
- package/lib/commonjs/storage/files/fileStore.js +2 -0
- package/lib/commonjs/transport/auth/sdkSession.js +28 -0
- package/lib/commonjs/transport/backoff/exponentialJitter.js +16 -0
- package/lib/commonjs/transport/http/endpoints.js +46 -0
- package/lib/commonjs/transport/http/httpClient.js +72 -0
- package/lib/commonjs/transport/rateLimit/retryAfter.js +2 -0
- package/lib/commonjs/transport/signing/requestSigner.js +2 -0
- package/lib/commonjs/vendor/protocol/index.js +327 -0
- package/lib/commonjs/vendor/protocol/internal/validation.js +429 -0
- package/lib/commonjs/vendor/sdk-contracts/bridge.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/config.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/events.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/features.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/index.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/platform.js +2 -0
- package/lib/commonjs/vendor/sdk-contracts/session-boundary.js +6 -0
- package/lib/commonjs/vendor/sdk-contracts/session.js +2 -0
- package/lib/commonjs/vendor/vendor.manifest +10 -0
- package/lib/module/analytics/EventTracker.js +592 -0
- package/lib/module/analytics/automaticEvents.js +63 -0
- package/lib/module/analytics/batching.js +55 -0
- package/lib/module/analytics/eventLane.js +47 -0
- package/lib/module/analytics/revenue.js +117 -0
- package/lib/module/analytics/subscription.js +86 -0
- package/lib/module/bootstrap/FeatureRegistry.js +79 -0
- package/lib/module/bootstrap/SDKBootstrapper.js +742 -0
- package/lib/module/bucketing/fnv1a32.js +37 -0
- package/lib/module/compat/codepush.js +147 -0
- package/lib/module/config/ConfigManager.js +230 -0
- package/lib/module/config/configTypes.js +10 -0
- package/lib/module/config/otaPolicyState.js +76 -0
- package/lib/module/config/quotaState.js +423 -0
- package/lib/module/core/architecture.js +38 -0
- package/lib/module/core/clock/now.js +7 -0
- package/lib/module/core/config/defaults.js +2 -0
- package/lib/module/core/config/schema.js +506 -0
- package/lib/module/core/constants/endpoints.js +13 -0
- package/lib/module/core/constants/protocol.js +25 -0
- package/lib/module/core/constants/timings.js +26 -0
- package/lib/module/core/constants/version.js +12 -0
- package/lib/module/core/context/app.js +2 -0
- package/lib/module/core/context/device.js +143 -0
- package/lib/module/core/context/session.js +2 -0
- package/lib/module/core/context/user.js +2 -0
- package/lib/module/core/contracts/IFeature.js +2 -0
- package/lib/module/core/di/container.js +22 -0
- package/lib/module/core/encoding/base64.js +44 -0
- package/lib/module/core/id/deviceId.js +45 -0
- package/lib/module/core/id/installationId.js +50 -0
- package/lib/module/core/id/sessionId.js +2 -0
- package/lib/module/core/lifecycle/appLifecycle.js +25 -0
- package/lib/module/core/lifecycle/crashSafe.js +26 -0
- package/lib/module/core/logger/errorClassification.js +96 -0
- package/lib/module/core/logger/internalLogger.js +59 -0
- package/lib/module/core/logger/levels.js +2 -0
- package/lib/module/crypto/hmacSha256.js +126 -0
- package/lib/module/debug/bootstrap.js +393 -0
- package/lib/module/debug/commands.js +726 -0
- package/lib/module/debug/configBuilder.js +63 -0
- package/lib/module/debug/exportBridge.js +148 -0
- package/lib/module/debug/hostResolver.js +37 -0
- package/lib/module/debug/index.js +13 -0
- package/lib/module/debug/metrics.js +33 -0
- package/lib/module/debug/perf.js +180 -0
- package/lib/module/debug/perfWiring.js +102 -0
- package/lib/module/debug/protocol.js +19 -0
- package/lib/module/debug/redaction.js +411 -0
- package/lib/module/debug/replayWiring.js +139 -0
- package/lib/module/debug/screenTracking.js +53 -0
- package/lib/module/debug/sessionWiring.js +43 -0
- package/lib/module/debug/stream.js +536 -0
- package/lib/module/debug/transport.js +362 -0
- package/lib/module/features/bugreport/BugReportFeature.js +105 -0
- package/lib/module/features/bugreport/buildPayload.js +91 -0
- package/lib/module/features/bugreport/index.js +2 -0
- package/lib/module/features/crash/CrashFeature.js +79 -0
- package/lib/module/features/crash/CrashReporter.js +151 -0
- package/lib/module/features/crash/NativeCrashFeature.js +36 -0
- package/lib/module/features/crash/capture.js +42 -0
- package/lib/module/features/crash/globalHandler.js +36 -0
- package/lib/module/features/crash/index.js +8 -0
- package/lib/module/features/crash/nativeCrashBridge.js +350 -0
- package/lib/module/features/crash/rejectionHandler.js +171 -0
- package/lib/module/features/crash/scrubCrash.js +149 -0
- package/lib/module/features/engage/EngageAnchor.js +121 -0
- package/lib/module/features/engage/EngageArchetypeRenderers.js +4264 -0
- package/lib/module/features/engage/EngageInAppView.js +2656 -0
- package/lib/module/features/engage/EngageInlinePlacement.js +123 -0
- package/lib/module/features/engage/EngagePromptProvider.js +1054 -0
- package/lib/module/features/engage/EngagePromptView.js +1243 -0
- package/lib/module/features/engage/EngageTransport.js +602 -0
- package/lib/module/features/engage/EngageVariantContent.js +1771 -0
- package/lib/module/features/engage/__test-support__/reactNativeStub.js +52 -0
- package/lib/module/features/engage/attachmentCapture.js +42 -0
- package/lib/module/features/engage/captureVoiceAttachment.js +80 -0
- package/lib/module/features/engage/engageCoachmarkTour.js +94 -0
- package/lib/module/features/engage/engageGameLogic.js +287 -0
- package/lib/module/features/engage/engageMediaSizing.js +51 -0
- package/lib/module/features/engage/engageMultiStepSheet.js +35 -0
- package/lib/module/features/engage/engageOutcome.js +108 -0
- package/lib/module/features/engage/engagePushTokenBridge.js +65 -0
- package/lib/module/features/engage/engageShakeBridge.js +56 -0
- package/lib/module/features/engage/engageSignals.js +34 -0
- package/lib/module/features/engage/engageStoreReviewBridge.js +43 -0
- package/lib/module/features/engage/engageTestSeenStore.js +92 -0
- package/lib/module/features/engage/engageThrottle.js +390 -0
- package/lib/module/features/engage/engageTriggerEngine.js +360 -0
- package/lib/module/features/engage/engageTypes.js +110 -0
- package/lib/module/features/engage/engageVariantResolver.js +135 -0
- package/lib/module/features/engage/engageWindowInsets.js +89 -0
- package/lib/module/features/engage/gestureTriggerDetector.js +80 -0
- package/lib/module/features/engage/transcription/TranscriptionProvider.js +46 -0
- package/lib/module/features/install-referrer/installReferrer.js +104 -0
- package/lib/module/features/journey/ScaleBunDebugRoot.js +1030 -0
- package/lib/module/features/journey/ScaleBunFlatList.js +32 -0
- package/lib/module/features/journey/ScaleBunImpression.js +105 -0
- package/lib/module/features/journey/ScaleBunScrollView.js +95 -0
- package/lib/module/features/journey/ScaleBunSectionList.js +32 -0
- package/lib/module/features/journey/autoInstrumentScroll.js +155 -0
- package/lib/module/features/journey/calibrationContext.js +35 -0
- package/lib/module/features/journey/gestureBuffer.js +56 -0
- package/lib/module/features/journey/gestureDetector.js +169 -0
- package/lib/module/features/journey/impression.js +84 -0
- package/lib/module/features/journey/interactionProtocol.js +158 -0
- package/lib/module/features/journey/journeyManager.js +459 -0
- package/lib/module/features/journey/journeyTypes.js +49 -0
- package/lib/module/features/journey/nativeScroll.js +77 -0
- package/lib/module/features/journey/navDetector.js +154 -0
- package/lib/module/features/journey/screenshotHelper.js +129 -0
- package/lib/module/features/journey/scrollContext.js +142 -0
- package/lib/module/features/journey/targetGeometry.js +175 -0
- package/lib/module/features/journey/targetRegistry.js +44 -0
- package/lib/module/features/journey/touchTarget.js +241 -0
- package/lib/module/features/journey/uiState.js +176 -0
- package/lib/module/features/navigation/AutoScreenDetector.js +601 -0
- package/lib/module/features/network/NetworkFeature.js +209 -0
- package/lib/module/features/network/index.js +17 -0
- package/lib/module/features/network/thirdParty.js +142 -0
- package/lib/module/features/ota/OtaEventEmitter.js +123 -0
- package/lib/module/features/ota/OtaOrchestrator.js +1302 -0
- package/lib/module/features/ota/OtaTypes.js +2 -0
- package/lib/module/features/ota/deviceAttributes.js +43 -0
- package/lib/module/features/ota/environment.js +165 -0
- package/lib/module/features/ota/geoCountry.js +86 -0
- package/lib/module/features/ota/retry.js +87 -0
- package/lib/module/features/ota/signedDownload.js +174 -0
- package/lib/module/features/ota/useOtaUpdate.js +100 -0
- package/lib/module/features/performance/PerformanceFeature.js +643 -0
- package/lib/module/features/performance/collectors/AppLaunchCollector.js +115 -0
- package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js +225 -0
- package/lib/module/features/performance/collectors/CustomTraceCollector.js +92 -0
- package/lib/module/features/performance/collectors/FrameMetricsCollector.js +177 -0
- package/lib/module/features/performance/collectors/JsStallCollector.js +158 -0
- package/lib/module/features/performance/collectors/NetworkPerfCollector.js +52 -0
- package/lib/module/features/performance/collectors/ScreenLoadCollector.js +71 -0
- package/lib/module/features/performance/collectors/UiHangCollector.js +71 -0
- package/lib/module/features/performance/config.js +51 -0
- package/lib/module/features/performance/getNativePerformanceModule.js +39 -0
- package/lib/module/features/performance/index.js +9 -0
- package/lib/module/features/performance/metrics/MetricsEngine.js +139 -0
- package/lib/module/features/performance/models.js +42 -0
- package/lib/module/features/performance/transport/PerformanceTransport.js +162 -0
- package/lib/module/features/profiler/ProfilerFeature.js +594 -0
- package/lib/module/features/profiler/config.js +143 -0
- package/lib/module/features/profiler/contracts.js +56 -0
- package/lib/module/features/profiler/index.js +11 -0
- package/lib/module/features/profiler/models.js +106 -0
- package/lib/module/features/profiler/transport/ProfilerTransport.js +87 -0
- package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js +198 -0
- package/lib/module/features/replay/bridge/eventEmitter.js +122 -0
- package/lib/module/features/replay/bridge/nativeModule.js +89 -0
- package/lib/module/features/replay/bridge/nativeQuota.js +109 -0
- package/lib/module/features/replay/core/clock/clock.js +37 -0
- package/lib/module/features/replay/core/config/defaults.js +82 -0
- package/lib/module/features/replay/core/config/validator.js +103 -0
- package/lib/module/features/replay/core/env/environmentDetector.js +22 -0
- package/lib/module/features/replay/core/errors/safeCall.js +35 -0
- package/lib/module/features/replay/core/ids/sessionId.js +44 -0
- package/lib/module/features/replay/core/logger/logger.js +29 -0
- package/lib/module/features/replay/core/privacy/privacyTypes.js +27 -0
- package/lib/module/features/replay/core/queue/boundedQueue.js +64 -0
- package/lib/module/features/replay/integrations/alert/alertInstrumentation.js +252 -0
- package/lib/module/features/replay/integrations/logs/consoleIntegration.js +131 -0
- package/lib/module/features/replay/integrations/network/networkAdapter.js +70 -0
- package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js +82 -0
- package/lib/module/features/replay/integrations/touch/ReplayRoot.js +96 -0
- package/lib/module/features/replay/pipeline/batching/batchManager.js +113 -0
- package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js +43 -0
- package/lib/module/features/replay/pipeline/retry/retryPolicy.js +45 -0
- package/lib/module/features/replay/pipeline/transport/transportTypes.js +60 -0
- package/lib/module/features/replay/public/api.js +332 -0
- package/lib/module/features/replay/public/enums.js +85 -0
- package/lib/module/features/replay/public/types.js +2 -0
- package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js +113 -0
- package/lib/module/features/replay/replay/frames/frameModels.js +33 -0
- package/lib/module/features/replay/replay/session/sessionOrchestrator.js +272 -0
- package/lib/module/features/replay/replay/timeline/timelineModels.js +108 -0
- package/lib/module/features/replay/transport/BackendReplayTransport.js +169 -0
- package/lib/module/features/replay/transport/CompositeReplayTransport.js +68 -0
- package/lib/module/features/replay/transport/DesktopReplayTransport.js +119 -0
- package/lib/module/features/replay/transport/ReplayTransport.js +2 -0
- package/lib/module/features/session/BackendSessionAdapter.js +1908 -0
- package/lib/module/features/session/DesktopSessionTransport.js +118 -0
- package/lib/module/features/session/JourneyEventPipeline.js +239 -0
- package/lib/module/features/session/ReplayCaptureManager.js +1248 -0
- package/lib/module/features/session/ScrollTracker.js +141 -0
- package/lib/module/features/session/SessionManager.js +1443 -0
- package/lib/module/features/session/SyncDecisionEngine.js +88 -0
- package/lib/module/features/session/frameLink.js +29 -0
- package/lib/module/features/session/frameScrollState.js +34 -0
- package/lib/module/features/session/index.js +35 -0
- package/lib/module/features/session/nativeCapture.js +45 -0
- package/lib/module/features/session/outboxFrameCapture.js +77 -0
- package/lib/module/features/session/sessionTypes.js +226 -0
- package/lib/module/features/session/viewportPlausibility.js +137 -0
- package/lib/module/features/skan/skanBridge.js +48 -0
- package/lib/module/features/skan/skanConversionManager.js +128 -0
- package/lib/module/index.js +80 -0
- package/lib/module/integrations/fetch/fetchInterceptor.js +169 -0
- package/lib/module/integrations/navigation/screenTracker.js +2 -0
- package/lib/module/integrations/network/bodyCapture.js +320 -0
- package/lib/module/integrations/xhr/xhrInterceptor.js +219 -0
- package/lib/module/metro/composeSourceMap.js +97 -0
- package/lib/module/metro/featureModules.js +123 -0
- package/lib/module/metro/index.js +218 -0
- package/lib/module/metro/optionalDependencyStub.js +14 -0
- package/lib/module/metro/optionalModules.js +25 -0
- package/lib/module/metro/serializerCompose.js +152 -0
- package/lib/module/pipeline/dispatcher/dispatcher.js +21 -0
- package/lib/module/pipeline/envelope/envelope.js +11 -0
- package/lib/module/pipeline/envelope/serializer.js +8 -0
- package/lib/module/pipeline/processors/dedupe.js +2 -0
- package/lib/module/pipeline/processors/enrich.js +10 -0
- package/lib/module/pipeline/processors/sampling.js +2 -0
- package/lib/module/pipeline/processors/sanitize.js +22 -0
- package/lib/module/pipeline/queue/flushQueue.js +102 -0
- package/lib/module/pipeline/queue/memoryQueue.js +24 -0
- package/lib/module/pipeline/queue/persistentQueue.js +336 -0
- package/lib/module/pipeline/queue/queuePolicy.js +2 -0
- package/lib/module/pipeline/scheduler/flushScheduler.js +38 -0
- package/lib/module/pipeline/scheduler/retryPolicy.js +9 -0
- package/lib/module/public/ScaleBunErrorBoundary.js +82 -0
- package/lib/module/public/ScaleBunFacade.js +2038 -0
- package/lib/module/public/ScaleBunProvider.js +54 -0
- package/lib/module/public/typedTracker.js +72 -0
- package/lib/module/public/types.js +2 -0
- package/lib/module/push/PushManager.js +263 -0
- package/lib/module/push/adapters/ManualAdapter.js +79 -0
- package/lib/module/push/adapters/NativeBridgeAdapter.js +124 -0
- package/lib/module/push/adapters/NoopAdapter.js +38 -0
- package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js +241 -0
- package/lib/module/push/adapters/loadMessaging.js +23 -0
- package/lib/module/push/adapters/loadNotifee.js +30 -0
- package/lib/module/push/adapters/selectAdapter.js +147 -0
- package/lib/module/push/detect/capabilities.js +130 -0
- package/lib/module/push/index.js +9 -0
- package/lib/module/push/native/nativeNotifications.js +155 -0
- package/lib/module/push/types.js +2 -0
- package/lib/module/specs/NativeReplaySdk.js +24 -0
- package/lib/module/specs/NativeScaleBunCrash.js +26 -0
- package/lib/module/specs/NativeScaleBunInstallReferrer.js +20 -0
- package/lib/module/specs/NativeScaleBunOta.js +28 -0
- package/lib/module/specs/NativeScaleBunPerformance.js +21 -0
- package/lib/module/specs/NativeScaleBunProfiler.js +22 -0
- package/lib/module/specs/NativeScaleBunStorage.js +36 -0
- package/lib/module/storage/StorageBackend.js +231 -0
- package/lib/module/storage/db/sqlite.js +2 -0
- package/lib/module/storage/files/fileStore.js +2 -0
- package/lib/module/transport/auth/sdkSession.js +21 -0
- package/lib/module/transport/backoff/exponentialJitter.js +10 -0
- package/lib/module/transport/http/endpoints.js +40 -0
- package/lib/module/transport/http/httpClient.js +64 -0
- package/lib/module/transport/rateLimit/retryAfter.js +2 -0
- package/lib/module/transport/signing/requestSigner.js +2 -0
- package/lib/module/vendor/protocol/index.js +312 -0
- package/lib/module/vendor/protocol/internal/validation.js +423 -0
- package/lib/module/vendor/sdk-contracts/bridge.js +2 -0
- package/lib/module/vendor/sdk-contracts/config.js +2 -0
- package/lib/module/vendor/sdk-contracts/events.js +2 -0
- package/lib/module/vendor/sdk-contracts/features.js +2 -0
- package/lib/module/vendor/sdk-contracts/index.js +2 -0
- package/lib/module/vendor/sdk-contracts/platform.js +2 -0
- package/lib/module/vendor/sdk-contracts/session-boundary.js +2 -0
- package/lib/module/vendor/sdk-contracts/session.js +2 -0
- package/lib/module/vendor/vendor.manifest +10 -0
- package/lib/typescript/analytics/EventTracker.d.ts +197 -0
- package/lib/typescript/analytics/automaticEvents.d.ts +30 -0
- package/lib/typescript/analytics/batching.d.ts +33 -0
- package/lib/typescript/analytics/eventLane.d.ts +22 -0
- package/lib/typescript/analytics/revenue.d.ts +94 -0
- package/lib/typescript/analytics/subscription.d.ts +35 -0
- package/lib/typescript/bootstrap/FeatureRegistry.d.ts +36 -0
- package/lib/typescript/bootstrap/SDKBootstrapper.d.ts +82 -0
- package/lib/typescript/bucketing/fnv1a32.d.ts +20 -0
- package/lib/typescript/compat/codepush.d.ts +76 -0
- package/lib/typescript/config/ConfigManager.d.ts +82 -0
- package/lib/typescript/config/configTypes.d.ts +73 -0
- package/lib/typescript/config/otaPolicyState.d.ts +55 -0
- package/lib/typescript/config/quotaState.d.ts +155 -0
- package/lib/typescript/core/architecture.d.ts +29 -0
- package/lib/typescript/core/clock/now.d.ts +5 -0
- package/lib/typescript/core/config/defaults.d.ts +1 -0
- package/lib/typescript/core/config/schema.d.ts +107 -0
- package/lib/typescript/core/constants/endpoints.d.ts +13 -0
- package/lib/typescript/core/constants/protocol.d.ts +23 -0
- package/lib/typescript/core/constants/timings.d.ts +22 -0
- package/lib/typescript/core/constants/version.d.ts +12 -0
- package/lib/typescript/core/context/app.d.ts +1 -0
- package/lib/typescript/core/context/device.d.ts +61 -0
- package/lib/typescript/core/context/session.d.ts +1 -0
- package/lib/typescript/core/context/user.d.ts +24 -0
- package/lib/typescript/core/contracts/IFeature.d.ts +44 -0
- package/lib/typescript/core/di/container.d.ts +9 -0
- package/lib/typescript/core/encoding/base64.d.ts +13 -0
- package/lib/typescript/core/id/deviceId.d.ts +9 -0
- package/lib/typescript/core/id/installationId.d.ts +20 -0
- package/lib/typescript/core/id/sessionId.d.ts +1 -0
- package/lib/typescript/core/lifecycle/appLifecycle.d.ts +14 -0
- package/lib/typescript/core/lifecycle/crashSafe.d.ts +7 -0
- package/lib/typescript/core/logger/errorClassification.d.ts +46 -0
- package/lib/typescript/core/logger/internalLogger.d.ts +24 -0
- package/lib/typescript/core/logger/levels.d.ts +1 -0
- package/lib/typescript/crypto/hmacSha256.d.ts +10 -0
- package/lib/typescript/debug/bootstrap.d.ts +148 -0
- package/lib/typescript/debug/commands.d.ts +77 -0
- package/lib/typescript/debug/configBuilder.d.ts +13 -0
- package/lib/typescript/debug/exportBridge.d.ts +27 -0
- package/lib/typescript/debug/hostResolver.d.ts +14 -0
- package/lib/typescript/debug/index.d.ts +12 -0
- package/lib/typescript/debug/metrics.d.ts +2 -0
- package/lib/typescript/debug/perf.d.ts +43 -0
- package/lib/typescript/debug/perfWiring.d.ts +33 -0
- package/lib/typescript/debug/protocol.d.ts +15 -0
- package/lib/typescript/debug/redaction.d.ts +69 -0
- package/lib/typescript/debug/replayWiring.d.ts +25 -0
- package/lib/typescript/debug/screenTracking.d.ts +16 -0
- package/lib/typescript/debug/sessionWiring.d.ts +16 -0
- package/lib/typescript/debug/stream.d.ts +77 -0
- package/lib/typescript/debug/transport.d.ts +110 -0
- package/lib/typescript/features/bugreport/BugReportFeature.d.ts +59 -0
- package/lib/typescript/features/bugreport/buildPayload.d.ts +51 -0
- package/lib/typescript/features/bugreport/index.d.ts +1 -0
- package/lib/typescript/features/crash/CrashFeature.d.ts +21 -0
- package/lib/typescript/features/crash/CrashReporter.d.ts +107 -0
- package/lib/typescript/features/crash/NativeCrashFeature.d.ts +17 -0
- package/lib/typescript/features/crash/capture.d.ts +22 -0
- package/lib/typescript/features/crash/globalHandler.d.ts +14 -0
- package/lib/typescript/features/crash/index.d.ts +2 -0
- package/lib/typescript/features/crash/nativeCrashBridge.d.ts +43 -0
- package/lib/typescript/features/crash/rejectionHandler.d.ts +65 -0
- package/lib/typescript/features/crash/scrubCrash.d.ts +35 -0
- package/lib/typescript/features/engage/EngageAnchor.d.ts +36 -0
- package/lib/typescript/features/engage/EngageArchetypeRenderers.d.ts +66 -0
- package/lib/typescript/features/engage/EngageInAppView.d.ts +164 -0
- package/lib/typescript/features/engage/EngageInlinePlacement.d.ts +42 -0
- package/lib/typescript/features/engage/EngagePromptProvider.d.ts +233 -0
- package/lib/typescript/features/engage/EngagePromptView.d.ts +97 -0
- package/lib/typescript/features/engage/EngageTransport.d.ts +158 -0
- package/lib/typescript/features/engage/EngageVariantContent.d.ts +12 -0
- package/lib/typescript/features/engage/attachmentCapture.d.ts +17 -0
- package/lib/typescript/features/engage/captureVoiceAttachment.d.ts +31 -0
- package/lib/typescript/features/engage/engageCoachmarkTour.d.ts +18 -0
- package/lib/typescript/features/engage/engageGameLogic.d.ts +34 -0
- package/lib/typescript/features/engage/engageMediaSizing.d.ts +23 -0
- package/lib/typescript/features/engage/engageMultiStepSheet.d.ts +25 -0
- package/lib/typescript/features/engage/engageOutcome.d.ts +38 -0
- package/lib/typescript/features/engage/engagePushTokenBridge.d.ts +30 -0
- package/lib/typescript/features/engage/engageShakeBridge.d.ts +20 -0
- package/lib/typescript/features/engage/engageSignals.d.ts +13 -0
- package/lib/typescript/features/engage/engageStoreReviewBridge.d.ts +23 -0
- package/lib/typescript/features/engage/engageTestSeenStore.d.ts +46 -0
- package/lib/typescript/features/engage/engageThrottle.d.ts +180 -0
- package/lib/typescript/features/engage/engageTriggerEngine.d.ts +16 -0
- package/lib/typescript/features/engage/engageTypes.d.ts +576 -0
- package/lib/typescript/features/engage/engageVariantResolver.d.ts +46 -0
- package/lib/typescript/features/engage/engageWindowInsets.d.ts +25 -0
- package/lib/typescript/features/engage/gestureTriggerDetector.d.ts +20 -0
- package/lib/typescript/features/engage/transcription/TranscriptionProvider.d.ts +51 -0
- package/lib/typescript/features/install-referrer/installReferrer.d.ts +39 -0
- package/lib/typescript/features/journey/ScaleBunDebugRoot.d.ts +49 -0
- package/lib/typescript/features/journey/ScaleBunFlatList.d.ts +20 -0
- package/lib/typescript/features/journey/ScaleBunImpression.d.ts +30 -0
- package/lib/typescript/features/journey/ScaleBunScrollView.d.ts +25 -0
- package/lib/typescript/features/journey/ScaleBunSectionList.d.ts +20 -0
- package/lib/typescript/features/journey/autoInstrumentScroll.d.ts +46 -0
- package/lib/typescript/features/journey/calibrationContext.d.ts +26 -0
- package/lib/typescript/features/journey/gestureBuffer.d.ts +27 -0
- package/lib/typescript/features/journey/gestureDetector.d.ts +40 -0
- package/lib/typescript/features/journey/impression.d.ts +48 -0
- package/lib/typescript/features/journey/interactionProtocol.d.ts +159 -0
- package/lib/typescript/features/journey/journeyManager.d.ts +62 -0
- package/lib/typescript/features/journey/journeyTypes.d.ts +161 -0
- package/lib/typescript/features/journey/nativeScroll.d.ts +47 -0
- package/lib/typescript/features/journey/navDetector.d.ts +42 -0
- package/lib/typescript/features/journey/screenshotHelper.d.ts +33 -0
- package/lib/typescript/features/journey/scrollContext.d.ts +49 -0
- package/lib/typescript/features/journey/targetGeometry.d.ts +126 -0
- package/lib/typescript/features/journey/targetRegistry.d.ts +28 -0
- package/lib/typescript/features/journey/touchTarget.d.ts +174 -0
- package/lib/typescript/features/journey/uiState.d.ts +93 -0
- package/lib/typescript/features/navigation/AutoScreenDetector.d.ts +196 -0
- package/lib/typescript/features/network/NetworkFeature.d.ts +43 -0
- package/lib/typescript/features/network/index.d.ts +46 -0
- package/lib/typescript/features/network/thirdParty.d.ts +95 -0
- package/lib/typescript/features/ota/OtaEventEmitter.d.ts +93 -0
- package/lib/typescript/features/ota/OtaOrchestrator.d.ts +287 -0
- package/lib/typescript/features/ota/OtaTypes.d.ts +193 -0
- package/lib/typescript/features/ota/deviceAttributes.d.ts +18 -0
- package/lib/typescript/features/ota/environment.d.ts +99 -0
- package/lib/typescript/features/ota/geoCountry.d.ts +14 -0
- package/lib/typescript/features/ota/retry.d.ts +53 -0
- package/lib/typescript/features/ota/signedDownload.d.ts +81 -0
- package/lib/typescript/features/ota/useOtaUpdate.d.ts +72 -0
- package/lib/typescript/features/performance/PerformanceFeature.d.ts +132 -0
- package/lib/typescript/features/performance/collectors/AppLaunchCollector.d.ts +27 -0
- package/lib/typescript/features/performance/collectors/AutoScreenLoadCollector.d.ts +70 -0
- package/lib/typescript/features/performance/collectors/CustomTraceCollector.d.ts +35 -0
- package/lib/typescript/features/performance/collectors/FrameMetricsCollector.d.ts +74 -0
- package/lib/typescript/features/performance/collectors/JsStallCollector.d.ts +45 -0
- package/lib/typescript/features/performance/collectors/NetworkPerfCollector.d.ts +23 -0
- package/lib/typescript/features/performance/collectors/ScreenLoadCollector.d.ts +30 -0
- package/lib/typescript/features/performance/collectors/UiHangCollector.d.ts +21 -0
- package/lib/typescript/features/performance/config.d.ts +73 -0
- package/lib/typescript/features/performance/getNativePerformanceModule.d.ts +2 -0
- package/lib/typescript/features/performance/index.d.ts +10 -0
- package/lib/typescript/features/performance/metrics/MetricsEngine.d.ts +69 -0
- package/lib/typescript/features/performance/models.d.ts +169 -0
- package/lib/typescript/features/performance/transport/PerformanceTransport.d.ts +40 -0
- package/lib/typescript/features/profiler/ProfilerFeature.d.ts +92 -0
- package/lib/typescript/features/profiler/config.d.ts +85 -0
- package/lib/typescript/features/profiler/contracts.d.ts +142 -0
- package/lib/typescript/features/profiler/index.d.ts +13 -0
- package/lib/typescript/features/profiler/models.d.ts +332 -0
- package/lib/typescript/features/profiler/transport/ProfilerTransport.d.ts +30 -0
- package/lib/typescript/features/replay/bridge/adapters/bridgeAdapter.d.ts +52 -0
- package/lib/typescript/features/replay/bridge/eventEmitter.d.ts +100 -0
- package/lib/typescript/features/replay/bridge/nativeModule.d.ts +166 -0
- package/lib/typescript/features/replay/bridge/nativeQuota.d.ts +26 -0
- package/lib/typescript/features/replay/core/clock/clock.d.ts +16 -0
- package/lib/typescript/features/replay/core/config/defaults.d.ts +28 -0
- package/lib/typescript/features/replay/core/config/validator.d.ts +13 -0
- package/lib/typescript/features/replay/core/env/environmentDetector.d.ts +14 -0
- package/lib/typescript/features/replay/core/errors/safeCall.d.ts +12 -0
- package/lib/typescript/features/replay/core/ids/sessionId.d.ts +15 -0
- package/lib/typescript/features/replay/core/logger/logger.d.ts +15 -0
- package/lib/typescript/features/replay/core/privacy/privacyTypes.d.ts +24 -0
- package/lib/typescript/features/replay/core/queue/boundedQueue.d.ts +29 -0
- package/lib/typescript/features/replay/integrations/alert/alertInstrumentation.d.ts +48 -0
- package/lib/typescript/features/replay/integrations/logs/consoleIntegration.d.ts +18 -0
- package/lib/typescript/features/replay/integrations/network/networkAdapter.d.ts +31 -0
- package/lib/typescript/features/replay/integrations/react-navigation/navigationIntegration.d.ts +25 -0
- package/lib/typescript/features/replay/integrations/touch/ReplayRoot.d.ts +26 -0
- package/lib/typescript/features/replay/pipeline/batching/batchManager.d.ts +47 -0
- package/lib/typescript/features/replay/pipeline/envelope/envelopeBuilder.d.ts +12 -0
- package/lib/typescript/features/replay/pipeline/retry/retryPolicy.d.ts +17 -0
- package/lib/typescript/features/replay/pipeline/transport/transportTypes.d.ts +40 -0
- package/lib/typescript/features/replay/public/api.d.ts +83 -0
- package/lib/typescript/features/replay/public/enums.d.ts +73 -0
- package/lib/typescript/features/replay/public/types.d.ts +249 -0
- package/lib/typescript/features/replay/replay/breadcrumbs/breadcrumbCollector.d.ts +26 -0
- package/lib/typescript/features/replay/replay/frames/frameModels.d.ts +23 -0
- package/lib/typescript/features/replay/replay/session/sessionOrchestrator.d.ts +53 -0
- package/lib/typescript/features/replay/replay/timeline/timelineModels.d.ts +29 -0
- package/lib/typescript/features/replay/transport/BackendReplayTransport.d.ts +45 -0
- package/lib/typescript/features/replay/transport/CompositeReplayTransport.d.ts +22 -0
- package/lib/typescript/features/replay/transport/DesktopReplayTransport.d.ts +35 -0
- package/lib/typescript/features/replay/transport/ReplayTransport.d.ts +72 -0
- package/lib/typescript/features/session/BackendSessionAdapter.d.ts +528 -0
- package/lib/typescript/features/session/DesktopSessionTransport.d.ts +28 -0
- package/lib/typescript/features/session/JourneyEventPipeline.d.ts +74 -0
- package/lib/typescript/features/session/ReplayCaptureManager.d.ts +391 -0
- package/lib/typescript/features/session/ScrollTracker.d.ts +48 -0
- package/lib/typescript/features/session/SessionManager.d.ts +414 -0
- package/lib/typescript/features/session/SyncDecisionEngine.d.ts +33 -0
- package/lib/typescript/features/session/frameLink.d.ts +27 -0
- package/lib/typescript/features/session/frameScrollState.d.ts +27 -0
- package/lib/typescript/features/session/index.d.ts +23 -0
- package/lib/typescript/features/session/nativeCapture.d.ts +18 -0
- package/lib/typescript/features/session/outboxFrameCapture.d.ts +20 -0
- package/lib/typescript/features/session/sessionTypes.d.ts +362 -0
- package/lib/typescript/features/session/viewportPlausibility.d.ts +72 -0
- package/lib/typescript/features/skan/skanBridge.d.ts +18 -0
- package/lib/typescript/features/skan/skanConversionManager.d.ts +69 -0
- package/lib/typescript/index.d.ts +59 -0
- package/lib/typescript/integrations/fetch/fetchInterceptor.d.ts +41 -0
- package/lib/typescript/integrations/navigation/screenTracker.d.ts +1 -0
- package/lib/typescript/integrations/network/bodyCapture.d.ts +101 -0
- package/lib/typescript/integrations/xhr/xhrInterceptor.d.ts +46 -0
- package/lib/typescript/metro/composeSourceMap.d.ts +26 -0
- package/lib/typescript/metro/featureModules.d.ts +49 -0
- package/lib/typescript/metro/index.d.ts +99 -0
- package/lib/typescript/metro/optionalDependencyStub.d.ts +14 -0
- package/lib/typescript/metro/optionalModules.d.ts +20 -0
- package/lib/typescript/metro/serializerCompose.d.ts +46 -0
- package/lib/typescript/pipeline/dispatcher/dispatcher.d.ts +7 -0
- package/lib/typescript/pipeline/envelope/envelope.d.ts +16 -0
- package/lib/typescript/pipeline/envelope/serializer.d.ts +7 -0
- package/lib/typescript/pipeline/processors/dedupe.d.ts +1 -0
- package/lib/typescript/pipeline/processors/enrich.d.ts +3 -0
- package/lib/typescript/pipeline/processors/sampling.d.ts +1 -0
- package/lib/typescript/pipeline/processors/sanitize.d.ts +3 -0
- package/lib/typescript/pipeline/queue/flushQueue.d.ts +12 -0
- package/lib/typescript/pipeline/queue/memoryQueue.d.ts +12 -0
- package/lib/typescript/pipeline/queue/persistentQueue.d.ts +120 -0
- package/lib/typescript/pipeline/queue/queuePolicy.d.ts +1 -0
- package/lib/typescript/pipeline/scheduler/flushScheduler.d.ts +9 -0
- package/lib/typescript/pipeline/scheduler/retryPolicy.d.ts +5 -0
- package/lib/typescript/public/ScaleBunErrorBoundary.d.ts +44 -0
- package/lib/typescript/public/ScaleBunFacade.d.ts +800 -0
- package/lib/typescript/public/ScaleBunProvider.d.ts +23 -0
- package/lib/typescript/public/typedTracker.d.ts +88 -0
- package/lib/typescript/public/types.d.ts +316 -0
- package/lib/typescript/push/PushManager.d.ts +69 -0
- package/lib/typescript/push/adapters/ManualAdapter.d.ts +40 -0
- package/lib/typescript/push/adapters/NativeBridgeAdapter.d.ts +37 -0
- package/lib/typescript/push/adapters/NoopAdapter.d.ts +21 -0
- package/lib/typescript/push/adapters/RNFirebaseMessagingAdapter.d.ts +39 -0
- package/lib/typescript/push/adapters/loadMessaging.d.ts +17 -0
- package/lib/typescript/push/adapters/loadNotifee.d.ts +15 -0
- package/lib/typescript/push/adapters/selectAdapter.d.ts +20 -0
- package/lib/typescript/push/detect/capabilities.d.ts +15 -0
- package/lib/typescript/push/index.d.ts +10 -0
- package/lib/typescript/push/native/nativeNotifications.d.ts +65 -0
- package/lib/typescript/push/types.d.ts +143 -0
- package/lib/typescript/specs/NativeReplaySdk.d.ts +69 -0
- package/lib/typescript/specs/NativeScaleBunCrash.d.ts +58 -0
- package/lib/typescript/specs/NativeScaleBunInstallReferrer.d.ts +28 -0
- package/lib/typescript/specs/NativeScaleBunOta.d.ts +141 -0
- package/lib/typescript/specs/NativeScaleBunPerformance.d.ts +31 -0
- package/lib/typescript/specs/NativeScaleBunProfiler.d.ts +38 -0
- package/lib/typescript/specs/NativeScaleBunStorage.d.ts +55 -0
- package/lib/typescript/storage/StorageBackend.d.ts +131 -0
- package/lib/typescript/storage/db/sqlite.d.ts +1 -0
- package/lib/typescript/storage/files/fileStore.d.ts +1 -0
- package/lib/typescript/transport/auth/sdkSession.d.ts +10 -0
- package/lib/typescript/transport/backoff/exponentialJitter.d.ts +5 -0
- package/lib/typescript/transport/http/endpoints.d.ts +26 -0
- package/lib/typescript/transport/http/httpClient.d.ts +23 -0
- package/lib/typescript/transport/rateLimit/retryAfter.d.ts +1 -0
- package/lib/typescript/transport/signing/requestSigner.d.ts +1 -0
- package/lib/typescript/vendor/protocol/index.d.ts +345 -0
- package/lib/typescript/vendor/protocol/internal/validation.d.ts +114 -0
- package/lib/typescript/vendor/sdk-contracts/bridge.d.ts +104 -0
- package/lib/typescript/vendor/sdk-contracts/config.d.ts +156 -0
- package/lib/typescript/vendor/sdk-contracts/events.d.ts +42 -0
- package/lib/typescript/vendor/sdk-contracts/features.d.ts +38 -0
- package/lib/typescript/vendor/sdk-contracts/index.d.ts +15 -0
- package/lib/typescript/vendor/sdk-contracts/platform.d.ts +35 -0
- package/lib/typescript/vendor/sdk-contracts/session-boundary.d.ts +42 -0
- package/lib/typescript/vendor/sdk-contracts/session.d.ts +157 -0
- package/package.json +153 -0
- package/react-native.config.js +24 -0
- package/scalebun-react-native.podspec +44 -0
- package/src/analytics/EventTracker.ts +654 -0
- package/src/analytics/automaticEvents.ts +109 -0
- package/src/analytics/batching.ts +54 -0
- package/src/analytics/eventLane.ts +48 -0
- package/src/analytics/revenue.ts +143 -0
- package/src/analytics/subscription.ts +145 -0
- package/src/bootstrap/FeatureRegistry.ts +81 -0
- package/src/bootstrap/SDKBootstrapper.ts +769 -0
- package/src/bucketing/fnv1a32.ts +40 -0
- package/src/compat/codepush.ts +189 -0
- package/src/config/ConfigManager.ts +233 -0
- package/src/config/configTypes.ts +62 -0
- package/src/config/otaPolicyState.ts +79 -0
- package/src/config/quotaState.ts +484 -0
- package/src/core/architecture.ts +39 -0
- package/src/core/clock/now.ts +6 -0
- package/src/core/config/defaults.ts +0 -0
- package/src/core/config/schema.ts +455 -0
- package/src/core/constants/endpoints.ts +12 -0
- package/src/core/constants/protocol.ts +24 -0
- package/src/core/constants/timings.ts +25 -0
- package/src/core/constants/version.ts +11 -0
- package/src/core/context/app.ts +0 -0
- package/src/core/context/device.ts +169 -0
- package/src/core/context/session.ts +0 -0
- package/src/core/context/user.ts +26 -0
- package/src/core/contracts/IFeature.ts +53 -0
- package/src/core/di/container.ts +26 -0
- package/src/core/encoding/base64.ts +46 -0
- package/src/core/id/deviceId.ts +51 -0
- package/src/core/id/installationId.ts +52 -0
- package/src/core/id/sessionId.ts +0 -0
- package/src/core/lifecycle/appLifecycle.ts +33 -0
- package/src/core/lifecycle/crashSafe.ts +29 -0
- package/src/core/logger/errorClassification.ts +108 -0
- package/src/core/logger/internalLogger.ts +65 -0
- package/src/core/logger/levels.ts +0 -0
- package/src/crypto/hmacSha256.ts +106 -0
- package/src/debug/bootstrap.ts +436 -0
- package/src/debug/commands.ts +597 -0
- package/src/debug/configBuilder.ts +56 -0
- package/src/debug/exportBridge.ts +155 -0
- package/src/debug/hostResolver.ts +34 -0
- package/src/debug/index.ts +25 -0
- package/src/debug/metrics.ts +29 -0
- package/src/debug/perf.ts +212 -0
- package/src/debug/perfWiring.ts +119 -0
- package/src/debug/protocol.ts +58 -0
- package/src/debug/redaction.ts +483 -0
- package/src/debug/replayWiring.ts +148 -0
- package/src/debug/screenTracking.ts +55 -0
- package/src/debug/sessionWiring.ts +59 -0
- package/src/debug/stream.ts +561 -0
- package/src/debug/transport.ts +440 -0
- package/src/features/bugreport/BugReportFeature.ts +128 -0
- package/src/features/bugreport/buildPayload.ts +116 -0
- package/src/features/bugreport/index.ts +0 -0
- package/src/features/crash/CrashFeature.ts +87 -0
- package/src/features/crash/CrashReporter.ts +189 -0
- package/src/features/crash/NativeCrashFeature.ts +42 -0
- package/src/features/crash/capture.ts +48 -0
- package/src/features/crash/globalHandler.ts +39 -0
- package/src/features/crash/index.ts +8 -0
- package/src/features/crash/nativeCrashBridge.ts +352 -0
- package/src/features/crash/rejectionHandler.ts +196 -0
- package/src/features/crash/scrubCrash.ts +175 -0
- package/src/features/engage/EngageAnchor.tsx +159 -0
- package/src/features/engage/EngageArchetypeRenderers.tsx +3705 -0
- package/src/features/engage/EngageInAppView.tsx +2678 -0
- package/src/features/engage/EngageInlinePlacement.tsx +169 -0
- package/src/features/engage/EngagePromptProvider.tsx +1318 -0
- package/src/features/engage/EngagePromptView.tsx +1400 -0
- package/src/features/engage/EngageTransport.ts +668 -0
- package/src/features/engage/EngageVariantContent.tsx +1483 -0
- package/src/features/engage/__test-support__/reactNativeStub.js +40 -0
- package/src/features/engage/attachmentCapture.ts +45 -0
- package/src/features/engage/captureVoiceAttachment.ts +81 -0
- package/src/features/engage/engageCoachmarkTour.ts +120 -0
- package/src/features/engage/engageGameLogic.ts +347 -0
- package/src/features/engage/engageMediaSizing.ts +76 -0
- package/src/features/engage/engageMultiStepSheet.ts +53 -0
- package/src/features/engage/engageOutcome.ts +157 -0
- package/src/features/engage/engagePushTokenBridge.ts +84 -0
- package/src/features/engage/engageShakeBridge.ts +67 -0
- package/src/features/engage/engageSignals.ts +40 -0
- package/src/features/engage/engageStoreReviewBridge.ts +48 -0
- package/src/features/engage/engageTestSeenStore.ts +95 -0
- package/src/features/engage/engageThrottle.ts +478 -0
- package/src/features/engage/engageTriggerEngine.ts +350 -0
- package/src/features/engage/engageTypes.ts +712 -0
- package/src/features/engage/engageVariantResolver.ts +364 -0
- package/src/features/engage/engageWindowInsets.ts +108 -0
- package/src/features/engage/gestureTriggerDetector.ts +83 -0
- package/src/features/engage/transcription/TranscriptionProvider.ts +68 -0
- package/src/features/install-referrer/installReferrer.ts +112 -0
- package/src/features/journey/ScaleBunDebugRoot.tsx +1045 -0
- package/src/features/journey/ScaleBunFlatList.tsx +39 -0
- package/src/features/journey/ScaleBunImpression.tsx +109 -0
- package/src/features/journey/ScaleBunScrollView.tsx +101 -0
- package/src/features/journey/ScaleBunSectionList.tsx +39 -0
- package/src/features/journey/autoInstrumentScroll.ts +155 -0
- package/src/features/journey/calibrationContext.ts +44 -0
- package/src/features/journey/gestureBuffer.ts +59 -0
- package/src/features/journey/gestureDetector.ts +162 -0
- package/src/features/journey/impression.ts +92 -0
- package/src/features/journey/interactionProtocol.ts +243 -0
- package/src/features/journey/journeyManager.ts +469 -0
- package/src/features/journey/journeyTypes.ts +215 -0
- package/src/features/journey/nativeScroll.ts +94 -0
- package/src/features/journey/navDetector.ts +149 -0
- package/src/features/journey/screenshotHelper.ts +137 -0
- package/src/features/journey/scrollContext.ts +146 -0
- package/src/features/journey/targetGeometry.ts +197 -0
- package/src/features/journey/targetRegistry.ts +43 -0
- package/src/features/journey/touchTarget.ts +339 -0
- package/src/features/journey/uiState.ts +182 -0
- package/src/features/navigation/AutoScreenDetector.ts +617 -0
- package/src/features/network/NetworkFeature.ts +232 -0
- package/src/features/network/index.ts +59 -0
- package/src/features/network/thirdParty.ts +160 -0
- package/src/features/ota/OtaEventEmitter.ts +187 -0
- package/src/features/ota/OtaOrchestrator.ts +1513 -0
- package/src/features/ota/OtaTypes.ts +230 -0
- package/src/features/ota/deviceAttributes.ts +46 -0
- package/src/features/ota/environment.ts +199 -0
- package/src/features/ota/geoCountry.ts +85 -0
- package/src/features/ota/retry.ts +123 -0
- package/src/features/ota/signedDownload.ts +202 -0
- package/src/features/ota/useOtaUpdate.ts +161 -0
- package/src/features/performance/PerformanceFeature.ts +729 -0
- package/src/features/performance/collectors/AppLaunchCollector.ts +131 -0
- package/src/features/performance/collectors/AutoScreenLoadCollector.ts +258 -0
- package/src/features/performance/collectors/CustomTraceCollector.ts +116 -0
- package/src/features/performance/collectors/FrameMetricsCollector.ts +210 -0
- package/src/features/performance/collectors/JsStallCollector.ts +184 -0
- package/src/features/performance/collectors/NetworkPerfCollector.ts +69 -0
- package/src/features/performance/collectors/ScreenLoadCollector.ts +95 -0
- package/src/features/performance/collectors/UiHangCollector.ts +98 -0
- package/src/features/performance/config.ts +136 -0
- package/src/features/performance/getNativePerformanceModule.ts +38 -0
- package/src/features/performance/index.ts +28 -0
- package/src/features/performance/metrics/MetricsEngine.ts +152 -0
- package/src/features/performance/models.ts +235 -0
- package/src/features/performance/transport/PerformanceTransport.ts +161 -0
- package/src/features/profiler/ProfilerFeature.ts +661 -0
- package/src/features/profiler/config.ts +230 -0
- package/src/features/profiler/contracts.ts +176 -0
- package/src/features/profiler/index.ts +45 -0
- package/src/features/profiler/models.ts +430 -0
- package/src/features/profiler/transport/ProfilerTransport.ts +93 -0
- package/src/features/replay/bridge/adapters/bridgeAdapter.ts +235 -0
- package/src/features/replay/bridge/eventEmitter.ts +176 -0
- package/src/features/replay/bridge/nativeModule.ts +252 -0
- package/src/features/replay/bridge/nativeQuota.ts +111 -0
- package/src/features/replay/core/clock/clock.ts +38 -0
- package/src/features/replay/core/config/defaults.ts +66 -0
- package/src/features/replay/core/config/validator.ts +113 -0
- package/src/features/replay/core/env/environmentDetector.ts +21 -0
- package/src/features/replay/core/errors/safeCall.ts +34 -0
- package/src/features/replay/core/ids/sessionId.ts +44 -0
- package/src/features/replay/core/logger/logger.ts +36 -0
- package/src/features/replay/core/privacy/privacyTypes.ts +41 -0
- package/src/features/replay/core/queue/boundedQueue.ts +71 -0
- package/src/features/replay/integrations/alert/alertInstrumentation.ts +277 -0
- package/src/features/replay/integrations/logs/consoleIntegration.ts +136 -0
- package/src/features/replay/integrations/network/networkAdapter.ts +73 -0
- package/src/features/replay/integrations/react-navigation/navigationIntegration.ts +89 -0
- package/src/features/replay/integrations/touch/ReplayRoot.tsx +114 -0
- package/src/features/replay/pipeline/batching/batchManager.ts +133 -0
- package/src/features/replay/pipeline/envelope/envelopeBuilder.ts +66 -0
- package/src/features/replay/pipeline/retry/retryPolicy.ts +62 -0
- package/src/features/replay/pipeline/transport/transportTypes.ts +85 -0
- package/src/features/replay/public/api.ts +364 -0
- package/src/features/replay/public/enums.ts +78 -0
- package/src/features/replay/public/types.ts +297 -0
- package/src/features/replay/replay/breadcrumbs/breadcrumbCollector.ts +115 -0
- package/src/features/replay/replay/frames/frameModels.ts +45 -0
- package/src/features/replay/replay/session/sessionOrchestrator.ts +286 -0
- package/src/features/replay/replay/timeline/timelineModels.ts +129 -0
- package/src/features/replay/transport/BackendReplayTransport.ts +215 -0
- package/src/features/replay/transport/CompositeReplayTransport.ts +82 -0
- package/src/features/replay/transport/DesktopReplayTransport.ts +140 -0
- package/src/features/replay/transport/ReplayTransport.ts +84 -0
- package/src/features/session/BackendSessionAdapter.ts +1977 -0
- package/src/features/session/DesktopSessionTransport.ts +130 -0
- package/src/features/session/JourneyEventPipeline.ts +278 -0
- package/src/features/session/ReplayCaptureManager.ts +1401 -0
- package/src/features/session/ScrollTracker.ts +166 -0
- package/src/features/session/SessionManager.ts +1687 -0
- package/src/features/session/SyncDecisionEngine.ts +117 -0
- package/src/features/session/frameLink.ts +41 -0
- package/src/features/session/frameScrollState.ts +36 -0
- package/src/features/session/index.ts +88 -0
- package/src/features/session/nativeCapture.ts +43 -0
- package/src/features/session/outboxFrameCapture.ts +79 -0
- package/src/features/session/sessionTypes.ts +528 -0
- package/src/features/session/viewportPlausibility.ts +134 -0
- package/src/features/skan/skanBridge.ts +53 -0
- package/src/features/skan/skanConversionManager.ts +173 -0
- package/src/index.ts +206 -0
- package/src/integrations/fetch/fetchInterceptor.ts +201 -0
- package/src/integrations/navigation/screenTracker.ts +0 -0
- package/src/integrations/network/bodyCapture.ts +328 -0
- package/src/integrations/xhr/xhrInterceptor.ts +259 -0
- package/src/metro/composeSourceMap.ts +104 -0
- package/src/metro/featureModules.ts +143 -0
- package/src/metro/index.ts +336 -0
- package/src/metro/optionalDependencyStub.ts +13 -0
- package/src/metro/optionalModules.ts +27 -0
- package/src/metro/serializerCompose.ts +193 -0
- package/src/pipeline/dispatcher/dispatcher.ts +22 -0
- package/src/pipeline/envelope/envelope.ts +31 -0
- package/src/pipeline/envelope/serializer.ts +14 -0
- package/src/pipeline/processors/dedupe.ts +0 -0
- package/src/pipeline/processors/enrich.ts +11 -0
- package/src/pipeline/processors/sampling.ts +0 -0
- package/src/pipeline/processors/sanitize.ts +23 -0
- package/src/pipeline/queue/flushQueue.ts +144 -0
- package/src/pipeline/queue/memoryQueue.ts +31 -0
- package/src/pipeline/queue/persistentQueue.ts +385 -0
- package/src/pipeline/queue/queuePolicy.ts +0 -0
- package/src/pipeline/scheduler/flushScheduler.ts +47 -0
- package/src/pipeline/scheduler/retryPolicy.ts +8 -0
- package/src/public/ScaleBunErrorBoundary.tsx +91 -0
- package/src/public/ScaleBunFacade.ts +2129 -0
- package/src/public/ScaleBunProvider.tsx +91 -0
- package/src/public/typedTracker.ts +123 -0
- package/src/public/types.ts +362 -0
- package/src/push/PushManager.ts +318 -0
- package/src/push/adapters/ManualAdapter.ts +100 -0
- package/src/push/adapters/NativeBridgeAdapter.ts +142 -0
- package/src/push/adapters/NoopAdapter.ts +46 -0
- package/src/push/adapters/RNFirebaseMessagingAdapter.ts +271 -0
- package/src/push/adapters/loadMessaging.ts +24 -0
- package/src/push/adapters/loadNotifee.ts +29 -0
- package/src/push/adapters/selectAdapter.ts +176 -0
- package/src/push/detect/capabilities.ts +124 -0
- package/src/push/index.ts +22 -0
- package/src/push/native/nativeNotifications.ts +207 -0
- package/src/push/types.ts +159 -0
- package/src/specs/NativeReplaySdk.ts +101 -0
- package/src/specs/NativeScaleBunCrash.ts +64 -0
- package/src/specs/NativeScaleBunInstallReferrer.ts +29 -0
- package/src/specs/NativeScaleBunOta.ts +154 -0
- package/src/specs/NativeScaleBunPerformance.ts +34 -0
- package/src/specs/NativeScaleBunProfiler.ts +41 -0
- package/src/specs/NativeScaleBunStorage.ts +59 -0
- package/src/storage/StorageBackend.ts +272 -0
- package/src/storage/db/sqlite.ts +0 -0
- package/src/storage/files/fileStore.ts +0 -0
- package/src/transport/auth/sdkSession.ts +27 -0
- package/src/transport/backoff/exponentialJitter.ts +9 -0
- package/src/transport/http/endpoints.ts +33 -0
- package/src/transport/http/httpClient.ts +73 -0
- package/src/transport/rateLimit/retryAfter.ts +0 -0
- package/src/transport/signing/requestSigner.ts +0 -0
- package/src/vendor/protocol/index.ts +391 -0
- package/src/vendor/protocol/internal/validation.ts +497 -0
- package/src/vendor/sdk-contracts/bridge.ts +162 -0
- package/src/vendor/sdk-contracts/config.ts +192 -0
- package/src/vendor/sdk-contracts/events.ts +50 -0
- package/src/vendor/sdk-contracts/features.ts +42 -0
- package/src/vendor/sdk-contracts/index.ts +98 -0
- package/src/vendor/sdk-contracts/platform.ts +42 -0
- package/src/vendor/sdk-contracts/session-boundary.ts +55 -0
- package/src/vendor/sdk-contracts/session.ts +225 -0
- package/src/vendor/vendor.manifest +10 -0
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScaleBun SDK — Engage Prompt Provider (campaign renderer core, D4)
|
|
3
|
+
*
|
|
4
|
+
* Wraps the host app and owns the campaign-render lifecycle for the shared
|
|
5
|
+
* cross-platform JS overlay:
|
|
6
|
+
* 1. on a trigger (app-controlled via `showEngagePrompt()` and/or the campaign's
|
|
7
|
+
* own `trigger` from config), calls `facade.engage.fetchConfig()`,
|
|
8
|
+
* 2. runs the throttle/decision core (`selectCampaignToRender`) to pick which
|
|
9
|
+
* campaign — if any — is eligible, honoring frequency caps,
|
|
10
|
+
* 3. mounts the parameterized `EngagePromptView` (Open/Closed: NPS now,
|
|
11
|
+
* ratings/feedback/survey later via the renderer registry),
|
|
12
|
+
* 4. on submit → `facade.engage.submitResponse({ surveyId, score, text })`
|
|
13
|
+
* (transport stamps `responseId` UUID + `schemaVersion` per contract),
|
|
14
|
+
* records the impression as completed, and emits an in-app dismiss/submit
|
|
15
|
+
* tracking event,
|
|
16
|
+
* 5. on dismiss → `facade.engage.trackEvent` with a `dismiss` event.
|
|
17
|
+
*
|
|
18
|
+
* The provider depends only on the `engage` namespace shape — NOT the whole
|
|
19
|
+
* facade — so it stays decoupled and testable, and reuses the existing transport
|
|
20
|
+
* (no second HTTP path).
|
|
21
|
+
*
|
|
22
|
+
* IN-APP MESSAGES (the second Engage family, §2.4/§2.5) are surfaced by this SAME
|
|
23
|
+
* provider — NOT a parallel one. `showInAppMessage()` fetches the config, picks an
|
|
24
|
+
* eligible message from `inAppMessages[]` (shared throttle store), and mounts the
|
|
25
|
+
* config-driven `EngageInAppView` (banner/modal/overlay). Events: `impression` on
|
|
26
|
+
* show, `click` on CTA tap (the resolved deep link is surfaced to the host via
|
|
27
|
+
* `onInAppDeepLink` — the SDK never opens URLs), `dismiss` on close.
|
|
28
|
+
*
|
|
29
|
+
* PRECEDENCE (campaign vs in-app): a campaign prompt wins the screen. If a
|
|
30
|
+
* campaign prompt is already visible, `showInAppMessage()` is a no-op (returns
|
|
31
|
+
* false) and the mounted in-app view is hidden while a campaign is up, so the two
|
|
32
|
+
* families never fight for the screen.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import React, { createContext, useContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
36
|
+
import { Linking, Platform } from 'react-native';
|
|
37
|
+
import { logger } from '../../core/logger/internalLogger';
|
|
38
|
+
import { installEngageTriggerEngine } from './engageTriggerEngine';
|
|
39
|
+
import { appLifecycle } from '../../core/lifecycle/appLifecycle';
|
|
40
|
+
import { getDeviceId } from '../../core/id/deviceId';
|
|
41
|
+
import { ReplaySdk } from '../replay/public/api';
|
|
42
|
+
import { SessionManager } from '../session/SessionManager';
|
|
43
|
+
import { EngagePromptView } from './EngagePromptView';
|
|
44
|
+
import { EngageInAppView } from './EngageInAppView';
|
|
45
|
+
import { EngageAnchorProvider } from './EngageAnchor';
|
|
46
|
+
import { EngageInlinePlacementProvider, createEngageInlinePlacementRegistry, resolveEngageInlinePlacement } from './EngageInlinePlacement';
|
|
47
|
+
import { resolveInAppPresentation } from './engageVariantResolver';
|
|
48
|
+
import { shouldTrackInAppCta } from './engageOutcome';
|
|
49
|
+
import { EngageThrottleStore, selectCampaignToRender, selectInAppToRender, selectInAppVariant, selectLatestUnseenTest, testRunIdOf } from './engageThrottle';
|
|
50
|
+
import { EngageTestSeenStore } from './engageTestSeenStore';
|
|
51
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
52
|
+
/** Client-generated UUID for app-rating idempotency (D8: `clientRatingId`). */
|
|
53
|
+
function ratingUuid() {
|
|
54
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
55
|
+
const r = Math.random() * 16 | 0;
|
|
56
|
+
const v = c === 'x' ? r : r & 0x3 | 0x8;
|
|
57
|
+
return v.toString(16);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Preserve a multi-question survey answer in the keyed wire shape (§1.4). */
|
|
62
|
+
export function toWireAnswers(answers) {
|
|
63
|
+
return answers.map(a => ({
|
|
64
|
+
key: a.key,
|
|
65
|
+
value: a.value
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the canonical session id for response linkage (contract §1/§7).
|
|
71
|
+
* Primary source is `SessionManager.currentSessionId` — the always-on analytics
|
|
72
|
+
* session id (`rs-…`) that the replay recording attaches to (and that `/sessions/:id`
|
|
73
|
+
* keys on). `ReplaySdk.sessionId` (the orchestrator's recording id) is only set
|
|
74
|
+
* while a recording is mid-flight and reads `null` at submit time, so it is a
|
|
75
|
+
* fallback, not the primary. Returns `undefined` (not `null`) so the optional wire
|
|
76
|
+
* field is simply omitted when no session is active.
|
|
77
|
+
*/
|
|
78
|
+
function currentSessionId() {
|
|
79
|
+
return SessionManager.getExistingInstance()?.currentSessionId ?? ReplaySdk.sessionId ?? undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The host app version for by-version analytics (contract §1). Read from the
|
|
84
|
+
* SAME synchronous source the SDK's rating lane already uses
|
|
85
|
+
* (`SessionManager.currentSessionMetadata.appVersion`, populated from native
|
|
86
|
+
* device info) — NOT hardcoded, and NOT the SDK build version. `undefined` when
|
|
87
|
+
* no session metadata is available yet, so the optional field is omitted.
|
|
88
|
+
*/
|
|
89
|
+
function currentAppVersion() {
|
|
90
|
+
return SessionManager.getExistingInstance()?.currentSessionMetadata?.appVersion ?? undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Device platform as the `'android' | 'ios'` wire union (contract §1). Shared JS
|
|
95
|
+
* path — NOT platform-gated — so Android and iOS both stamp their own value.
|
|
96
|
+
* `Platform.OS` also yields `'windows' | 'macos' | 'web'`; those are out of the
|
|
97
|
+
* SDK's mobile scope and intentionally collapse to `undefined` (field omitted).
|
|
98
|
+
*/
|
|
99
|
+
function currentPlatform() {
|
|
100
|
+
return Platform.OS === 'android' || Platform.OS === 'ios' ? Platform.OS : undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Build the config-serve context (contract §1.3 query). ALWAYS carries `deviceId`
|
|
105
|
+
* — the backend keys per-device test previews on it, so omitting it would hide a
|
|
106
|
+
* "Send Test" preview from the very device it was queued for (T1). `platform`/
|
|
107
|
+
* `appVersion` ride along for server-side targeting; both honest, both omitted when
|
|
108
|
+
* unresolved. A caller-supplied `context` (manual show) overrides field-by-field.
|
|
109
|
+
*/
|
|
110
|
+
function buildConfigContext(engage, override) {
|
|
111
|
+
const identifiedUserId = engage.getIdentifiedUserId?.();
|
|
112
|
+
return {
|
|
113
|
+
deviceId: getDeviceId(),
|
|
114
|
+
...(currentPlatform() ? {
|
|
115
|
+
platform: currentPlatform()
|
|
116
|
+
} : {}),
|
|
117
|
+
...(currentAppVersion() ? {
|
|
118
|
+
appVersion: currentAppVersion()
|
|
119
|
+
} : {}),
|
|
120
|
+
...(identifiedUserId ? {
|
|
121
|
+
endUserId: identifiedUserId
|
|
122
|
+
} : {}),
|
|
123
|
+
...override
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Build the rating-funnel breakdown dimensions (ratings-rebuild CONTRACT §1.2 `dims`)
|
|
129
|
+
* from the SAME live session metadata the response builder reads — NOT hardcoded.
|
|
130
|
+
* Only honest, present values are included; `country`/`locale`/`acquisitionSource`
|
|
131
|
+
* are intentionally omitted here (no on-device source yet) so the backend reports
|
|
132
|
+
* them as absent rather than fabricated.
|
|
133
|
+
*/
|
|
134
|
+
function currentRatingDims() {
|
|
135
|
+
const meta = SessionManager.getExistingInstance()?.currentSessionMetadata;
|
|
136
|
+
const platform = currentPlatform();
|
|
137
|
+
return {
|
|
138
|
+
...(platform ? {
|
|
139
|
+
platform
|
|
140
|
+
} : {}),
|
|
141
|
+
...(meta?.appVersion ? {
|
|
142
|
+
appVersion: meta.appVersion
|
|
143
|
+
} : {}),
|
|
144
|
+
...(meta?.osVersion ? {
|
|
145
|
+
osVersion: meta.osVersion
|
|
146
|
+
} : {}),
|
|
147
|
+
...(meta?.deviceModel ? {
|
|
148
|
+
deviceModel: meta.deviceModel
|
|
149
|
+
} : {})
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The slice of the SDK facade the renderer consumes (the `engage` namespace).
|
|
155
|
+
* Matching this shape — rather than importing the facade — keeps the renderer a
|
|
156
|
+
* pure consumer of the foundation transport and trivially testable.
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Host-app RATING_PROMPT routing config. The store deeplink is NEVER hardcoded —
|
|
161
|
+
* the host supplies either a static `storeUrl` or an `onHighRating` callback (e.g.
|
|
162
|
+
* `Linking.openURL(...)` / native `requestReview()`), and an `onLowRating` for the
|
|
163
|
+
* feedback hand-off. The provider only decides WHICH callback to invoke.
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* The host's deep-link sink for an in-app CTA tap. The SDK NEVER opens a URL — it
|
|
168
|
+
* hands the resolved `deepLink` (and full message/cta) to the host, which decides
|
|
169
|
+
* how to navigate (e.g. `Linking.openURL` / a router push). Only fired for a CTA
|
|
170
|
+
* whose `action` resolves to a link with a `deepLink`.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
/** Imperative controller a host app uses to trigger a prompt / in-app message. */
|
|
174
|
+
|
|
175
|
+
const EngagePromptContext = /*#__PURE__*/createContext(null);
|
|
176
|
+
const DEFAULT_TYPES = ['NPS'];
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Provider that mounts the shared overlay and exposes the imperative controller
|
|
180
|
+
* via `useEngagePrompt()`.
|
|
181
|
+
*/
|
|
182
|
+
export function EngagePromptProvider({
|
|
183
|
+
engage,
|
|
184
|
+
defaultTypes,
|
|
185
|
+
ratingRouting,
|
|
186
|
+
onInAppDeepLink,
|
|
187
|
+
onInAppGameRequest,
|
|
188
|
+
previewPollMs,
|
|
189
|
+
children
|
|
190
|
+
}) {
|
|
191
|
+
const [active, setActive] = useState(null);
|
|
192
|
+
const [activeInApp, setActiveInApp] = useState(null);
|
|
193
|
+
const [inlineFallbackMessageId, setInlineFallbackMessageId] = useState(null);
|
|
194
|
+
const [inlinePlacementRevision, setInlinePlacementRevision] = useState(0);
|
|
195
|
+
const inlinePlacementRegistry = useMemo(createEngageInlinePlacementRegistry, []);
|
|
196
|
+
const shownInAppMessageIdRef = useRef(null);
|
|
197
|
+
// Resolved A/B arm for the active in-app message (D8/J6). Held in a ref: it is
|
|
198
|
+
// render-stable metadata (the chosen `spec` drives the view, the `variant` id
|
|
199
|
+
// rides the lifecycle events) and must not perturb the precedence that keys off
|
|
200
|
+
// `activeInApp`. `null` when no message is active (or it has no experiment).
|
|
201
|
+
const activeInAppVariantRef = useRef(null);
|
|
202
|
+
// Show-time screen of the currently-active campaign prompt (contract §1
|
|
203
|
+
// `screen`). Held in a ref alongside `active` — it is render-irrelevant
|
|
204
|
+
// metadata read only at submit, so it needs no re-render and must not perturb
|
|
205
|
+
// the campaign-vs-in-app precedence which keys off `active`/`activeInApp`.
|
|
206
|
+
const activeScreenRef = useRef(undefined);
|
|
207
|
+
const surveyStartedRef = useRef(null);
|
|
208
|
+
// [T1] Test previews bypass the throttle store and the backend re-serves them on
|
|
209
|
+
// EVERY config poll until TTL — great for "reopen the app and see it again", but it
|
|
210
|
+
// means a dismissed preview would re-appear on the next warm poll. This session set
|
|
211
|
+
// records previews the user already closed (dismiss/CTA) so we don't re-show the SAME
|
|
212
|
+
// one. It is in-memory only: a cold restart clears it, so reopening the app still
|
|
213
|
+
// shows the queued test (the intended QA behavior).
|
|
214
|
+
const consumedPreviewIds = useRef(new Set());
|
|
215
|
+
// [T1] Persistent dedupe for ONE-SHOT test delivery — survives cold restarts (unlike
|
|
216
|
+
// consumedPreviewIds above). A testRunId is recorded here AFTER it actually renders, so
|
|
217
|
+
// reopening the app does NOT re-show a test the device already displayed. This is the
|
|
218
|
+
// fix for "close/open and the old test re-appears, and they stack up". Separate from the
|
|
219
|
+
// throttle store so production frequency caps never block a fresh test and vice-versa.
|
|
220
|
+
const seenTestsRef = useRef(null);
|
|
221
|
+
if (seenTestsRef.current === null) {
|
|
222
|
+
seenTestsRef.current = new EngageTestSeenStore();
|
|
223
|
+
}
|
|
224
|
+
// One persistent throttle store for the provider lifetime — SHARED by campaigns
|
|
225
|
+
// and in-app messages so both honor the same per-id frequency caps.
|
|
226
|
+
const storeRef = useRef(null);
|
|
227
|
+
if (storeRef.current === null) {
|
|
228
|
+
storeRef.current = new EngageThrottleStore();
|
|
229
|
+
}
|
|
230
|
+
const types = defaultTypes ?? DEFAULT_TYPES;
|
|
231
|
+
|
|
232
|
+
// ─── Reusable submit state machine (Slice D5) ────────────────────────────
|
|
233
|
+
// ONE machine for EVERY question type. `responseIdRef` is the idempotency key,
|
|
234
|
+
// generated once per prompt and REUSED on retry so a re-send can't duplicate.
|
|
235
|
+
// `submitCtxRef` holds the campaign+result so retry re-runs the same submit.
|
|
236
|
+
const [submitStatus, setSubmitStatus] = useState({
|
|
237
|
+
phase: 'idle'
|
|
238
|
+
});
|
|
239
|
+
const responseIdRef = useRef(null);
|
|
240
|
+
const submitCtxRef = useRef(null);
|
|
241
|
+
const successTimerRef = useRef(null);
|
|
242
|
+
const resetSubmit = useCallback(() => {
|
|
243
|
+
if (successTimerRef.current) {
|
|
244
|
+
clearTimeout(successTimerRef.current);
|
|
245
|
+
successTimerRef.current = null;
|
|
246
|
+
}
|
|
247
|
+
responseIdRef.current = null;
|
|
248
|
+
submitCtxRef.current = null;
|
|
249
|
+
setSubmitStatus({
|
|
250
|
+
phase: 'idle'
|
|
251
|
+
});
|
|
252
|
+
}, []);
|
|
253
|
+
|
|
254
|
+
// Single campaign tracking lane (mirrors trackInApp). `impression` on show,
|
|
255
|
+
// `completion` on submit, `dismiss` on close — the §2.5 analytics events that
|
|
256
|
+
// back the response-rate / completion KPIs (P3-e #2). Distinct from the local
|
|
257
|
+
// throttle store, which only counts impressions for frequency caps.
|
|
258
|
+
const trackCampaign = useCallback((campaign, eventType) => {
|
|
259
|
+
try {
|
|
260
|
+
engage.trackEvent({
|
|
261
|
+
campaignId: campaign.id,
|
|
262
|
+
channel: 'inapp',
|
|
263
|
+
type: eventType,
|
|
264
|
+
deviceId: getDeviceId()
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
__DEV__ && logger.debug('[Engage] trackEvent failed:', err?.message);
|
|
268
|
+
}
|
|
269
|
+
}, [engage]);
|
|
270
|
+
const trackSurveyStage = useCallback((campaign, stage) => {
|
|
271
|
+
if (campaign.type === 'RATING_PROMPT' || campaign.type === 'RATINGS_PROMPT') return;
|
|
272
|
+
try {
|
|
273
|
+
engage.trackSurveyImpression?.({
|
|
274
|
+
surveyId: campaign.id,
|
|
275
|
+
stage,
|
|
276
|
+
sessionId: currentSessionId(),
|
|
277
|
+
deviceId: getDeviceId(),
|
|
278
|
+
platform: currentPlatform(),
|
|
279
|
+
appVersion: currentAppVersion(),
|
|
280
|
+
screen: activeScreenRef.current
|
|
281
|
+
});
|
|
282
|
+
} catch (err) {
|
|
283
|
+
__DEV__ && logger.debug('[Engage] survey impression failed:', err?.message);
|
|
284
|
+
}
|
|
285
|
+
}, [engage]);
|
|
286
|
+
const isRatingType = type => type === 'RATING_PROMPT' || type === 'RATINGS_PROMPT';
|
|
287
|
+
|
|
288
|
+
// Rating-funnel emit lane (ratings-rebuild CONTRACT §1.2). Distinct from
|
|
289
|
+
// trackCampaign (the §2.5 in-app analytics lane) and from submitRating (the D1
|
|
290
|
+
// app-rating lane): these are dimensioned FACTS feeding the Overview funnel and
|
|
291
|
+
// are NEVER counted as responses. `stars` rides only on `rating_selected`.
|
|
292
|
+
const emitRatingFunnel = useCallback((campaign, type, extra) => {
|
|
293
|
+
try {
|
|
294
|
+
engage.emitRatingEvent?.({
|
|
295
|
+
type,
|
|
296
|
+
sessionId: currentSessionId(),
|
|
297
|
+
userId: engage.getIdentifiedUserId?.(),
|
|
298
|
+
promptId: campaign.id,
|
|
299
|
+
triggerId: campaign.trigger,
|
|
300
|
+
...(extra?.stars !== undefined ? {
|
|
301
|
+
stars: extra.stars
|
|
302
|
+
} : {}),
|
|
303
|
+
dims: currentRatingDims()
|
|
304
|
+
});
|
|
305
|
+
} catch (err) {
|
|
306
|
+
__DEV__ && logger.debug('[Engage] emitRatingEvent failed:', err?.message);
|
|
307
|
+
}
|
|
308
|
+
}, [engage]);
|
|
309
|
+
const dismissEngagePrompt = useCallback(() => {
|
|
310
|
+
setActive(current => {
|
|
311
|
+
if (current) {
|
|
312
|
+
trackCampaign(current, 'dismiss');
|
|
313
|
+
// Rating funnel: a close without a selection is a funnel drop.
|
|
314
|
+
if (isRatingType(current.type)) emitRatingFunnel(current, 'rating_prompt_dismissed');
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
});
|
|
318
|
+
activeScreenRef.current = undefined;
|
|
319
|
+
surveyStartedRef.current = null;
|
|
320
|
+
resetSubmit();
|
|
321
|
+
}, [trackCampaign, resetSubmit, emitRatingFunnel]);
|
|
322
|
+
|
|
323
|
+
// The actual submit run — used by both the first submit and a retry. Reads
|
|
324
|
+
// `submitCtxRef` + `responseIdRef` so a retry re-sends with the SAME idempotency
|
|
325
|
+
// key. Resolves to `success` ONLY on confirmed persistence; `error` on failure.
|
|
326
|
+
const runSubmit = useCallback(async () => {
|
|
327
|
+
const ctx = submitCtxRef.current;
|
|
328
|
+
if (!ctx) return;
|
|
329
|
+
const {
|
|
330
|
+
campaign,
|
|
331
|
+
result
|
|
332
|
+
} = ctx;
|
|
333
|
+
const store = storeRef.current;
|
|
334
|
+
const responseId = responseIdRef.current ?? (responseIdRef.current = ratingUuid());
|
|
335
|
+
setSubmitStatus({
|
|
336
|
+
phase: 'submitting',
|
|
337
|
+
stage: 'saving'
|
|
338
|
+
});
|
|
339
|
+
try {
|
|
340
|
+
if (isRatingType(campaign.type)) {
|
|
341
|
+
// RATING_PROMPT submits via the EXISTING app-rating lane (D1), NOT
|
|
342
|
+
// submitResponse, with a client clientRatingId for idempotency. Awaited
|
|
343
|
+
// so the loading state reflects the real round-trip.
|
|
344
|
+
const rating = typeof result.score === 'number' ? result.score : 0;
|
|
345
|
+
await Promise.resolve(engage.submitRating?.({
|
|
346
|
+
rating,
|
|
347
|
+
source: 'prompt',
|
|
348
|
+
clientRatingId: responseId
|
|
349
|
+
}));
|
|
350
|
+
// Funnel: user picked 1–5★ (carries stars). Emitted regardless of route.
|
|
351
|
+
emitRatingFunnel(campaign, 'rating_selected', {
|
|
352
|
+
stars: rating
|
|
353
|
+
});
|
|
354
|
+
// Routing decided by the view (`route`), executed against host-supplied
|
|
355
|
+
// callbacks/URL — the deeplink is never hardcoded.
|
|
356
|
+
if (result.route === 'store') {
|
|
357
|
+
// D5: prefer the genuinely-native in-app review sheet. `store_redirect_clicked`
|
|
358
|
+
// fires ONLY when an actual store route resolves (native review ran, or a
|
|
359
|
+
// host-supplied deeplink/callback executed) — never speculatively.
|
|
360
|
+
let redirected = false;
|
|
361
|
+
if (engage.requestStoreReview) {
|
|
362
|
+
redirected = await engage.requestStoreReview();
|
|
363
|
+
}
|
|
364
|
+
const storeUrl = campaign.storeUrl ?? ratingRouting?.storeUrl;
|
|
365
|
+
if (ratingRouting?.onHighRating) {
|
|
366
|
+
ratingRouting.onHighRating({
|
|
367
|
+
rating,
|
|
368
|
+
campaign,
|
|
369
|
+
storeUrl
|
|
370
|
+
});
|
|
371
|
+
redirected = true;
|
|
372
|
+
} else if (!redirected && storeUrl) {
|
|
373
|
+
redirected = await Linking.openURL(storeUrl).then(() => true).catch(() => false);
|
|
374
|
+
}
|
|
375
|
+
if (redirected) emitRatingFunnel(campaign, 'store_redirect_clicked');
|
|
376
|
+
} else if (result.route === 'feedback') {
|
|
377
|
+
ratingRouting?.onLowRating?.({
|
|
378
|
+
rating,
|
|
379
|
+
campaign
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
// [v2] response context (contract §1): session linkage + originating
|
|
384
|
+
// screen + platform + app version. All optional; omitted when unresolved.
|
|
385
|
+
// We send ONLY the new response fact + the sessionId; replay/errors/network
|
|
386
|
+
// are NOT re-sent — the read side joins them by sessionId.
|
|
387
|
+
const input = Array.isArray(result.answers) ? {
|
|
388
|
+
surveyId: campaign.id,
|
|
389
|
+
text: result.reason,
|
|
390
|
+
answers: toWireAnswers(result.answers),
|
|
391
|
+
deviceId: getDeviceId(),
|
|
392
|
+
sessionId: currentSessionId(),
|
|
393
|
+
screen: activeScreenRef.current,
|
|
394
|
+
platform: currentPlatform(),
|
|
395
|
+
appVersion: currentAppVersion()
|
|
396
|
+
} : {
|
|
397
|
+
surveyId: campaign.id,
|
|
398
|
+
score: result.score,
|
|
399
|
+
text: result.reason,
|
|
400
|
+
tags: result.tags,
|
|
401
|
+
deviceId: getDeviceId(),
|
|
402
|
+
sessionId: currentSessionId(),
|
|
403
|
+
screen: activeScreenRef.current,
|
|
404
|
+
platform: currentPlatform(),
|
|
405
|
+
appVersion: currentAppVersion()
|
|
406
|
+
};
|
|
407
|
+
const drafts = result.attachments ?? [];
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Bug-report lane — opt in per campaign via `fileAsBugReport`.
|
|
411
|
+
*
|
|
412
|
+
* A FEEDBACK campaign fired by `shake_device` is almost always "something is
|
|
413
|
+
* broken", not "how do you feel", and those are different products: a bug report
|
|
414
|
+
* gets a status, a priority and an assignee on /diagnose/bug-reports, while a survey
|
|
415
|
+
* response is counted in aggregate and cannot be triaged.
|
|
416
|
+
*
|
|
417
|
+
* Routed INSTEAD of submitResponse rather than in addition — a dual write would
|
|
418
|
+
* create two rows for one submission and double-count the campaign on the Engage
|
|
419
|
+
* side.
|
|
420
|
+
*
|
|
421
|
+
* `responseId` doubles as the idempotency key so a retried submit cannot file the
|
|
422
|
+
* same report twice (BugReport.clientReportId is @unique).
|
|
423
|
+
*
|
|
424
|
+
* Falls through to the normal lane when the host facade predates `reportBugDetailed`
|
|
425
|
+
* — an older app bundling a newer config degrades to existing behaviour instead of
|
|
426
|
+
* dropping the user's report on the floor.
|
|
427
|
+
*/
|
|
428
|
+
const bugLane = campaign.fileAsBugReport && typeof engage.reportBugDetailed === 'function' ? engage.reportBugDetailed : null;
|
|
429
|
+
if (bugLane) {
|
|
430
|
+
const outcome = await bugLane({
|
|
431
|
+
message: result.reason ?? '',
|
|
432
|
+
title: campaign.name,
|
|
433
|
+
clientReportId: responseId
|
|
434
|
+
});
|
|
435
|
+
// Surface a refusal as a throw so the existing retry/error UI handles it; a
|
|
436
|
+
// silent success here would tell the user their report was filed when it wasn't.
|
|
437
|
+
if (outcome && typeof outcome === 'object' && 'e' in outcome) {
|
|
438
|
+
throw new Error(`bug report failed: ${outcome.e}`);
|
|
439
|
+
}
|
|
440
|
+
} else if (engage.submitResponseConfirmed) {
|
|
441
|
+
// Confirmed lane: awaits real persistence (presign+PUT bytes → response
|
|
442
|
+
// POST), reports stages, idempotent on responseId, throws on failure.
|
|
443
|
+
await engage.submitResponseConfirmed(input, drafts, {
|
|
444
|
+
responseId,
|
|
445
|
+
onStage: stage => setSubmitStatus({
|
|
446
|
+
phase: 'submitting',
|
|
447
|
+
stage
|
|
448
|
+
})
|
|
449
|
+
});
|
|
450
|
+
} else if (drafts.length > 0 && engage.submitResponseWithAttachments) {
|
|
451
|
+
// Fallback (older facade): fire-and-forget — resolves immediately.
|
|
452
|
+
engage.submitResponseWithAttachments(input, drafts);
|
|
453
|
+
} else {
|
|
454
|
+
engage.submitResponse(input);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
store?.markCompleted(campaign.id);
|
|
458
|
+
trackCampaign(campaign, 'completion');
|
|
459
|
+
setSubmitStatus({
|
|
460
|
+
phase: 'success'
|
|
461
|
+
});
|
|
462
|
+
// Brief success beat, then close + reset.
|
|
463
|
+
successTimerRef.current = setTimeout(() => {
|
|
464
|
+
setActive(null);
|
|
465
|
+
activeScreenRef.current = undefined;
|
|
466
|
+
resetSubmit();
|
|
467
|
+
}, 1100);
|
|
468
|
+
} catch (err) {
|
|
469
|
+
logger.warn('[Engage] submit failed:', err?.message);
|
|
470
|
+
setSubmitStatus({
|
|
471
|
+
phase: 'error',
|
|
472
|
+
message: err?.message
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}, [engage, trackCampaign, ratingRouting, resetSubmit, emitRatingFunnel]);
|
|
476
|
+
const handleSubmit = useCallback((campaign, result) => {
|
|
477
|
+
// Guard double-submit: ignore re-fires once a submit is in flight or done.
|
|
478
|
+
if (submitCtxRef.current && responseIdRef.current) return;
|
|
479
|
+
submitCtxRef.current = {
|
|
480
|
+
campaign,
|
|
481
|
+
result
|
|
482
|
+
};
|
|
483
|
+
void runSubmit();
|
|
484
|
+
}, [runSubmit]);
|
|
485
|
+
const closeAfterSubmit = useCallback(() => {
|
|
486
|
+
setActive(null);
|
|
487
|
+
activeScreenRef.current = undefined;
|
|
488
|
+
resetSubmit();
|
|
489
|
+
}, [resetSubmit]);
|
|
490
|
+
const showEngagePrompt = useCallback(async options => {
|
|
491
|
+
const store = storeRef.current;
|
|
492
|
+
if (!store) return false;
|
|
493
|
+
try {
|
|
494
|
+
const config = await engage.fetchConfig(options?.context);
|
|
495
|
+
if (!config || !Array.isArray(config.campaigns)) return false;
|
|
496
|
+
const campaign = selectCampaignToRender(config.campaigns, store, {
|
|
497
|
+
// A behavioral-trigger fire (`options.trigger`) is type-agnostic:
|
|
498
|
+
// the trigger itself selects the campaign, so don't layer the
|
|
499
|
+
// NPS-first default on top (it would drop FEEDBACK/CSAT/etc.).
|
|
500
|
+
// Manual fires keep the provider default unless overridden.
|
|
501
|
+
types: options?.types ?? (options?.trigger ? undefined : types),
|
|
502
|
+
screen: options?.screen,
|
|
503
|
+
trigger: options?.trigger,
|
|
504
|
+
seconds: options?.seconds,
|
|
505
|
+
event: options?.event,
|
|
506
|
+
action: options?.action
|
|
507
|
+
});
|
|
508
|
+
if (!campaign) {
|
|
509
|
+
// Name the inputs so a silent mismatch (wrong trigger name, throttle
|
|
510
|
+
// suppression, type filter) is diagnosable from device logs alone.
|
|
511
|
+
__DEV__ && logger.debug(`[Engage] no eligible campaign to render (trigger=${options?.trigger ?? '—'} ` + `candidates=${config.campaigns.length} ` + `[${config.campaigns.map(c => `${c.type}:${c.trigger ?? '—'}`).join(', ')}])`);
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Record the impression up front so throttle counts it even if the
|
|
516
|
+
// user backgrounds the app before submitting.
|
|
517
|
+
store.recordImpression(campaign.id);
|
|
518
|
+
// Emit the §2.5 impression event (P3-e #2) so the dashboard's
|
|
519
|
+
// response-rate / completion KPIs have a real denominator — the
|
|
520
|
+
// prompt path previously only counted impressions locally.
|
|
521
|
+
trackCampaign(campaign, 'impression');
|
|
522
|
+
// Rating funnel (CONTRACT §1.1): selection passed the throttle/anti-
|
|
523
|
+
// annoyance gate (→ eligible) and we are about to render (→ shown).
|
|
524
|
+
if (isRatingType(campaign.type)) {
|
|
525
|
+
emitRatingFunnel(campaign, 'rating_prompt_eligible');
|
|
526
|
+
emitRatingFunnel(campaign, 'rating_prompt_shown');
|
|
527
|
+
}
|
|
528
|
+
// Stamp the show-time screen alongside the active campaign so
|
|
529
|
+
// handleSubmit can attribute the response to its originating screen.
|
|
530
|
+
activeScreenRef.current = options?.screen;
|
|
531
|
+
surveyStartedRef.current = null;
|
|
532
|
+
trackSurveyStage(campaign, 'shown');
|
|
533
|
+
resetSubmit();
|
|
534
|
+
setActive(campaign);
|
|
535
|
+
return true;
|
|
536
|
+
} catch (err) {
|
|
537
|
+
logger.warn('[Engage] showEngagePrompt failed:', err?.message);
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
}, [engage, types, trackCampaign, trackSurveyStage, emitRatingFunnel]);
|
|
541
|
+
|
|
542
|
+
// ─── In-app message lifecycle (the second Engage family, §2.4/§2.5) ──────
|
|
543
|
+
// Reuses the SAME transport (`trackEvent`), the SAME throttle store, and the
|
|
544
|
+
// SAME provider — NOT a parallel provider. Events: impression on show, click
|
|
545
|
+
// on CTA tap, completion on a finished tour, dismiss on close/skip.
|
|
546
|
+
|
|
547
|
+
const trackInApp = useCallback((message, eventType, extraMeta) => {
|
|
548
|
+
try {
|
|
549
|
+
// A/B attribution (D8/J6): when the active message resolved to an
|
|
550
|
+
// experiment arm, tag every lifecycle event with the chosen variant
|
|
551
|
+
// via the existing optional `meta` field — NO event-schema change
|
|
552
|
+
// (EngageEventUpload already carries `meta`; the backend EngageEvent
|
|
553
|
+
// accepts it). Plain (non-experiment) messages send no variant key.
|
|
554
|
+
const variant = activeInAppVariantRef.current?.variant;
|
|
555
|
+
// [T1] Test-preview tagging: a preview-flagged message stamps
|
|
556
|
+
// `previewId` + `isTest` + `source` so (a) the backend CONSUMES the
|
|
557
|
+
// matching preview row on the impression and (b) production KPIs
|
|
558
|
+
// exclude the traffic. Normal campaign messages omit all of it.
|
|
559
|
+
const isPreview = message.preview === true || message.isTest === true;
|
|
560
|
+
const meta = {
|
|
561
|
+
...(variant ? {
|
|
562
|
+
variant
|
|
563
|
+
} : {}),
|
|
564
|
+
// testRunId correlates a specific "Send Test" run to its render/click/
|
|
565
|
+
// dismiss in the dashboard; rides the existing meta field (no schema churn).
|
|
566
|
+
...(message.testRunId ? {
|
|
567
|
+
testRunId: message.testRunId
|
|
568
|
+
} : {}),
|
|
569
|
+
...(extraMeta ?? {})
|
|
570
|
+
};
|
|
571
|
+
engage.trackEvent({
|
|
572
|
+
campaignId: message.id,
|
|
573
|
+
channel: 'inapp',
|
|
574
|
+
type: eventType,
|
|
575
|
+
deviceId: getDeviceId(),
|
|
576
|
+
...(message.previewId ? {
|
|
577
|
+
previewId: message.previewId
|
|
578
|
+
} : {}),
|
|
579
|
+
...(isPreview ? {
|
|
580
|
+
isTest: true,
|
|
581
|
+
source: 'test_preview'
|
|
582
|
+
} : {}),
|
|
583
|
+
...(variant ? {
|
|
584
|
+
variantId: variant
|
|
585
|
+
} : {}),
|
|
586
|
+
...(Object.keys(meta).length > 0 ? {
|
|
587
|
+
meta
|
|
588
|
+
} : {})
|
|
589
|
+
});
|
|
590
|
+
} catch (err) {
|
|
591
|
+
__DEV__ && logger.debug('[Engage] in-app trackEvent failed:', err?.message);
|
|
592
|
+
}
|
|
593
|
+
}, [engage]);
|
|
594
|
+
|
|
595
|
+
// [T1] In-app message actually mounted on screen. The impression event IS the test
|
|
596
|
+
// ACK to the backend (which consumes the preview row → 'rendered'). We ALSO persist the
|
|
597
|
+
// testRunId locally so a cold restart can't re-show it before the ACK is processed
|
|
598
|
+
// server-side — the one-shot guarantee survives a flaky/slow network.
|
|
599
|
+
const handleInAppShow = useCallback(message => {
|
|
600
|
+
// A slot can be replaced or degrade to an overlay while the same message
|
|
601
|
+
// remains active. Treat that as one mount lifecycle, not two impressions.
|
|
602
|
+
if (shownInAppMessageIdRef.current === message.id) return;
|
|
603
|
+
shownInAppMessageIdRef.current = message.id;
|
|
604
|
+
trackInApp(message, 'impression');
|
|
605
|
+
if (message.preview === true || message.isTest === true) {
|
|
606
|
+
const runId = message.testRunId ?? message.previewId ?? message.id;
|
|
607
|
+
seenTestsRef.current?.markSeen(runId);
|
|
608
|
+
// Eager-flush so the backend consumes the one-shot preview row NOW — a fast
|
|
609
|
+
// close→kill→reopen must not re-serve a still-`delivered` test.
|
|
610
|
+
engage.flushEvents?.();
|
|
611
|
+
__DEV__ && logger.debug(`[Engage] test ${runId} render displayed — ACK sent (impression), flushed`);
|
|
612
|
+
}
|
|
613
|
+
}, [trackInApp, engage]);
|
|
614
|
+
const finalizeInAppMessage = useCallback(eventType => {
|
|
615
|
+
setActiveInApp(current => {
|
|
616
|
+
if (current) {
|
|
617
|
+
const isTest = current.preview === true || current.isTest === true;
|
|
618
|
+
const runId = current.testRunId ?? current.previewId ?? current.id;
|
|
619
|
+
__DEV__ && logger.debug(`[Engage] in-app ${eventType}${isTest ? ` (test ${runId})` : ''}`);
|
|
620
|
+
trackInApp(current, eventType);
|
|
621
|
+
if (isTest) {
|
|
622
|
+
consumedPreviewIds.current.add(current.previewId ?? current.id);
|
|
623
|
+
seenTestsRef.current?.markSeen(runId);
|
|
624
|
+
engage.flushEvents?.();
|
|
625
|
+
__DEV__ && logger.debug(`[Engage] test ${runId} ${eventType} persisted + ACK flushed`);
|
|
626
|
+
} else {
|
|
627
|
+
// Stamp the SERVED revision: without it the completion can never be invalidated,
|
|
628
|
+
// and an edited campaign would never return to a device that closed the old one.
|
|
629
|
+
storeRef.current?.markCompleted(current.id, Date.now(), current.revision);
|
|
630
|
+
engage.flushEvents?.();
|
|
631
|
+
__DEV__ && logger.debug(`[Engage] in-app ${current.id} ${eventType} — marked done on device`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return null;
|
|
635
|
+
});
|
|
636
|
+
// Clear the resolved A/B arm after the lifecycle event has read it.
|
|
637
|
+
shownInAppMessageIdRef.current = null;
|
|
638
|
+
activeInAppVariantRef.current = null;
|
|
639
|
+
}, [trackInApp, engage]);
|
|
640
|
+
const dismissInAppMessage = useCallback(() => {
|
|
641
|
+
finalizeInAppMessage('dismiss');
|
|
642
|
+
}, [finalizeInAppMessage]);
|
|
643
|
+
const completeInAppMessage = useCallback(() => {
|
|
644
|
+
finalizeInAppMessage('completion');
|
|
645
|
+
}, [finalizeInAppMessage]);
|
|
646
|
+
const handleInAppCta = useCallback((message, cta) => {
|
|
647
|
+
if (shouldTrackInAppCta(cta)) trackInApp(message, 'click');
|
|
648
|
+
// Deep-link opening is the host's job — surface it, never open it here.
|
|
649
|
+
if (cta.action === 'link') {
|
|
650
|
+
if (!cta.deepLink) {
|
|
651
|
+
// Misconfigured link CTA (no deepLink) — observable, not silent (T1 G17).
|
|
652
|
+
logger.warn('[Engage] link CTA has no deepLink');
|
|
653
|
+
trackInApp(message, 'cta_open_failed', {
|
|
654
|
+
reason: 'missing_deeplink'
|
|
655
|
+
});
|
|
656
|
+
} else if (!onInAppDeepLink) {
|
|
657
|
+
// Host wired no deep-link sink — the link can't open. Diagnose it.
|
|
658
|
+
logger.warn('[Engage] link CTA but no onInAppDeepLink handler supplied');
|
|
659
|
+
trackInApp(message, 'cta_open_failed', {
|
|
660
|
+
reason: 'no_handler'
|
|
661
|
+
});
|
|
662
|
+
} else {
|
|
663
|
+
try {
|
|
664
|
+
onInAppDeepLink({
|
|
665
|
+
message,
|
|
666
|
+
cta,
|
|
667
|
+
deepLink: cta.deepLink
|
|
668
|
+
});
|
|
669
|
+
} catch (err) {
|
|
670
|
+
logger.warn('[Engage] onInAppDeepLink threw:', err?.message);
|
|
671
|
+
trackInApp(message, 'cta_open_failed', {
|
|
672
|
+
reason: err?.message ?? 'handler_threw'
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
// A test preview the user acted on is done — don't re-show it next poll AND
|
|
678
|
+
// persist it durably (a CTA tap is as final as a close), then flush the ACK.
|
|
679
|
+
if (message.preview === true || message.isTest === true) {
|
|
680
|
+
const runId = message.testRunId ?? message.previewId ?? message.id;
|
|
681
|
+
consumedPreviewIds.current.add(message.previewId ?? message.id);
|
|
682
|
+
seenTestsRef.current?.markSeen(runId);
|
|
683
|
+
engage.flushEvents?.();
|
|
684
|
+
__DEV__ && logger.debug(`[Engage] test ${runId} CTA — persisted locally + ACK flushed`);
|
|
685
|
+
} else {
|
|
686
|
+
// Production message: a CTA tap is as final as a close — don't re-show it.
|
|
687
|
+
storeRef.current?.markCompleted(message.id, Date.now(), message.revision);
|
|
688
|
+
engage.flushEvents?.();
|
|
689
|
+
__DEV__ && logger.debug(`[Engage] in-app ${message.id} CTA tapped — marked done on device`);
|
|
690
|
+
}
|
|
691
|
+
setActiveInApp(null);
|
|
692
|
+
// Any enabled click event above already read the arm; clear it now.
|
|
693
|
+
shownInAppMessageIdRef.current = null;
|
|
694
|
+
activeInAppVariantRef.current = null;
|
|
695
|
+
}, [trackInApp, onInAppDeepLink, engage]);
|
|
696
|
+
|
|
697
|
+
// [T1] Pick the ONE test preview to render from a fetched config: drop any already
|
|
698
|
+
// displayed (persistent seen store) or closed-this-session, then take the LATEST by
|
|
699
|
+
// createdAt. One-shot + latest-only is what stops the "tests stack up 1,2,3…" bug.
|
|
700
|
+
const pickLatestPreview = useCallback(messages => {
|
|
701
|
+
const latest = selectLatestUnseenTest(messages, {
|
|
702
|
+
seen: runId => seenTestsRef.current?.has(runId) ?? false,
|
|
703
|
+
consumed: key => consumedPreviewIds.current.has(key)
|
|
704
|
+
});
|
|
705
|
+
if (latest) logger.debug(`[Engage] selected latest test ${testRunIdOf(latest)}`);
|
|
706
|
+
return latest;
|
|
707
|
+
}, []);
|
|
708
|
+
|
|
709
|
+
// [T1] Render a test preview IMMEDIATELY — bypassing trigger/throttle/schedule/
|
|
710
|
+
// sample/variant. No throttle write (a preview must stay re-showable until it is
|
|
711
|
+
// actually rendered + its impression consumes it server-side). Idempotent: if this
|
|
712
|
+
// exact preview is already on screen, don't re-mount (avoids a duplicate impression).
|
|
713
|
+
const showPreview = useCallback(preview => {
|
|
714
|
+
// PRECEDENCE: a campaign prompt owns the screen — defer (the backend re-serves
|
|
715
|
+
// the preview on every poll until TTL, so the next foreground retries).
|
|
716
|
+
if (active !== null) {
|
|
717
|
+
__DEV__ && logger.debug('[Engage] campaign prompt active — preview deferred');
|
|
718
|
+
return false;
|
|
719
|
+
}
|
|
720
|
+
if (activeInApp?.id === preview.id) return true;
|
|
721
|
+
const runId = preview.testRunId ?? preview.previewId ?? preview.id;
|
|
722
|
+
// Already closed this preview this session — don't re-show on the next poll.
|
|
723
|
+
if (consumedPreviewIds.current.has(preview.previewId ?? preview.id)) {
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
// [T1] One-shot: already DISPLAYED on this device (persisted across restarts) —
|
|
727
|
+
// never re-show, even if the backend briefly re-serves a not-yet-ACKed row.
|
|
728
|
+
if (seenTestsRef.current?.has(runId)) {
|
|
729
|
+
__DEV__ && logger.debug(`[Engage] test ${runId} already displayed on device — skip`);
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
activeInAppVariantRef.current = null;
|
|
733
|
+
setActiveInApp(preview);
|
|
734
|
+
__DEV__ && logger.debug(`[Engage] test ${runId} render started`);
|
|
735
|
+
return true;
|
|
736
|
+
}, [active, activeInApp]);
|
|
737
|
+
const showInAppMessage = useCallback(async options => {
|
|
738
|
+
const store = storeRef.current;
|
|
739
|
+
if (!store) return false;
|
|
740
|
+
// PRECEDENCE: a campaign prompt on screen wins — never stack an in-app
|
|
741
|
+
// message over an open survey/NPS/rating prompt.
|
|
742
|
+
if (active !== null) {
|
|
743
|
+
__DEV__ && logger.debug('[Engage] campaign prompt active — in-app message deferred');
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
try {
|
|
747
|
+
const config = await engage.fetchConfig(buildConfigContext(engage, options?.context));
|
|
748
|
+
if (!config || !Array.isArray(config.inAppMessages)) return false;
|
|
749
|
+
|
|
750
|
+
// [T1] A queued test preview wins immediately, bypassing throttle/variant.
|
|
751
|
+
// Pick the LATEST unseen one (one-shot dedupe) — never stack old tests.
|
|
752
|
+
const preview = pickLatestPreview(config.inAppMessages);
|
|
753
|
+
if (preview) return showPreview(preview);
|
|
754
|
+
|
|
755
|
+
// Normal selection runs over NON-preview messages only — a preview must
|
|
756
|
+
// never enter the throttle store (it would falsely cap a real campaign id).
|
|
757
|
+
const normal = config.inAppMessages.filter(m => !(m.preview === true || m.isTest === true));
|
|
758
|
+
const message = selectInAppToRender(normal, store, {
|
|
759
|
+
screen: options?.screen,
|
|
760
|
+
trigger: options?.trigger,
|
|
761
|
+
seconds: options?.seconds,
|
|
762
|
+
event: options?.event,
|
|
763
|
+
action: options?.action
|
|
764
|
+
});
|
|
765
|
+
if (!message) {
|
|
766
|
+
__DEV__ && logger.debug('[Engage] no eligible in-app message to render');
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// A/B variant selection (D8/J6): deterministically bucket this
|
|
771
|
+
// device into arm A (base spec) or B (experiment.variantB) BEFORE
|
|
772
|
+
// showing, so the impression event (and click/dismiss) attribute to
|
|
773
|
+
// the arm the user actually saw. Only retained for attribution when
|
|
774
|
+
// the message actually carries an enabled experiment; otherwise the
|
|
775
|
+
// resolved spec is just the base spec and no variant key is emitted.
|
|
776
|
+
const resolved = selectInAppVariant(message, getDeviceId());
|
|
777
|
+
activeInAppVariantRef.current = message.experiment?.enabled ? resolved : null;
|
|
778
|
+
// Record up front so the throttle counts it (impression also emitted
|
|
779
|
+
// by the view's onShow → trackEvent for the analytics lane). Pass the
|
|
780
|
+
// content revision so an edited campaign starts a fresh cap generation.
|
|
781
|
+
store.recordImpression(message.id, Date.now(), message.revision);
|
|
782
|
+
setActiveInApp(message);
|
|
783
|
+
return true;
|
|
784
|
+
} catch (err) {
|
|
785
|
+
logger.warn('[Engage] showInAppMessage failed:', err?.message);
|
|
786
|
+
return false;
|
|
787
|
+
}
|
|
788
|
+
}, [engage, active, showPreview, pickLatestPreview]);
|
|
789
|
+
|
|
790
|
+
// ─── Cold-start + foreground preview check (T1) ──────────────────────────
|
|
791
|
+
// "Send Test → reopen the app → see it immediately, EVERY time": the SDK fetches
|
|
792
|
+
// config (deviceId in context, HTTP cache-bypassed) on mount AND on every
|
|
793
|
+
// AppState→active, and renders any queued preview at once — no trigger, no throttle,
|
|
794
|
+
// no schedule. The backend keeps serving the preview on every poll until its TTL, so
|
|
795
|
+
// a tester sees it on each reopen (rendering records lifecycle but does not consume).
|
|
796
|
+
const checkForPreview = useCallback(async () => {
|
|
797
|
+
if (active !== null) return;
|
|
798
|
+
try {
|
|
799
|
+
const config = await engage.fetchConfig(buildConfigContext(engage));
|
|
800
|
+
// One-shot + latest-only: render the newest test not already displayed.
|
|
801
|
+
const preview = pickLatestPreview(config?.inAppMessages ?? []);
|
|
802
|
+
if (preview) showPreview(preview);
|
|
803
|
+
} catch (err) {
|
|
804
|
+
logger.warn('[Engage] preview check failed:', err?.message);
|
|
805
|
+
}
|
|
806
|
+
}, [engage, active, showPreview, pickLatestPreview]);
|
|
807
|
+
useEffect(() => {
|
|
808
|
+
// Drop stale seen-test entries (past TTL) so the persistent set stays bounded.
|
|
809
|
+
seenTestsRef.current?.prune();
|
|
810
|
+
void checkForPreview();
|
|
811
|
+
const onLifecycle = state => {
|
|
812
|
+
if (state === 'active') void checkForPreview();
|
|
813
|
+
};
|
|
814
|
+
appLifecycle.addListener(onLifecycle);
|
|
815
|
+
return () => appLifecycle.removeListener(onLifecycle);
|
|
816
|
+
}, [checkForPreview]);
|
|
817
|
+
|
|
818
|
+
// DEV/TEST warm-foreground poll (T1): covers "Send Test while the app is already
|
|
819
|
+
// open" — no background→foreground edge fires, so without this you'd have to switch
|
|
820
|
+
// apps to see it. Only runs when the host opts in via `previewPollMs` (unset in prod).
|
|
821
|
+
useEffect(() => {
|
|
822
|
+
if (!previewPollMs || previewPollMs <= 0) return;
|
|
823
|
+
__DEV__ && logger.debug(`[Engage] test-preview warm poll every ${previewPollMs}ms (dev)`);
|
|
824
|
+
const interval = setInterval(() => {
|
|
825
|
+
void checkForPreview();
|
|
826
|
+
}, previewPollMs);
|
|
827
|
+
return () => clearInterval(interval);
|
|
828
|
+
}, [previewPollMs, checkForPreview]);
|
|
829
|
+
|
|
830
|
+
// ─── Always-on behavioral triggers (P3-e #3 / Slice E) ───────────────────
|
|
831
|
+
// The trigger engine wires every behavioral trigger (session_start, app_open,
|
|
832
|
+
// screen_view/exit, time_in_app, n_sessions, after_purchase, before_logout,
|
|
833
|
+
// custom_event, failed_action, after_crash/js_error, network_error, slow_screen,
|
|
834
|
+
// and the native gesture triggers) to the SDK signals the app already produces.
|
|
835
|
+
// A fire first tries the survey/rating campaign path (showEngagePrompt); if no
|
|
836
|
+
// campaign matches, the SAME trigger drives an in-app message (showInAppMessage).
|
|
837
|
+
// Both families share the throttle store, so a behavioral fire never double-shows.
|
|
838
|
+
// The engine buffers events fired before the first config arrives and replays
|
|
839
|
+
// them once it does (late binding), honoring each trigger's remaining delay.
|
|
840
|
+
useEffect(() => {
|
|
841
|
+
return installEngageTriggerEngine({
|
|
842
|
+
fire: options => {
|
|
843
|
+
void (async () => {
|
|
844
|
+
const shown = await showEngagePrompt(options);
|
|
845
|
+
if (!shown && options.trigger) {
|
|
846
|
+
await showInAppMessage({
|
|
847
|
+
trigger: options.trigger,
|
|
848
|
+
screen: options.screen,
|
|
849
|
+
event: options.event,
|
|
850
|
+
action: options.action,
|
|
851
|
+
seconds: options.seconds
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
})();
|
|
855
|
+
},
|
|
856
|
+
fetchConfig: () => engage.fetchConfig(buildConfigContext(engage))
|
|
857
|
+
});
|
|
858
|
+
}, [showEngagePrompt, showInAppMessage, engage]);
|
|
859
|
+
const controller = useMemo(() => ({
|
|
860
|
+
showEngagePrompt,
|
|
861
|
+
dismissEngagePrompt,
|
|
862
|
+
showInAppMessage,
|
|
863
|
+
dismissInAppMessage
|
|
864
|
+
}), [showEngagePrompt, dismissEngagePrompt, showInAppMessage, dismissInAppMessage]);
|
|
865
|
+
const activeInAppSpec = activeInAppVariantRef.current?.spec ?? activeInApp?.spec;
|
|
866
|
+
const activeInAppPresentation = activeInApp && activeInAppSpec ? resolveInAppPresentation({
|
|
867
|
+
layout: activeInApp.layout,
|
|
868
|
+
variantKey: activeInApp.variantKey,
|
|
869
|
+
spec: activeInAppSpec
|
|
870
|
+
}) : null;
|
|
871
|
+
// Route by the canonical mount, not a variant allow-list. This covers every
|
|
872
|
+
// current/future inline variant, including smart_inbox_message.
|
|
873
|
+
const routesToInlineSlot = activeInAppPresentation?.mountModel === 'inline';
|
|
874
|
+
const inlinePlacement = resolveEngageInlinePlacement(activeInAppSpec);
|
|
875
|
+
const handleActiveInAppShow = useCallback(() => {
|
|
876
|
+
if (!activeInApp) return;
|
|
877
|
+
handleInAppShow(activeInApp);
|
|
878
|
+
const tourId = activeInApp.spec.ext?.coachTourId;
|
|
879
|
+
const first = Array.isArray(activeInApp.spec.ext?.steps) ? activeInApp.spec.ext?.steps[0] : undefined;
|
|
880
|
+
if (typeof tourId === 'string') {
|
|
881
|
+
engage.trackCoachmarkEvent?.('$coachmark_tour_started', {
|
|
882
|
+
tourId
|
|
883
|
+
});
|
|
884
|
+
engage.trackCoachmarkEvent?.('$coachmark_step_entered', {
|
|
885
|
+
tourId,
|
|
886
|
+
stepId: String(first?.id ?? first?.anchorKey ?? '1')
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
}, [activeInApp, handleInAppShow, engage]);
|
|
890
|
+
const handleActiveInAppCta = useCallback(cta => {
|
|
891
|
+
if (activeInApp) handleInAppCta(activeInApp, cta);
|
|
892
|
+
}, [activeInApp, handleInAppCta]);
|
|
893
|
+
const handleActiveInAppInteraction = useCallback(interaction => {
|
|
894
|
+
if (!activeInApp) return;
|
|
895
|
+
trackInApp(activeInApp, 'interaction', {
|
|
896
|
+
interaction
|
|
897
|
+
});
|
|
898
|
+
const tourId = activeInApp.spec.ext?.coachTourId;
|
|
899
|
+
if (typeof tourId !== 'string' || interaction.mechanic !== 'coachmark_spotlight') return;
|
|
900
|
+
const meta = interaction.meta ?? {};
|
|
901
|
+
const stepId = String(meta.anchorKey ?? meta.step ?? meta.toStep ?? 'unknown');
|
|
902
|
+
if (interaction.result === 'step_viewed' && interaction.phase !== 'started') {
|
|
903
|
+
engage.trackCoachmarkEvent?.('$coachmark_step_entered', {
|
|
904
|
+
tourId,
|
|
905
|
+
stepId
|
|
906
|
+
});
|
|
907
|
+
} else if (interaction.phase === 'completed') {
|
|
908
|
+
engage.trackCoachmarkEvent?.('$coachmark_tour_completed', {
|
|
909
|
+
tourId,
|
|
910
|
+
stepId
|
|
911
|
+
});
|
|
912
|
+
} else if (interaction.result === 'skipped') {
|
|
913
|
+
engage.trackCoachmarkEvent?.('$coachmark_tour_abandoned', {
|
|
914
|
+
tourId,
|
|
915
|
+
stepId
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
}, [activeInApp, trackInApp, engage]);
|
|
919
|
+
const handleActiveInAppRenderError = useCallback(reason => {
|
|
920
|
+
if (activeInApp) {
|
|
921
|
+
trackInApp(activeInApp, 'render_failed', {
|
|
922
|
+
reason
|
|
923
|
+
});
|
|
924
|
+
const tourId = activeInApp.spec.ext?.coachTourId;
|
|
925
|
+
if (typeof tourId === 'string') {
|
|
926
|
+
const anchorKey = reason.startsWith('anchor_not_found:') ? reason.slice('anchor_not_found:'.length) : 'unknown';
|
|
927
|
+
engage.trackCoachmarkEvent?.('$coachmark_anchor_failed', {
|
|
928
|
+
tourId,
|
|
929
|
+
stepId: anchorKey,
|
|
930
|
+
reason: reason.startsWith('anchor_not_found:') ? 'anchor_not_found' : reason
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
shownInAppMessageIdRef.current = null;
|
|
935
|
+
activeInAppVariantRef.current = null;
|
|
936
|
+
setActiveInApp(null);
|
|
937
|
+
}, [activeInApp, trackInApp, engage]);
|
|
938
|
+
useEffect(() => {
|
|
939
|
+
if (!routesToInlineSlot || !inlinePlacement.placementKey) return;
|
|
940
|
+
return inlinePlacementRegistry.subscribe(inlinePlacement.placementKey, () => {
|
|
941
|
+
setInlinePlacementRevision(revision => revision + 1);
|
|
942
|
+
});
|
|
943
|
+
}, [inlinePlacement.placementKey, inlinePlacementRegistry, routesToInlineSlot]);
|
|
944
|
+
useEffect(() => {
|
|
945
|
+
if (!activeInApp || active !== null || !routesToInlineSlot) {
|
|
946
|
+
setInlineFallbackMessageId(null);
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
const messageId = activeInApp.id;
|
|
950
|
+
// Once this message has visibly degraded, keep it on that mount. Moving it
|
|
951
|
+
// into a late slot would create a second renderer and a misleading lifecycle.
|
|
952
|
+
if (inlineFallbackMessageId === messageId) return;
|
|
953
|
+
const reason = inlinePlacement.placementKey ? `inline_placement_not_found:${inlinePlacement.placementKey}` : 'missing_inline_placement_key';
|
|
954
|
+
const delivery = {
|
|
955
|
+
message: activeInApp,
|
|
956
|
+
spec: activeInAppSpec,
|
|
957
|
+
onShow: handleActiveInAppShow,
|
|
958
|
+
onCta: handleActiveInAppCta,
|
|
959
|
+
onDismiss: dismissInAppMessage,
|
|
960
|
+
onComplete: completeInAppMessage,
|
|
961
|
+
onInteraction: handleActiveInAppInteraction,
|
|
962
|
+
onInAppGameRequest,
|
|
963
|
+
onRenderError: handleActiveInAppRenderError
|
|
964
|
+
};
|
|
965
|
+
const delivered = inlinePlacementRegistry.deliver(inlinePlacement.placementKey, delivery);
|
|
966
|
+
if (delivered) {
|
|
967
|
+
setInlineFallbackMessageId(null);
|
|
968
|
+
} else {
|
|
969
|
+
inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
|
|
970
|
+
if (inlinePlacement.fallback === 'skip') {
|
|
971
|
+
setInlineFallbackMessageId(null);
|
|
972
|
+
handleActiveInAppRenderError(reason);
|
|
973
|
+
} else {
|
|
974
|
+
// Preserve the legacy visible behavior, but make the degradation observable.
|
|
975
|
+
trackInApp(activeInApp, 'render_degraded', {
|
|
976
|
+
reason,
|
|
977
|
+
placementKey: inlinePlacement.placementKey,
|
|
978
|
+
fallback: 'overlay'
|
|
979
|
+
});
|
|
980
|
+
setInlineFallbackMessageId(messageId);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return () => inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
|
|
984
|
+
}, [active, activeInApp, activeInAppSpec, dismissInAppMessage, completeInAppMessage, handleActiveInAppCta, handleActiveInAppInteraction, handleActiveInAppRenderError, handleActiveInAppShow, inlinePlacement.fallback, inlinePlacement.placementKey, inlinePlacementRegistry, inlineFallbackMessageId, inlinePlacementRevision, onInAppGameRequest, routesToInlineSlot, trackInApp]);
|
|
985
|
+
const rootInAppVisible = activeInApp !== null && active === null && (!routesToInlineSlot || inlineFallbackMessageId === activeInApp.id);
|
|
986
|
+
return /*#__PURE__*/_jsx(EngageAnchorProvider, {
|
|
987
|
+
children: /*#__PURE__*/_jsx(EngageInlinePlacementProvider, {
|
|
988
|
+
registry: inlinePlacementRegistry,
|
|
989
|
+
children: /*#__PURE__*/_jsxs(EngagePromptContext.Provider, {
|
|
990
|
+
value: controller,
|
|
991
|
+
children: [children, /*#__PURE__*/_jsx(EngagePromptView, {
|
|
992
|
+
campaign: active,
|
|
993
|
+
visible: active !== null,
|
|
994
|
+
rating: ratingRouting,
|
|
995
|
+
submitStatus: submitStatus,
|
|
996
|
+
onRetrySubmit: () => void runSubmit(),
|
|
997
|
+
onCloseSubmit: closeAfterSubmit,
|
|
998
|
+
onSubmit: result => {
|
|
999
|
+
if (active) handleSubmit(active, result);
|
|
1000
|
+
},
|
|
1001
|
+
onStart: () => {
|
|
1002
|
+
if (active && surveyStartedRef.current !== active.id) {
|
|
1003
|
+
surveyStartedRef.current = active.id;
|
|
1004
|
+
trackSurveyStage(active, 'started');
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
onDismiss: dismissEngagePrompt
|
|
1008
|
+
}), /*#__PURE__*/_jsx(EngageInAppView, {
|
|
1009
|
+
message: activeInApp,
|
|
1010
|
+
visible: rootInAppVisible,
|
|
1011
|
+
mountModelOverride: routesToInlineSlot && inlineFallbackMessageId === activeInApp?.id ? 'overlay' : undefined
|
|
1012
|
+
// Render the resolved A/B arm's content (D8/J6) when an experiment is
|
|
1013
|
+
// active; undefined ⇒ the view falls back to the message's base spec.
|
|
1014
|
+
,
|
|
1015
|
+
spec: activeInAppVariantRef.current?.spec,
|
|
1016
|
+
onShow: handleActiveInAppShow,
|
|
1017
|
+
onCta: handleActiveInAppCta,
|
|
1018
|
+
onDismiss: dismissInAppMessage,
|
|
1019
|
+
onComplete: completeInAppMessage,
|
|
1020
|
+
onInteraction: handleActiveInAppInteraction,
|
|
1021
|
+
onInAppGameRequest: onInAppGameRequest,
|
|
1022
|
+
onRenderError: handleActiveInAppRenderError
|
|
1023
|
+
})]
|
|
1024
|
+
})
|
|
1025
|
+
})
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Hook a host app uses to trigger/dismiss the prompt:
|
|
1031
|
+
* const { showEngagePrompt } = useEngagePrompt();
|
|
1032
|
+
* showEngagePrompt({ types: ['NPS'] });
|
|
1033
|
+
*/
|
|
1034
|
+
export function useEngagePrompt() {
|
|
1035
|
+
const ctx = useContext(EngagePromptContext);
|
|
1036
|
+
if (!ctx) {
|
|
1037
|
+
// Fail-soft: a host that calls the hook outside the provider gets no-ops
|
|
1038
|
+
// instead of a crash (matches the SDK's no-throw public-API style).
|
|
1039
|
+
return {
|
|
1040
|
+
showEngagePrompt: async () => {
|
|
1041
|
+
logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
|
|
1042
|
+
return false;
|
|
1043
|
+
},
|
|
1044
|
+
dismissEngagePrompt: () => {},
|
|
1045
|
+
showInAppMessage: async () => {
|
|
1046
|
+
logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
|
|
1047
|
+
return false;
|
|
1048
|
+
},
|
|
1049
|
+
dismissInAppMessage: () => {}
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
return ctx;
|
|
1053
|
+
}
|
|
1054
|
+
//# sourceMappingURL=EngagePromptProvider.js.map
|