@scalebun/react-native 1.0.1 → 1.0.2
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 -21
- package/README.md +65 -65
- package/android/build/generated/source/buildConfig/debug/com/scalebun/sdk/BuildConfig.java +12 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeReplaySdkSpec.java +208 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunCrashSpec.java +46 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.java +38 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunOtaSpec.java +63 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunPerformanceSpec.java +70 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunProfilerSpec.java +96 -0
- package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunStorageSpec.java +50 -0
- package/android/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
- package/android/build/generated/source/codegen/jni/ScaleBunSpec-generated.cpp +554 -0
- package/android/build/generated/source/codegen/jni/ScaleBunSpec.h +79 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ComponentDescriptors.cpp +22 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ComponentDescriptors.h +24 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/EventEmitters.cpp +16 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/EventEmitters.h +17 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/Props.cpp +19 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/Props.h +18 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ScaleBunSpecJSI-generated.cpp +595 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ScaleBunSpecJSI.h +1070 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ShadowNodes.cpp +17 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ShadowNodes.h +23 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/States.cpp +16 -0
- package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/States.h +20 -0
- package/android/build/generated/source/codegen/schema.json +1 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +20 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
- package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
- package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
- package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/sdk/BuildConfig.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeReplaySdkSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunCrashSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunOtaSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunPerformanceSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunProfilerSpec.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunStorageSpec.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +2 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +24 -0
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +20 -0
- package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/CrashStorage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/NativeCrashHandler$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/NativeCrashHandler.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/ANRWatchdog$HangInfo.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/ANRWatchdog.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$AppStartInfo.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$Breakdown.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$start$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$FrameMetricsSnapshot.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$start$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$startChoreographerFallback$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/PerformanceCore$Listener.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/PerformanceCore.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/CpuCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/IncidentDetector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/MemoryCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/RenderCollector$frameCallback$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/RenderCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/SamplerScheduler.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/SamplerSchedulerKt.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/ThreadCollector$WhenMappings.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/ThreadCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule$registerConnectivity$cb$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/CaptureReason$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/CaptureReason.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureManager$startFrequencyTimer$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$FrameRequest.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$SettleWatch.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$StabilityWatch.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/CaptureMode$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/CaptureMode.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayConfig$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayLogger.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ScreenshotQuality$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ScreenshotQuality.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/SessionIdGenerator.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/SessionState.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/ReplayFrame.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/ReplaySession.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/TimelineEvent.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox$enforceLimits$lambda$37$$inlined$sortedBy$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$NetworkError.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$Response.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$Outcome.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$WhenMappings.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/session/SessionManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/storage/ReplayStorage$enforceStorageLimit$$inlined$sortedBy$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/storage/ReplayStorage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/timeline/TimelineCollector.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/DialogTouchObserver$start$runnable$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/DialogTouchObserver.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/InteractionTracker.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/NativeTouchInterceptor.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/ScreenTracker.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport$UploadResult.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport$upload$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder$Result.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber$TranscriptResult.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber$listener$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ScaleBunPackage$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ScaleBunPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$WindowInsetEdges.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$shakeListener$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngagePackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunNotificationPresenter.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/SlotManager$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/SlotManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule$coreListener$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$getInstallReferrer$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageModule$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/sdk/BuildConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeReplaySdkSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunCrashSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunOtaSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunPerformanceSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunProfilerSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunStorageSpec.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/storage/KvFileStore$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/storage/KvFileStore.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +25 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/CrashStorage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/NativeCrashHandler$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/NativeCrashHandler.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/ANRWatchdog$HangInfo.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/ANRWatchdog.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$AppStartInfo.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$Breakdown.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$start$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$FrameMetricsSnapshot.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$start$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$startChoreographerFallback$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/PerformanceCore$Listener.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/PerformanceCore.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerPackage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/CpuCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/IncidentDetector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/MemoryCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/RenderCollector$frameCallback$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/RenderCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/SamplerScheduler.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/SamplerSchedulerKt.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/ThreadCollector$WhenMappings.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/ThreadCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule$registerConnectivity$cb$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkPackage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/CaptureReason$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/CaptureReason.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureManager$startFrequencyTimer$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureManager.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$FrameRequest.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$SettleWatch.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$StabilityWatch.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/CaptureMode$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/CaptureMode.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayConfig$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayConfig.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayLogger.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ScreenshotQuality$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ScreenshotQuality.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/SessionIdGenerator.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/SessionState.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/ReplayFrame.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/ReplaySession.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/TimelineEvent.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox$enforceLimits$lambda$37$$inlined$sortedBy$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$NetworkError.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$Response.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$Outcome.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$WhenMappings.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/session/SessionManager.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/storage/ReplayStorage$enforceStorageLimit$$inlined$sortedBy$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/storage/ReplayStorage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/timeline/TimelineCollector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/DialogTouchObserver$start$runnable$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/DialogTouchObserver.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/InteractionTracker.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/NativeTouchInterceptor.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/ScreenTracker.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport$UploadResult.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport$upload$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder$Result.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber$TranscriptResult.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber$listener$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ScaleBunPackage$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ScaleBunPackage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashPackage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$WindowInsetEdges.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$shakeListener$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngagePackage.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunNotificationPresenter.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/SlotManager$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/SlotManager.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule$coreListener$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$getInstallReferrer$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageSpec.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/storage/KvFileStore$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/scalebun/storage/KvFileStore.class +0 -0
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +28 -28
- package/android/src/main/AndroidManifest.xml +14 -14
- package/android/src/main/java/com/scalebun/core/crash/CrashStorage.kt +41 -41
- package/android/src/main/java/com/scalebun/core/crash/NativeCrashHandler.kt +79 -79
- package/android/src/main/java/com/scalebun/core/performance/ANRWatchdog.kt +100 -100
- package/android/src/main/java/com/scalebun/core/performance/AppStartCollector.kt +132 -132
- package/android/src/main/java/com/scalebun/core/performance/FrameMetricsCollector.kt +230 -230
- package/android/src/main/java/com/scalebun/core/performance/PerformanceCore.kt +165 -165
- package/android/src/main/java/com/scalebun/profiler/ProfilerModule.kt +398 -398
- package/android/src/main/java/com/scalebun/profiler/ProfilerPackage.kt +24 -24
- package/android/src/main/java/com/scalebun/profiler/collectors/CpuCollector.kt +161 -161
- package/android/src/main/java/com/scalebun/profiler/collectors/IncidentDetector.kt +223 -223
- package/android/src/main/java/com/scalebun/profiler/collectors/MemoryCollector.kt +157 -157
- package/android/src/main/java/com/scalebun/profiler/collectors/RenderCollector.kt +194 -194
- package/android/src/main/java/com/scalebun/profiler/collectors/SamplerScheduler.kt +218 -218
- package/android/src/main/java/com/scalebun/profiler/collectors/ThreadCollector.kt +142 -142
- package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkModule.kt +966 -966
- package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkPackage.kt +24 -24
- package/android/src/main/java/com/scalebun/replaysdk/capture/CaptureReason.kt +47 -47
- package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureManager.kt +508 -508
- package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureScheduler.kt +187 -187
- package/android/src/main/java/com/scalebun/replaysdk/capture/UiStabilityDetector.kt +214 -214
- package/android/src/main/java/com/scalebun/replaysdk/core/ReplayConfig.kt +144 -144
- package/android/src/main/java/com/scalebun/replaysdk/core/ReplayLogger.kt +31 -31
- package/android/src/main/java/com/scalebun/replaysdk/core/SessionIdGenerator.kt +15 -15
- package/android/src/main/java/com/scalebun/replaysdk/models/ReplayModels.kt +88 -88
- package/android/src/main/java/com/scalebun/replaysdk/outbox/NativeOutbox.kt +541 -541
- package/android/src/main/java/com/scalebun/replaysdk/outbox/OutboxUploader.kt +407 -407
- package/android/src/main/java/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.kt +126 -126
- package/android/src/main/java/com/scalebun/replaysdk/session/SessionManager.kt +281 -281
- package/android/src/main/java/com/scalebun/replaysdk/storage/ReplayStorage.kt +136 -136
- package/android/src/main/java/com/scalebun/replaysdk/timeline/TimelineCollector.kt +28 -28
- package/android/src/main/java/com/scalebun/replaysdk/tracking/InteractionTracker.kt +419 -419
- package/android/src/main/java/com/scalebun/replaysdk/tracking/ScreenTracker.kt +20 -20
- package/android/src/main/java/com/scalebun/replaysdk/transport/ReplayTransport.kt +99 -99
- package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceRecorder.kt +121 -121
- package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceTranscriber.kt +104 -104
- package/android/src/main/java/com/scalebun/rn/ScaleBunPackage.kt +113 -113
- package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashModule.kt +100 -100
- package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashPackage.kt +22 -22
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngageModule.kt +579 -579
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngagePackage.kt +22 -22
- package/android/src/main/java/com/scalebun/rn/engage/ScaleBunNotificationPresenter.kt +110 -110
- package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaModule.kt +136 -136
- package/android/src/main/java/com/scalebun/rn/ota/SlotManager.kt +285 -285
- package/android/src/main/java/com/scalebun/rn/performance/PerformanceModule.kt +206 -206
- package/android/src/main/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.kt +77 -77
- package/android/src/main/java/com/scalebun/rn/storage/ScaleBunStorageModule.kt +68 -68
- package/android/src/main/java/com/scalebun/storage/KvFileStore.kt +174 -174
- package/android/src/newarch/java/com/scalebun/profiler/ProfilerSpec.kt +12 -12
- package/android/src/newarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +12 -12
- package/android/src/newarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +15 -15
- package/android/src/newarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +16 -16
- package/android/src/newarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +12 -12
- package/android/src/newarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +14 -14
- package/android/src/newarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +16 -16
- package/android/src/oldarch/java/com/scalebun/profiler/ProfilerSpec.kt +34 -34
- package/android/src/oldarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +76 -76
- package/android/src/oldarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +21 -21
- package/android/src/oldarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +25 -25
- package/android/src/oldarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +27 -27
- package/android/src/oldarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +18 -18
- package/android/src/oldarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +26 -26
- package/bin/lib/iosCodemod.js +266 -266
- package/bin/scalebun.js +640 -640
- package/ios/Capture/InteractionTracker.swift +191 -191
- package/ios/Capture/PrivacyMaskProcessor.swift +158 -158
- package/ios/Capture/ScreenshotCaptureManager.swift +315 -315
- package/ios/Capture/WindowResolver.swift +63 -63
- package/ios/Core/ReplayConfig.swift +100 -100
- package/ios/Core/ReplayLogger.swift +22 -22
- package/ios/Core/SessionIdGenerator.swift +18 -18
- package/ios/Crash/ScaleBunCrashBridge.mm +63 -63
- package/ios/Crash/ScaleBunCrashHandler.swift +67 -67
- package/ios/Crash/ScaleBunCrashModule.swift +69 -69
- package/ios/Crash/ScaleBunCrashSignalBridge.h +18 -18
- package/ios/Crash/ScaleBunCrashSignalBridge.m +131 -131
- package/ios/Crash/ScaleBunCrashStorage.swift +46 -46
- package/ios/Engage/ScaleBunEngageBridge.m +32 -32
- package/ios/Engage/ScaleBunEngageModule.swift +250 -250
- package/ios/Engage/ScaleBunPushNotificationCenter.swift +185 -185
- package/ios/Ota/OtaSlotManager.swift +264 -264
- package/ios/Ota/ScaleBunOtaBridge.mm +68 -68
- package/ios/Ota/ScaleBunOtaModule.swift +123 -123
- package/ios/Outbox/NativeOutbox.swift +598 -598
- package/ios/Outbox/OutboxUploader.swift +431 -431
- package/ios/Performance/ScaleBunPerformanceBridge.m +32 -32
- package/ios/Performance/ScaleBunPerformanceModule.swift +290 -290
- package/ios/PrivacyInfo.xcprivacy +97 -97
- package/ios/Profiler/ScaleBunProfilerBridge.m +55 -55
- package/ios/Profiler/ScaleBunProfilerModule.swift +972 -972
- package/ios/ReplaySdk-Bridging-Header.h +2 -2
- package/ios/ReplaySdk.swift +608 -608
- package/ios/ReplaySdkBridge.m +94 -94
- package/ios/Session/SessionManager.swift +203 -203
- package/ios/Skan/ScaleBunSkanBridge.m +14 -14
- package/ios/Skan/ScaleBunSkanModule.swift +61 -61
- package/ios/Storage/ReplayStorage.swift +61 -61
- package/ios/Storage/ScaleBunKvFileStore.swift +125 -125
- package/ios/Storage/ScaleBunStorageBridge.mm +72 -72
- package/ios/Storage/ScaleBunStorageModule.swift +57 -57
- package/ios/Transport/ReplayTransport.swift +70 -70
- package/ios/VoiceRecorder.swift +145 -145
- package/lib/commonjs/analytics/EventTracker.js +34 -34
- package/lib/commonjs/analytics/EventTracker.js.map +1 -1
- package/lib/commonjs/analytics/automaticEvents.js +7 -7
- package/lib/commonjs/analytics/automaticEvents.js.map +1 -1
- package/lib/commonjs/analytics/batching.js +24 -24
- package/lib/commonjs/analytics/batching.js.map +1 -1
- package/lib/commonjs/analytics/eventLane.js +13 -13
- package/lib/commonjs/analytics/eventLane.js.map +1 -1
- package/lib/commonjs/bootstrap/FeatureRegistry.js +17 -17
- package/lib/commonjs/bootstrap/FeatureRegistry.js.map +1 -1
- package/lib/commonjs/bootstrap/SDKBootstrapper.js +42 -42
- package/lib/commonjs/bootstrap/SDKBootstrapper.js.map +1 -1
- package/lib/commonjs/bucketing/fnv1a32.js +10 -10
- package/lib/commonjs/bucketing/fnv1a32.js.map +1 -1
- package/lib/commonjs/compat/codepush.js +6 -6
- package/lib/commonjs/compat/codepush.js.map +1 -1
- package/lib/commonjs/config/ConfigManager.js +20 -20
- package/lib/commonjs/config/ConfigManager.js.map +1 -1
- package/lib/commonjs/config/configTypes.js.map +1 -1
- package/lib/commonjs/core/architecture.js +23 -23
- package/lib/commonjs/core/architecture.js.map +1 -1
- package/lib/commonjs/core/clock/now.js +2 -2
- package/lib/commonjs/core/clock/now.js.map +1 -1
- package/lib/commonjs/core/config/defaults.js.map +1 -1
- package/lib/commonjs/core/config/schema.js +102 -102
- package/lib/commonjs/core/config/schema.js.map +1 -1
- package/lib/commonjs/core/constants/endpoints.js +7 -7
- package/lib/commonjs/core/constants/endpoints.js.map +1 -1
- package/lib/commonjs/core/constants/timings.js +5 -5
- package/lib/commonjs/core/constants/timings.js.map +1 -1
- package/lib/commonjs/core/constants/version.js +4 -4
- package/lib/commonjs/core/constants/version.js.map +1 -1
- package/lib/commonjs/core/context/app.js.map +1 -1
- package/lib/commonjs/core/context/device.js.map +1 -1
- package/lib/commonjs/core/context/session.js.map +1 -1
- package/lib/commonjs/core/context/user.js.map +1 -1
- package/lib/commonjs/core/contracts/IFeature.js.map +1 -1
- package/lib/commonjs/core/di/container.js.map +1 -1
- package/lib/commonjs/core/encoding/base64.js +9 -9
- package/lib/commonjs/core/encoding/base64.js.map +1 -1
- package/lib/commonjs/core/id/deviceId.js +4 -4
- package/lib/commonjs/core/id/deviceId.js.map +1 -1
- package/lib/commonjs/core/id/sessionId.js.map +1 -1
- package/lib/commonjs/core/lifecycle/appLifecycle.js.map +1 -1
- package/lib/commonjs/core/lifecycle/crashSafe.js +3 -3
- package/lib/commonjs/core/lifecycle/crashSafe.js.map +1 -1
- package/lib/commonjs/core/logger/errorClassification.js +30 -30
- package/lib/commonjs/core/logger/errorClassification.js.map +1 -1
- package/lib/commonjs/core/logger/internalLogger.js.map +1 -1
- package/lib/commonjs/core/logger/levels.js.map +1 -1
- package/lib/commonjs/crypto/hmacSha256.js +6 -6
- package/lib/commonjs/crypto/hmacSha256.js.map +1 -1
- package/lib/commonjs/debug/bootstrap.js +26 -26
- package/lib/commonjs/debug/bootstrap.js.map +1 -1
- package/lib/commonjs/debug/commands.js +10 -10
- package/lib/commonjs/debug/commands.js.map +1 -1
- package/lib/commonjs/debug/configBuilder.js +6 -6
- package/lib/commonjs/debug/configBuilder.js.map +1 -1
- package/lib/commonjs/debug/exportBridge.js +17 -17
- package/lib/commonjs/debug/exportBridge.js.map +1 -1
- package/lib/commonjs/debug/hostResolver.js +10 -10
- package/lib/commonjs/debug/hostResolver.js.map +1 -1
- package/lib/commonjs/debug/index.js.map +1 -1
- package/lib/commonjs/debug/metrics.js.map +1 -1
- package/lib/commonjs/debug/perf.js +11 -11
- package/lib/commonjs/debug/perf.js.map +1 -1
- package/lib/commonjs/debug/perfWiring.js +10 -10
- package/lib/commonjs/debug/perfWiring.js.map +1 -1
- package/lib/commonjs/debug/protocol.js.map +1 -1
- package/lib/commonjs/debug/redaction.js +26 -26
- package/lib/commonjs/debug/redaction.js.map +1 -1
- package/lib/commonjs/debug/replayWiring.js +11 -11
- package/lib/commonjs/debug/replayWiring.js.map +1 -1
- package/lib/commonjs/debug/screenTracking.js +7 -7
- package/lib/commonjs/debug/screenTracking.js.map +1 -1
- package/lib/commonjs/debug/sessionWiring.js +8 -8
- package/lib/commonjs/debug/sessionWiring.js.map +1 -1
- package/lib/commonjs/debug/stream.js +26 -26
- package/lib/commonjs/debug/stream.js.map +1 -1
- package/lib/commonjs/debug/transport.js +24 -24
- package/lib/commonjs/debug/transport.js.map +1 -1
- package/lib/commonjs/features/bugreport/index.js.map +1 -1
- package/lib/commonjs/features/crash/CrashFeature.js +9 -9
- package/lib/commonjs/features/crash/CrashFeature.js.map +1 -1
- package/lib/commonjs/features/crash/CrashReporter.js +28 -28
- package/lib/commonjs/features/crash/CrashReporter.js.map +1 -1
- package/lib/commonjs/features/crash/NativeCrashFeature.js +7 -7
- package/lib/commonjs/features/crash/NativeCrashFeature.js.map +1 -1
- package/lib/commonjs/features/crash/capture.js.map +1 -1
- package/lib/commonjs/features/crash/globalHandler.js +11 -11
- package/lib/commonjs/features/crash/globalHandler.js.map +1 -1
- package/lib/commonjs/features/crash/index.js.map +1 -1
- package/lib/commonjs/features/crash/nativeCrashBridge.js +19 -19
- package/lib/commonjs/features/crash/nativeCrashBridge.js.map +1 -1
- package/lib/commonjs/features/engage/EngageAnchor.js +3 -3
- package/lib/commonjs/features/engage/EngageAnchor.js.map +1 -1
- package/lib/commonjs/features/engage/EngageArchetypeRenderers.js +19 -19
- package/lib/commonjs/features/engage/EngageArchetypeRenderers.js.map +1 -1
- package/lib/commonjs/features/engage/EngageInAppView.js +35 -35
- package/lib/commonjs/features/engage/EngageInAppView.js.map +1 -1
- package/lib/commonjs/features/engage/EngageInlinePlacement.js +7 -7
- package/lib/commonjs/features/engage/EngageInlinePlacement.js.map +1 -1
- package/lib/commonjs/features/engage/EngagePromptProvider.js +84 -84
- package/lib/commonjs/features/engage/EngagePromptProvider.js.map +1 -1
- package/lib/commonjs/features/engage/EngagePromptView.js +18 -18
- package/lib/commonjs/features/engage/EngagePromptView.js.map +1 -1
- package/lib/commonjs/features/engage/EngageTransport.js +79 -79
- package/lib/commonjs/features/engage/EngageTransport.js.map +1 -1
- package/lib/commonjs/features/engage/EngageVariantContent.js +10 -10
- package/lib/commonjs/features/engage/EngageVariantContent.js.map +1 -1
- package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js +7 -7
- package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js.map +1 -1
- package/lib/commonjs/features/engage/attachmentCapture.js +12 -12
- package/lib/commonjs/features/engage/attachmentCapture.js.map +1 -1
- package/lib/commonjs/features/engage/captureVoiceAttachment.js +20 -20
- package/lib/commonjs/features/engage/captureVoiceAttachment.js.map +1 -1
- package/lib/commonjs/features/engage/engageCoachmarkTour.js +4 -4
- package/lib/commonjs/features/engage/engageCoachmarkTour.js.map +1 -1
- package/lib/commonjs/features/engage/engageGameLogic.js.map +1 -1
- package/lib/commonjs/features/engage/engageMediaSizing.js +15 -15
- package/lib/commonjs/features/engage/engageMediaSizing.js.map +1 -1
- package/lib/commonjs/features/engage/engageMultiStepSheet.js +6 -6
- package/lib/commonjs/features/engage/engageMultiStepSheet.js.map +1 -1
- package/lib/commonjs/features/engage/engageOutcome.js +6 -6
- package/lib/commonjs/features/engage/engageOutcome.js.map +1 -1
- package/lib/commonjs/features/engage/engagePushTokenBridge.js +20 -20
- package/lib/commonjs/features/engage/engagePushTokenBridge.js.map +1 -1
- package/lib/commonjs/features/engage/engageShakeBridge.js +16 -16
- package/lib/commonjs/features/engage/engageShakeBridge.js.map +1 -1
- package/lib/commonjs/features/engage/engageSignals.js.map +1 -1
- package/lib/commonjs/features/engage/engageStoreReviewBridge.js +19 -19
- package/lib/commonjs/features/engage/engageStoreReviewBridge.js.map +1 -1
- package/lib/commonjs/features/engage/engageTestSeenStore.js +29 -29
- package/lib/commonjs/features/engage/engageTestSeenStore.js.map +1 -1
- package/lib/commonjs/features/engage/engageThrottle.js +76 -76
- package/lib/commonjs/features/engage/engageThrottle.js.map +1 -1
- package/lib/commonjs/features/engage/engageTriggerEngine.js +7 -7
- package/lib/commonjs/features/engage/engageTriggerEngine.js.map +1 -1
- package/lib/commonjs/features/engage/engageTypes.js +33 -33
- package/lib/commonjs/features/engage/engageTypes.js.map +1 -1
- package/lib/commonjs/features/engage/engageVariantResolver.js +13 -13
- package/lib/commonjs/features/engage/engageVariantResolver.js.map +1 -1
- package/lib/commonjs/features/engage/engageWindowInsets.js +10 -10
- package/lib/commonjs/features/engage/engageWindowInsets.js.map +1 -1
- package/lib/commonjs/features/engage/gestureTriggerDetector.js.map +1 -1
- package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js +16 -16
- package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js.map +1 -1
- package/lib/commonjs/features/install-referrer/installReferrer.js +26 -26
- package/lib/commonjs/features/install-referrer/installReferrer.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunDebugRoot.js +28 -28
- package/lib/commonjs/features/journey/ScaleBunDebugRoot.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunFlatList.js +15 -15
- package/lib/commonjs/features/journey/ScaleBunFlatList.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunImpression.js +22 -22
- package/lib/commonjs/features/journey/ScaleBunImpression.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunScrollView.js +20 -20
- package/lib/commonjs/features/journey/ScaleBunScrollView.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunSectionList.js +15 -15
- package/lib/commonjs/features/journey/ScaleBunSectionList.js.map +1 -1
- package/lib/commonjs/features/journey/calibrationContext.js +12 -12
- package/lib/commonjs/features/journey/calibrationContext.js.map +1 -1
- package/lib/commonjs/features/journey/gestureBuffer.js +9 -9
- package/lib/commonjs/features/journey/gestureBuffer.js.map +1 -1
- package/lib/commonjs/features/journey/gestureDetector.js +10 -10
- package/lib/commonjs/features/journey/gestureDetector.js.map +1 -1
- package/lib/commonjs/features/journey/impression.js +18 -18
- package/lib/commonjs/features/journey/impression.js.map +1 -1
- package/lib/commonjs/features/journey/journeyManager.js +6 -6
- package/lib/commonjs/features/journey/journeyManager.js.map +1 -1
- package/lib/commonjs/features/journey/journeyTypes.js +5 -5
- package/lib/commonjs/features/journey/journeyTypes.js.map +1 -1
- package/lib/commonjs/features/journey/navDetector.js +7 -7
- package/lib/commonjs/features/journey/navDetector.js.map +1 -1
- package/lib/commonjs/features/journey/screenshotHelper.js +7 -7
- package/lib/commonjs/features/journey/screenshotHelper.js.map +1 -1
- package/lib/commonjs/features/journey/targetRegistry.js +17 -17
- package/lib/commonjs/features/journey/targetRegistry.js.map +1 -1
- package/lib/commonjs/features/journey/touchTarget.js +29 -29
- package/lib/commonjs/features/journey/touchTarget.js.map +1 -1
- package/lib/commonjs/features/navigation/AutoScreenDetector.js +61 -61
- package/lib/commonjs/features/navigation/AutoScreenDetector.js.map +1 -1
- package/lib/commonjs/features/network/NetworkFeature.js +23 -23
- package/lib/commonjs/features/network/NetworkFeature.js.map +1 -1
- package/lib/commonjs/features/network/index.js +5 -5
- package/lib/commonjs/features/network/index.js.map +1 -1
- package/lib/commonjs/features/ota/OtaEventEmitter.js +21 -21
- package/lib/commonjs/features/ota/OtaEventEmitter.js.map +1 -1
- package/lib/commonjs/features/ota/OtaOrchestrator.js +20 -20
- package/lib/commonjs/features/ota/OtaOrchestrator.js.map +1 -1
- package/lib/commonjs/features/ota/OtaTypes.js.map +1 -1
- package/lib/commonjs/features/ota/useOtaUpdate.js +15 -15
- package/lib/commonjs/features/ota/useOtaUpdate.js.map +1 -1
- package/lib/commonjs/features/performance/PerformanceFeature.js +26 -26
- package/lib/commonjs/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js +13 -13
- package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js +32 -32
- package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js +13 -13
- package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js +11 -11
- package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/JsStallCollector.js +12 -12
- package/lib/commonjs/features/performance/collectors/JsStallCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js +10 -10
- package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js +11 -11
- package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/UiHangCollector.js +5 -5
- package/lib/commonjs/features/performance/collectors/UiHangCollector.js.map +1 -1
- package/lib/commonjs/features/performance/config.js +11 -11
- package/lib/commonjs/features/performance/config.js.map +1 -1
- package/lib/commonjs/features/performance/getNativePerformanceModule.js +11 -11
- package/lib/commonjs/features/performance/getNativePerformanceModule.js.map +1 -1
- package/lib/commonjs/features/performance/index.js.map +1 -1
- package/lib/commonjs/features/performance/metrics/MetricsEngine.js +13 -13
- package/lib/commonjs/features/performance/metrics/MetricsEngine.js.map +1 -1
- package/lib/commonjs/features/performance/models.js +8 -8
- package/lib/commonjs/features/performance/models.js.map +1 -1
- package/lib/commonjs/features/performance/transport/PerformanceTransport.js +6 -6
- package/lib/commonjs/features/performance/transport/PerformanceTransport.js.map +1 -1
- package/lib/commonjs/features/profiler/ProfilerFeature.js +53 -53
- package/lib/commonjs/features/profiler/ProfilerFeature.js.map +1 -1
- package/lib/commonjs/features/profiler/config.js +15 -15
- package/lib/commonjs/features/profiler/config.js.map +1 -1
- package/lib/commonjs/features/profiler/contracts.js +22 -22
- package/lib/commonjs/features/profiler/contracts.js.map +1 -1
- package/lib/commonjs/features/profiler/index.js.map +1 -1
- package/lib/commonjs/features/profiler/models.js +44 -44
- package/lib/commonjs/features/profiler/models.js.map +1 -1
- package/lib/commonjs/features/profiler/transport/ProfilerTransport.js +9 -9
- package/lib/commonjs/features/profiler/transport/ProfilerTransport.js.map +1 -1
- package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js +17 -17
- package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js.map +1 -1
- package/lib/commonjs/features/replay/bridge/eventEmitter.js +8 -8
- package/lib/commonjs/features/replay/bridge/eventEmitter.js.map +1 -1
- package/lib/commonjs/features/replay/bridge/nativeModule.js +20 -20
- package/lib/commonjs/features/replay/bridge/nativeModule.js.map +1 -1
- package/lib/commonjs/features/replay/core/clock/clock.js +6 -6
- package/lib/commonjs/features/replay/core/clock/clock.js.map +1 -1
- package/lib/commonjs/features/replay/core/config/defaults.js +2 -2
- package/lib/commonjs/features/replay/core/config/defaults.js.map +1 -1
- package/lib/commonjs/features/replay/core/config/validator.js +5 -5
- package/lib/commonjs/features/replay/core/config/validator.js.map +1 -1
- package/lib/commonjs/features/replay/core/env/environmentDetector.js +10 -10
- package/lib/commonjs/features/replay/core/env/environmentDetector.js.map +1 -1
- package/lib/commonjs/features/replay/core/errors/safeCall.js +4 -4
- package/lib/commonjs/features/replay/core/errors/safeCall.js.map +1 -1
- package/lib/commonjs/features/replay/core/ids/sessionId.js +5 -5
- package/lib/commonjs/features/replay/core/ids/sessionId.js.map +1 -1
- package/lib/commonjs/features/replay/core/logger/logger.js +5 -5
- package/lib/commonjs/features/replay/core/logger/logger.js.map +1 -1
- package/lib/commonjs/features/replay/core/privacy/privacyTypes.js +4 -4
- package/lib/commonjs/features/replay/core/privacy/privacyTypes.js.map +1 -1
- package/lib/commonjs/features/replay/core/queue/boundedQueue.js +5 -5
- package/lib/commonjs/features/replay/core/queue/boundedQueue.js.map +1 -1
- package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js +59 -59
- package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js.map +1 -1
- package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js +19 -19
- package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js.map +1 -1
- package/lib/commonjs/features/replay/integrations/network/networkAdapter.js +30 -30
- package/lib/commonjs/features/replay/integrations/network/networkAdapter.js.map +1 -1
- package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js +19 -19
- package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js.map +1 -1
- package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js +16 -16
- package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js.map +1 -1
- package/lib/commonjs/features/replay/pipeline/batching/batchManager.js +5 -5
- package/lib/commonjs/features/replay/pipeline/batching/batchManager.js.map +1 -1
- package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js +5 -5
- package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js.map +1 -1
- package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js +4 -4
- package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js.map +1 -1
- package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js +7 -7
- package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js.map +1 -1
- package/lib/commonjs/features/replay/public/api.js +21 -21
- package/lib/commonjs/features/replay/public/api.js.map +1 -1
- package/lib/commonjs/features/replay/public/enums.js +5 -5
- package/lib/commonjs/features/replay/public/enums.js.map +1 -1
- package/lib/commonjs/features/replay/public/types.js.map +1 -1
- package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js +5 -5
- package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js.map +1 -1
- package/lib/commonjs/features/replay/replay/frames/frameModels.js +4 -4
- package/lib/commonjs/features/replay/replay/frames/frameModels.js.map +1 -1
- package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js +10 -10
- package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js.map +1 -1
- package/lib/commonjs/features/replay/replay/timeline/timelineModels.js +4 -4
- package/lib/commonjs/features/replay/replay/timeline/timelineModels.js.map +1 -1
- package/lib/commonjs/features/replay/transport/BackendReplayTransport.js +13 -13
- package/lib/commonjs/features/replay/transport/BackendReplayTransport.js.map +1 -1
- package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js +8 -8
- package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js.map +1 -1
- package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js +14 -14
- package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js.map +1 -1
- package/lib/commonjs/features/replay/transport/ReplayTransport.js.map +1 -1
- package/lib/commonjs/features/session/BackendSessionAdapter.js +127 -127
- package/lib/commonjs/features/session/BackendSessionAdapter.js.map +1 -1
- package/lib/commonjs/features/session/DesktopSessionTransport.js +14 -14
- package/lib/commonjs/features/session/DesktopSessionTransport.js.map +1 -1
- package/lib/commonjs/features/session/JourneyEventPipeline.js +19 -19
- package/lib/commonjs/features/session/JourneyEventPipeline.js.map +1 -1
- package/lib/commonjs/features/session/ReplayCaptureManager.js +123 -123
- package/lib/commonjs/features/session/ReplayCaptureManager.js.map +1 -1
- package/lib/commonjs/features/session/ScrollTracker.js +17 -17
- package/lib/commonjs/features/session/ScrollTracker.js.map +1 -1
- package/lib/commonjs/features/session/SessionManager.js +143 -143
- package/lib/commonjs/features/session/SessionManager.js.map +1 -1
- package/lib/commonjs/features/session/SyncDecisionEngine.js +23 -23
- package/lib/commonjs/features/session/SyncDecisionEngine.js.map +1 -1
- package/lib/commonjs/features/session/index.js.map +1 -1
- package/lib/commonjs/features/session/nativeCapture.js +5 -5
- package/lib/commonjs/features/session/nativeCapture.js.map +1 -1
- package/lib/commonjs/features/session/outboxFrameCapture.js +15 -15
- package/lib/commonjs/features/session/outboxFrameCapture.js.map +1 -1
- package/lib/commonjs/features/session/sessionTypes.js +44 -44
- package/lib/commonjs/features/session/sessionTypes.js.map +1 -1
- package/lib/commonjs/features/skan/skanBridge.js +11 -11
- package/lib/commonjs/features/skan/skanBridge.js.map +1 -1
- package/lib/commonjs/features/skan/skanConversionManager.js +23 -23
- package/lib/commonjs/features/skan/skanConversionManager.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/integrations/fetch/fetchInterceptor.js +21 -21
- package/lib/commonjs/integrations/fetch/fetchInterceptor.js.map +1 -1
- package/lib/commonjs/integrations/navigation/screenTracker.js.map +1 -1
- package/lib/commonjs/integrations/network/bodyCapture.js +69 -69
- package/lib/commonjs/integrations/network/bodyCapture.js.map +1 -1
- package/lib/commonjs/integrations/xhr/xhrInterceptor.js +24 -24
- package/lib/commonjs/integrations/xhr/xhrInterceptor.js.map +1 -1
- package/lib/commonjs/metro/index.js +37 -37
- package/lib/commonjs/metro/index.js.map +1 -1
- package/lib/commonjs/metro/optionalDependencyStub.js.map +1 -1
- package/lib/commonjs/metro/optionalModules.js +16 -16
- package/lib/commonjs/metro/optionalModules.js.map +1 -1
- package/lib/commonjs/pipeline/dispatcher/dispatcher.js.map +1 -1
- package/lib/commonjs/pipeline/envelope/envelope.js.map +1 -1
- package/lib/commonjs/pipeline/envelope/serializer.js.map +1 -1
- package/lib/commonjs/pipeline/processors/dedupe.js.map +1 -1
- package/lib/commonjs/pipeline/processors/enrich.js.map +1 -1
- package/lib/commonjs/pipeline/processors/sampling.js.map +1 -1
- package/lib/commonjs/pipeline/processors/sanitize.js.map +1 -1
- package/lib/commonjs/pipeline/queue/flushQueue.js +4 -4
- package/lib/commonjs/pipeline/queue/flushQueue.js.map +1 -1
- package/lib/commonjs/pipeline/queue/memoryQueue.js.map +1 -1
- package/lib/commonjs/pipeline/queue/persistentQueue.js +80 -80
- package/lib/commonjs/pipeline/queue/persistentQueue.js.map +1 -1
- package/lib/commonjs/pipeline/queue/queuePolicy.js.map +1 -1
- package/lib/commonjs/pipeline/scheduler/flushScheduler.js.map +1 -1
- package/lib/commonjs/pipeline/scheduler/retryPolicy.js +2 -2
- package/lib/commonjs/pipeline/scheduler/retryPolicy.js.map +1 -1
- package/lib/commonjs/public/ScaleBunFacade.js +274 -274
- package/lib/commonjs/public/ScaleBunFacade.js.map +1 -1
- package/lib/commonjs/public/ScaleBunProvider.js +3 -3
- package/lib/commonjs/public/ScaleBunProvider.js.map +1 -1
- package/lib/commonjs/public/typedTracker.js +36 -36
- package/lib/commonjs/public/typedTracker.js.map +1 -1
- package/lib/commonjs/public/types.js.map +1 -1
- package/lib/commonjs/push/PushManager.js +21 -21
- package/lib/commonjs/push/PushManager.js.map +1 -1
- package/lib/commonjs/push/adapters/ManualAdapter.js +14 -14
- package/lib/commonjs/push/adapters/ManualAdapter.js.map +1 -1
- package/lib/commonjs/push/adapters/NativeBridgeAdapter.js +17 -17
- package/lib/commonjs/push/adapters/NativeBridgeAdapter.js.map +1 -1
- package/lib/commonjs/push/adapters/NoopAdapter.js +5 -5
- package/lib/commonjs/push/adapters/NoopAdapter.js.map +1 -1
- package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js +17 -17
- package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js.map +1 -1
- package/lib/commonjs/push/adapters/loadMessaging.js +12 -12
- package/lib/commonjs/push/adapters/loadMessaging.js.map +1 -1
- package/lib/commonjs/push/adapters/loadNotifee.js +12 -12
- package/lib/commonjs/push/adapters/loadNotifee.js.map +1 -1
- package/lib/commonjs/push/adapters/selectAdapter.js +14 -14
- package/lib/commonjs/push/adapters/selectAdapter.js.map +1 -1
- package/lib/commonjs/push/detect/capabilities.js +19 -19
- package/lib/commonjs/push/detect/capabilities.js.map +1 -1
- package/lib/commonjs/push/index.js.map +1 -1
- package/lib/commonjs/push/native/nativeNotifications.js +32 -32
- package/lib/commonjs/push/native/nativeNotifications.js.map +1 -1
- package/lib/commonjs/push/types.js.map +1 -1
- package/lib/commonjs/specs/NativeReplaySdk.js +18 -18
- package/lib/commonjs/specs/NativeReplaySdk.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunCrash.js +19 -19
- package/lib/commonjs/specs/NativeScaleBunCrash.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js +14 -14
- package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunOta.js +21 -21
- package/lib/commonjs/specs/NativeScaleBunOta.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunPerformance.js +15 -15
- package/lib/commonjs/specs/NativeScaleBunPerformance.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunProfiler.js +16 -16
- package/lib/commonjs/specs/NativeScaleBunProfiler.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunStorage.js +29 -29
- package/lib/commonjs/specs/NativeScaleBunStorage.js.map +1 -1
- package/lib/commonjs/storage/StorageBackend.js +83 -83
- package/lib/commonjs/storage/StorageBackend.js.map +1 -1
- package/lib/commonjs/storage/db/sqlite.js.map +1 -1
- package/lib/commonjs/storage/files/fileStore.js.map +1 -1
- package/lib/commonjs/transport/auth/sdkSession.js.map +1 -1
- package/lib/commonjs/transport/backoff/exponentialJitter.js +2 -2
- package/lib/commonjs/transport/backoff/exponentialJitter.js.map +1 -1
- package/lib/commonjs/transport/http/endpoints.js.map +1 -1
- package/lib/commonjs/transport/http/httpClient.js +3 -3
- package/lib/commonjs/transport/http/httpClient.js.map +1 -1
- package/lib/commonjs/transport/rateLimit/retryAfter.js.map +1 -1
- package/lib/commonjs/transport/signing/requestSigner.js.map +1 -1
- package/lib/commonjs/vendor/protocol/index.js +74 -74
- package/lib/commonjs/vendor/protocol/index.js.map +1 -1
- package/lib/commonjs/vendor/protocol/internal/validation.js +23 -23
- package/lib/commonjs/vendor/protocol/internal/validation.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/bridge.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/config.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/events.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/features.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/index.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/platform.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/session-boundary.js.map +1 -1
- package/lib/commonjs/vendor/sdk-contracts/session.js.map +1 -1
- package/lib/commonjs/vendor/vendor.manifest +10 -10
- package/lib/module/analytics/EventTracker.js +34 -34
- package/lib/module/analytics/EventTracker.js.map +1 -1
- package/lib/module/analytics/automaticEvents.js +7 -7
- package/lib/module/analytics/automaticEvents.js.map +1 -1
- package/lib/module/analytics/batching.js +24 -24
- package/lib/module/analytics/batching.js.map +1 -1
- package/lib/module/analytics/eventLane.js +13 -13
- package/lib/module/analytics/eventLane.js.map +1 -1
- package/lib/module/bootstrap/FeatureRegistry.js +17 -17
- package/lib/module/bootstrap/FeatureRegistry.js.map +1 -1
- package/lib/module/bootstrap/SDKBootstrapper.js +42 -42
- package/lib/module/bootstrap/SDKBootstrapper.js.map +1 -1
- package/lib/module/bucketing/fnv1a32.js +10 -10
- package/lib/module/bucketing/fnv1a32.js.map +1 -1
- package/lib/module/compat/codepush.js +6 -6
- package/lib/module/compat/codepush.js.map +1 -1
- package/lib/module/config/ConfigManager.js +20 -20
- package/lib/module/config/ConfigManager.js.map +1 -1
- package/lib/module/config/configTypes.js.map +1 -1
- package/lib/module/core/architecture.js +23 -23
- package/lib/module/core/architecture.js.map +1 -1
- package/lib/module/core/clock/now.js +2 -2
- package/lib/module/core/clock/now.js.map +1 -1
- package/lib/module/core/config/defaults.js.map +1 -1
- package/lib/module/core/config/schema.js +102 -102
- package/lib/module/core/config/schema.js.map +1 -1
- package/lib/module/core/constants/endpoints.js +7 -7
- package/lib/module/core/constants/endpoints.js.map +1 -1
- package/lib/module/core/constants/timings.js +5 -5
- package/lib/module/core/constants/timings.js.map +1 -1
- package/lib/module/core/constants/version.js +4 -4
- package/lib/module/core/constants/version.js.map +1 -1
- package/lib/module/core/context/app.js.map +1 -1
- package/lib/module/core/context/device.js.map +1 -1
- package/lib/module/core/context/session.js.map +1 -1
- package/lib/module/core/context/user.js.map +1 -1
- package/lib/module/core/contracts/IFeature.js.map +1 -1
- package/lib/module/core/di/container.js.map +1 -1
- package/lib/module/core/encoding/base64.js +9 -9
- package/lib/module/core/encoding/base64.js.map +1 -1
- package/lib/module/core/id/deviceId.js +4 -4
- package/lib/module/core/id/deviceId.js.map +1 -1
- package/lib/module/core/id/sessionId.js.map +1 -1
- package/lib/module/core/lifecycle/appLifecycle.js.map +1 -1
- package/lib/module/core/lifecycle/crashSafe.js +3 -3
- package/lib/module/core/lifecycle/crashSafe.js.map +1 -1
- package/lib/module/core/logger/errorClassification.js +30 -30
- package/lib/module/core/logger/errorClassification.js.map +1 -1
- package/lib/module/core/logger/internalLogger.js.map +1 -1
- package/lib/module/core/logger/levels.js.map +1 -1
- package/lib/module/crypto/hmacSha256.js +6 -6
- package/lib/module/crypto/hmacSha256.js.map +1 -1
- package/lib/module/debug/bootstrap.js +26 -26
- package/lib/module/debug/bootstrap.js.map +1 -1
- package/lib/module/debug/commands.js +10 -10
- package/lib/module/debug/commands.js.map +1 -1
- package/lib/module/debug/configBuilder.js +6 -6
- package/lib/module/debug/configBuilder.js.map +1 -1
- package/lib/module/debug/exportBridge.js +17 -17
- package/lib/module/debug/exportBridge.js.map +1 -1
- package/lib/module/debug/hostResolver.js +10 -10
- package/lib/module/debug/hostResolver.js.map +1 -1
- package/lib/module/debug/index.js +5 -5
- package/lib/module/debug/index.js.map +1 -1
- package/lib/module/debug/metrics.js.map +1 -1
- package/lib/module/debug/perf.js +11 -11
- package/lib/module/debug/perf.js.map +1 -1
- package/lib/module/debug/perfWiring.js +10 -10
- package/lib/module/debug/perfWiring.js.map +1 -1
- package/lib/module/debug/protocol.js +11 -11
- package/lib/module/debug/protocol.js.map +1 -1
- package/lib/module/debug/redaction.js +26 -26
- package/lib/module/debug/redaction.js.map +1 -1
- package/lib/module/debug/replayWiring.js +11 -11
- package/lib/module/debug/replayWiring.js.map +1 -1
- package/lib/module/debug/screenTracking.js +7 -7
- package/lib/module/debug/screenTracking.js.map +1 -1
- package/lib/module/debug/sessionWiring.js +8 -8
- package/lib/module/debug/sessionWiring.js.map +1 -1
- package/lib/module/debug/stream.js +26 -26
- package/lib/module/debug/stream.js.map +1 -1
- package/lib/module/debug/transport.js +24 -24
- package/lib/module/debug/transport.js.map +1 -1
- package/lib/module/features/bugreport/index.js.map +1 -1
- package/lib/module/features/crash/CrashFeature.js +9 -9
- package/lib/module/features/crash/CrashFeature.js.map +1 -1
- package/lib/module/features/crash/CrashReporter.js +28 -28
- package/lib/module/features/crash/CrashReporter.js.map +1 -1
- package/lib/module/features/crash/NativeCrashFeature.js +7 -7
- package/lib/module/features/crash/NativeCrashFeature.js.map +1 -1
- package/lib/module/features/crash/capture.js.map +1 -1
- package/lib/module/features/crash/globalHandler.js +11 -11
- package/lib/module/features/crash/globalHandler.js.map +1 -1
- package/lib/module/features/crash/index.js.map +1 -1
- package/lib/module/features/crash/nativeCrashBridge.js +19 -19
- package/lib/module/features/crash/nativeCrashBridge.js.map +1 -1
- package/lib/module/features/engage/EngageAnchor.js +3 -3
- package/lib/module/features/engage/EngageAnchor.js.map +1 -1
- package/lib/module/features/engage/EngageArchetypeRenderers.js +19 -19
- package/lib/module/features/engage/EngageArchetypeRenderers.js.map +1 -1
- package/lib/module/features/engage/EngageInAppView.js +35 -35
- package/lib/module/features/engage/EngageInAppView.js.map +1 -1
- package/lib/module/features/engage/EngageInlinePlacement.js +7 -7
- package/lib/module/features/engage/EngageInlinePlacement.js.map +1 -1
- package/lib/module/features/engage/EngagePromptProvider.js +84 -84
- package/lib/module/features/engage/EngagePromptProvider.js.map +1 -1
- package/lib/module/features/engage/EngagePromptView.js +18 -18
- package/lib/module/features/engage/EngagePromptView.js.map +1 -1
- package/lib/module/features/engage/EngageTransport.js +79 -79
- package/lib/module/features/engage/EngageTransport.js.map +1 -1
- package/lib/module/features/engage/EngageVariantContent.js +10 -10
- package/lib/module/features/engage/EngageVariantContent.js.map +1 -1
- package/lib/module/features/engage/__test-support__/reactNativeStub.js +7 -7
- package/lib/module/features/engage/__test-support__/reactNativeStub.js.map +1 -1
- package/lib/module/features/engage/attachmentCapture.js +12 -12
- package/lib/module/features/engage/attachmentCapture.js.map +1 -1
- package/lib/module/features/engage/captureVoiceAttachment.js +20 -20
- package/lib/module/features/engage/captureVoiceAttachment.js.map +1 -1
- package/lib/module/features/engage/engageCoachmarkTour.js +4 -4
- package/lib/module/features/engage/engageCoachmarkTour.js.map +1 -1
- package/lib/module/features/engage/engageGameLogic.js.map +1 -1
- package/lib/module/features/engage/engageMediaSizing.js +15 -15
- package/lib/module/features/engage/engageMediaSizing.js.map +1 -1
- package/lib/module/features/engage/engageMultiStepSheet.js +6 -6
- package/lib/module/features/engage/engageMultiStepSheet.js.map +1 -1
- package/lib/module/features/engage/engageOutcome.js +6 -6
- package/lib/module/features/engage/engageOutcome.js.map +1 -1
- package/lib/module/features/engage/engagePushTokenBridge.js +20 -20
- package/lib/module/features/engage/engagePushTokenBridge.js.map +1 -1
- package/lib/module/features/engage/engageShakeBridge.js +16 -16
- package/lib/module/features/engage/engageShakeBridge.js.map +1 -1
- package/lib/module/features/engage/engageSignals.js.map +1 -1
- package/lib/module/features/engage/engageStoreReviewBridge.js +19 -19
- package/lib/module/features/engage/engageStoreReviewBridge.js.map +1 -1
- package/lib/module/features/engage/engageTestSeenStore.js +29 -29
- package/lib/module/features/engage/engageTestSeenStore.js.map +1 -1
- package/lib/module/features/engage/engageThrottle.js +76 -76
- package/lib/module/features/engage/engageThrottle.js.map +1 -1
- package/lib/module/features/engage/engageTriggerEngine.js +7 -7
- package/lib/module/features/engage/engageTriggerEngine.js.map +1 -1
- package/lib/module/features/engage/engageTypes.js +33 -33
- package/lib/module/features/engage/engageTypes.js.map +1 -1
- package/lib/module/features/engage/engageVariantResolver.js +13 -13
- package/lib/module/features/engage/engageVariantResolver.js.map +1 -1
- package/lib/module/features/engage/engageWindowInsets.js +10 -10
- package/lib/module/features/engage/engageWindowInsets.js.map +1 -1
- package/lib/module/features/engage/gestureTriggerDetector.js.map +1 -1
- package/lib/module/features/engage/transcription/TranscriptionProvider.js +16 -16
- package/lib/module/features/engage/transcription/TranscriptionProvider.js.map +1 -1
- package/lib/module/features/install-referrer/installReferrer.js +26 -26
- package/lib/module/features/install-referrer/installReferrer.js.map +1 -1
- package/lib/module/features/journey/ScaleBunDebugRoot.js +28 -28
- package/lib/module/features/journey/ScaleBunDebugRoot.js.map +1 -1
- package/lib/module/features/journey/ScaleBunFlatList.js +15 -15
- package/lib/module/features/journey/ScaleBunFlatList.js.map +1 -1
- package/lib/module/features/journey/ScaleBunImpression.js +22 -22
- package/lib/module/features/journey/ScaleBunImpression.js.map +1 -1
- package/lib/module/features/journey/ScaleBunScrollView.js +20 -20
- package/lib/module/features/journey/ScaleBunScrollView.js.map +1 -1
- package/lib/module/features/journey/ScaleBunSectionList.js +15 -15
- package/lib/module/features/journey/ScaleBunSectionList.js.map +1 -1
- package/lib/module/features/journey/calibrationContext.js +12 -12
- package/lib/module/features/journey/calibrationContext.js.map +1 -1
- package/lib/module/features/journey/gestureBuffer.js +9 -9
- package/lib/module/features/journey/gestureBuffer.js.map +1 -1
- package/lib/module/features/journey/gestureDetector.js +10 -10
- package/lib/module/features/journey/gestureDetector.js.map +1 -1
- package/lib/module/features/journey/impression.js +18 -18
- package/lib/module/features/journey/impression.js.map +1 -1
- package/lib/module/features/journey/journeyManager.js +6 -6
- package/lib/module/features/journey/journeyManager.js.map +1 -1
- package/lib/module/features/journey/journeyTypes.js +5 -5
- package/lib/module/features/journey/journeyTypes.js.map +1 -1
- package/lib/module/features/journey/navDetector.js +7 -7
- package/lib/module/features/journey/navDetector.js.map +1 -1
- package/lib/module/features/journey/screenshotHelper.js +7 -7
- package/lib/module/features/journey/screenshotHelper.js.map +1 -1
- package/lib/module/features/journey/targetRegistry.js +17 -17
- package/lib/module/features/journey/targetRegistry.js.map +1 -1
- package/lib/module/features/journey/touchTarget.js +29 -29
- package/lib/module/features/journey/touchTarget.js.map +1 -1
- package/lib/module/features/navigation/AutoScreenDetector.js +61 -61
- package/lib/module/features/navigation/AutoScreenDetector.js.map +1 -1
- package/lib/module/features/network/NetworkFeature.js +23 -23
- package/lib/module/features/network/NetworkFeature.js.map +1 -1
- package/lib/module/features/network/index.js +5 -5
- package/lib/module/features/network/index.js.map +1 -1
- package/lib/module/features/ota/OtaEventEmitter.js +21 -21
- package/lib/module/features/ota/OtaEventEmitter.js.map +1 -1
- package/lib/module/features/ota/OtaOrchestrator.js +20 -20
- package/lib/module/features/ota/OtaOrchestrator.js.map +1 -1
- package/lib/module/features/ota/OtaTypes.js.map +1 -1
- package/lib/module/features/ota/useOtaUpdate.js +15 -15
- package/lib/module/features/ota/useOtaUpdate.js.map +1 -1
- package/lib/module/features/performance/PerformanceFeature.js +26 -26
- package/lib/module/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/module/features/performance/collectors/AppLaunchCollector.js +13 -13
- package/lib/module/features/performance/collectors/AppLaunchCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js +32 -32
- package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/CustomTraceCollector.js +13 -13
- package/lib/module/features/performance/collectors/CustomTraceCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/FrameMetricsCollector.js +11 -11
- package/lib/module/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/JsStallCollector.js +12 -12
- package/lib/module/features/performance/collectors/JsStallCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/NetworkPerfCollector.js +10 -10
- package/lib/module/features/performance/collectors/NetworkPerfCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/ScreenLoadCollector.js +11 -11
- package/lib/module/features/performance/collectors/ScreenLoadCollector.js.map +1 -1
- package/lib/module/features/performance/collectors/UiHangCollector.js +5 -5
- package/lib/module/features/performance/collectors/UiHangCollector.js.map +1 -1
- package/lib/module/features/performance/config.js +11 -11
- package/lib/module/features/performance/config.js.map +1 -1
- package/lib/module/features/performance/getNativePerformanceModule.js +11 -11
- package/lib/module/features/performance/getNativePerformanceModule.js.map +1 -1
- package/lib/module/features/performance/index.js +2 -2
- package/lib/module/features/performance/index.js.map +1 -1
- package/lib/module/features/performance/metrics/MetricsEngine.js +13 -13
- package/lib/module/features/performance/metrics/MetricsEngine.js.map +1 -1
- package/lib/module/features/performance/models.js +8 -8
- package/lib/module/features/performance/models.js.map +1 -1
- package/lib/module/features/performance/transport/PerformanceTransport.js +6 -6
- package/lib/module/features/performance/transport/PerformanceTransport.js.map +1 -1
- package/lib/module/features/profiler/ProfilerFeature.js +53 -53
- package/lib/module/features/profiler/ProfilerFeature.js.map +1 -1
- package/lib/module/features/profiler/config.js +15 -15
- package/lib/module/features/profiler/config.js.map +1 -1
- package/lib/module/features/profiler/contracts.js +22 -22
- package/lib/module/features/profiler/contracts.js.map +1 -1
- package/lib/module/features/profiler/index.js +4 -4
- package/lib/module/features/profiler/index.js.map +1 -1
- package/lib/module/features/profiler/models.js +44 -44
- package/lib/module/features/profiler/models.js.map +1 -1
- package/lib/module/features/profiler/transport/ProfilerTransport.js +9 -9
- package/lib/module/features/profiler/transport/ProfilerTransport.js.map +1 -1
- package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js +17 -17
- package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js.map +1 -1
- package/lib/module/features/replay/bridge/eventEmitter.js +8 -8
- package/lib/module/features/replay/bridge/eventEmitter.js.map +1 -1
- package/lib/module/features/replay/bridge/nativeModule.js +20 -20
- package/lib/module/features/replay/bridge/nativeModule.js.map +1 -1
- package/lib/module/features/replay/core/clock/clock.js +6 -6
- package/lib/module/features/replay/core/clock/clock.js.map +1 -1
- package/lib/module/features/replay/core/config/defaults.js +2 -2
- package/lib/module/features/replay/core/config/defaults.js.map +1 -1
- package/lib/module/features/replay/core/config/validator.js +5 -5
- package/lib/module/features/replay/core/config/validator.js.map +1 -1
- package/lib/module/features/replay/core/env/environmentDetector.js +10 -10
- package/lib/module/features/replay/core/env/environmentDetector.js.map +1 -1
- package/lib/module/features/replay/core/errors/safeCall.js +4 -4
- package/lib/module/features/replay/core/errors/safeCall.js.map +1 -1
- package/lib/module/features/replay/core/ids/sessionId.js +5 -5
- package/lib/module/features/replay/core/ids/sessionId.js.map +1 -1
- package/lib/module/features/replay/core/logger/logger.js +5 -5
- package/lib/module/features/replay/core/logger/logger.js.map +1 -1
- package/lib/module/features/replay/core/privacy/privacyTypes.js +4 -4
- package/lib/module/features/replay/core/privacy/privacyTypes.js.map +1 -1
- package/lib/module/features/replay/core/queue/boundedQueue.js +5 -5
- package/lib/module/features/replay/core/queue/boundedQueue.js.map +1 -1
- package/lib/module/features/replay/integrations/alert/alertInstrumentation.js +59 -59
- package/lib/module/features/replay/integrations/alert/alertInstrumentation.js.map +1 -1
- package/lib/module/features/replay/integrations/logs/consoleIntegration.js +19 -19
- package/lib/module/features/replay/integrations/logs/consoleIntegration.js.map +1 -1
- package/lib/module/features/replay/integrations/network/networkAdapter.js +30 -30
- package/lib/module/features/replay/integrations/network/networkAdapter.js.map +1 -1
- package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js +19 -19
- package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js.map +1 -1
- package/lib/module/features/replay/integrations/touch/ReplayRoot.js +16 -16
- package/lib/module/features/replay/integrations/touch/ReplayRoot.js.map +1 -1
- package/lib/module/features/replay/pipeline/batching/batchManager.js +5 -5
- package/lib/module/features/replay/pipeline/batching/batchManager.js.map +1 -1
- package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js +5 -5
- package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js.map +1 -1
- package/lib/module/features/replay/pipeline/retry/retryPolicy.js +4 -4
- package/lib/module/features/replay/pipeline/retry/retryPolicy.js.map +1 -1
- package/lib/module/features/replay/pipeline/transport/transportTypes.js +7 -7
- package/lib/module/features/replay/pipeline/transport/transportTypes.js.map +1 -1
- package/lib/module/features/replay/public/api.js +21 -21
- package/lib/module/features/replay/public/api.js.map +1 -1
- package/lib/module/features/replay/public/enums.js +5 -5
- package/lib/module/features/replay/public/enums.js.map +1 -1
- package/lib/module/features/replay/public/types.js.map +1 -1
- package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js +5 -5
- package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js.map +1 -1
- package/lib/module/features/replay/replay/frames/frameModels.js +4 -4
- package/lib/module/features/replay/replay/frames/frameModels.js.map +1 -1
- package/lib/module/features/replay/replay/session/sessionOrchestrator.js +10 -10
- package/lib/module/features/replay/replay/session/sessionOrchestrator.js.map +1 -1
- package/lib/module/features/replay/replay/timeline/timelineModels.js +4 -4
- package/lib/module/features/replay/replay/timeline/timelineModels.js.map +1 -1
- package/lib/module/features/replay/transport/BackendReplayTransport.js +13 -13
- package/lib/module/features/replay/transport/BackendReplayTransport.js.map +1 -1
- package/lib/module/features/replay/transport/CompositeReplayTransport.js +8 -8
- package/lib/module/features/replay/transport/CompositeReplayTransport.js.map +1 -1
- package/lib/module/features/replay/transport/DesktopReplayTransport.js +14 -14
- package/lib/module/features/replay/transport/DesktopReplayTransport.js.map +1 -1
- package/lib/module/features/replay/transport/ReplayTransport.js.map +1 -1
- package/lib/module/features/session/BackendSessionAdapter.js +127 -127
- package/lib/module/features/session/BackendSessionAdapter.js.map +1 -1
- package/lib/module/features/session/DesktopSessionTransport.js +14 -14
- package/lib/module/features/session/DesktopSessionTransport.js.map +1 -1
- package/lib/module/features/session/JourneyEventPipeline.js +19 -19
- package/lib/module/features/session/JourneyEventPipeline.js.map +1 -1
- package/lib/module/features/session/ReplayCaptureManager.js +123 -123
- package/lib/module/features/session/ReplayCaptureManager.js.map +1 -1
- package/lib/module/features/session/ScrollTracker.js +17 -17
- package/lib/module/features/session/ScrollTracker.js.map +1 -1
- package/lib/module/features/session/SessionManager.js +143 -143
- package/lib/module/features/session/SessionManager.js.map +1 -1
- package/lib/module/features/session/SyncDecisionEngine.js +23 -23
- package/lib/module/features/session/SyncDecisionEngine.js.map +1 -1
- package/lib/module/features/session/index.js +5 -5
- package/lib/module/features/session/index.js.map +1 -1
- package/lib/module/features/session/nativeCapture.js +5 -5
- package/lib/module/features/session/nativeCapture.js.map +1 -1
- package/lib/module/features/session/outboxFrameCapture.js +15 -15
- package/lib/module/features/session/outboxFrameCapture.js.map +1 -1
- package/lib/module/features/session/sessionTypes.js +44 -44
- package/lib/module/features/session/sessionTypes.js.map +1 -1
- package/lib/module/features/skan/skanBridge.js +11 -11
- package/lib/module/features/skan/skanBridge.js.map +1 -1
- package/lib/module/features/skan/skanConversionManager.js +23 -23
- package/lib/module/features/skan/skanConversionManager.js.map +1 -1
- package/lib/module/index.js +10 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/integrations/fetch/fetchInterceptor.js +21 -21
- package/lib/module/integrations/fetch/fetchInterceptor.js.map +1 -1
- package/lib/module/integrations/navigation/screenTracker.js.map +1 -1
- package/lib/module/integrations/network/bodyCapture.js +69 -69
- package/lib/module/integrations/network/bodyCapture.js.map +1 -1
- package/lib/module/integrations/xhr/xhrInterceptor.js +24 -24
- package/lib/module/integrations/xhr/xhrInterceptor.js.map +1 -1
- package/lib/module/metro/index.js +37 -37
- package/lib/module/metro/index.js.map +1 -1
- package/lib/module/metro/optionalDependencyStub.js +11 -11
- package/lib/module/metro/optionalDependencyStub.js.map +1 -1
- package/lib/module/metro/optionalModules.js +16 -16
- package/lib/module/metro/optionalModules.js.map +1 -1
- package/lib/module/pipeline/dispatcher/dispatcher.js.map +1 -1
- package/lib/module/pipeline/envelope/envelope.js.map +1 -1
- package/lib/module/pipeline/envelope/serializer.js.map +1 -1
- package/lib/module/pipeline/processors/dedupe.js.map +1 -1
- package/lib/module/pipeline/processors/enrich.js.map +1 -1
- package/lib/module/pipeline/processors/sampling.js.map +1 -1
- package/lib/module/pipeline/processors/sanitize.js.map +1 -1
- package/lib/module/pipeline/queue/flushQueue.js +4 -4
- package/lib/module/pipeline/queue/flushQueue.js.map +1 -1
- package/lib/module/pipeline/queue/memoryQueue.js.map +1 -1
- package/lib/module/pipeline/queue/persistentQueue.js +80 -80
- package/lib/module/pipeline/queue/persistentQueue.js.map +1 -1
- package/lib/module/pipeline/queue/queuePolicy.js.map +1 -1
- package/lib/module/pipeline/scheduler/flushScheduler.js.map +1 -1
- package/lib/module/pipeline/scheduler/retryPolicy.js +2 -2
- package/lib/module/pipeline/scheduler/retryPolicy.js.map +1 -1
- package/lib/module/public/ScaleBunFacade.js +274 -274
- package/lib/module/public/ScaleBunFacade.js.map +1 -1
- package/lib/module/public/ScaleBunProvider.js +3 -3
- package/lib/module/public/ScaleBunProvider.js.map +1 -1
- package/lib/module/public/typedTracker.js +36 -36
- package/lib/module/public/typedTracker.js.map +1 -1
- package/lib/module/public/types.js.map +1 -1
- package/lib/module/push/PushManager.js +21 -21
- package/lib/module/push/PushManager.js.map +1 -1
- package/lib/module/push/adapters/ManualAdapter.js +14 -14
- package/lib/module/push/adapters/ManualAdapter.js.map +1 -1
- package/lib/module/push/adapters/NativeBridgeAdapter.js +17 -17
- package/lib/module/push/adapters/NativeBridgeAdapter.js.map +1 -1
- package/lib/module/push/adapters/NoopAdapter.js +5 -5
- package/lib/module/push/adapters/NoopAdapter.js.map +1 -1
- package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js +17 -17
- package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js.map +1 -1
- package/lib/module/push/adapters/loadMessaging.js +12 -12
- package/lib/module/push/adapters/loadMessaging.js.map +1 -1
- package/lib/module/push/adapters/loadNotifee.js +12 -12
- package/lib/module/push/adapters/loadNotifee.js.map +1 -1
- package/lib/module/push/adapters/selectAdapter.js +14 -14
- package/lib/module/push/adapters/selectAdapter.js.map +1 -1
- package/lib/module/push/detect/capabilities.js +19 -19
- package/lib/module/push/detect/capabilities.js.map +1 -1
- package/lib/module/push/index.js +3 -3
- package/lib/module/push/index.js.map +1 -1
- package/lib/module/push/native/nativeNotifications.js +32 -32
- package/lib/module/push/native/nativeNotifications.js.map +1 -1
- package/lib/module/push/types.js.map +1 -1
- package/lib/module/specs/NativeReplaySdk.js +18 -18
- package/lib/module/specs/NativeReplaySdk.js.map +1 -1
- package/lib/module/specs/NativeScaleBunCrash.js +19 -19
- package/lib/module/specs/NativeScaleBunCrash.js.map +1 -1
- package/lib/module/specs/NativeScaleBunInstallReferrer.js +14 -14
- package/lib/module/specs/NativeScaleBunInstallReferrer.js.map +1 -1
- package/lib/module/specs/NativeScaleBunOta.js +21 -21
- package/lib/module/specs/NativeScaleBunOta.js.map +1 -1
- package/lib/module/specs/NativeScaleBunPerformance.js +15 -15
- package/lib/module/specs/NativeScaleBunPerformance.js.map +1 -1
- package/lib/module/specs/NativeScaleBunProfiler.js +16 -16
- package/lib/module/specs/NativeScaleBunProfiler.js.map +1 -1
- package/lib/module/specs/NativeScaleBunStorage.js +29 -29
- package/lib/module/specs/NativeScaleBunStorage.js.map +1 -1
- package/lib/module/storage/StorageBackend.js +83 -83
- package/lib/module/storage/StorageBackend.js.map +1 -1
- package/lib/module/storage/db/sqlite.js.map +1 -1
- package/lib/module/storage/files/fileStore.js.map +1 -1
- package/lib/module/transport/auth/sdkSession.js.map +1 -1
- package/lib/module/transport/backoff/exponentialJitter.js +2 -2
- package/lib/module/transport/backoff/exponentialJitter.js.map +1 -1
- package/lib/module/transport/http/endpoints.js.map +1 -1
- package/lib/module/transport/http/httpClient.js +3 -3
- package/lib/module/transport/http/httpClient.js.map +1 -1
- package/lib/module/transport/rateLimit/retryAfter.js.map +1 -1
- package/lib/module/transport/signing/requestSigner.js.map +1 -1
- package/lib/module/vendor/protocol/index.js +74 -74
- package/lib/module/vendor/protocol/index.js.map +1 -1
- package/lib/module/vendor/protocol/internal/validation.js +23 -23
- package/lib/module/vendor/protocol/internal/validation.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/bridge.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/config.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/events.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/features.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/index.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/platform.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/session-boundary.js.map +1 -1
- package/lib/module/vendor/sdk-contracts/session.js.map +1 -1
- package/lib/module/vendor/vendor.manifest +10 -10
- package/package.json +12 -10
- package/react-native.config.js +24 -24
- package/scalebun-react-native.podspec +37 -37
- package/src/analytics/EventTracker.ts +462 -462
- package/src/analytics/automaticEvents.ts +105 -105
- package/src/analytics/batching.ts +54 -54
- package/src/analytics/eventLane.ts +26 -26
- package/src/bootstrap/FeatureRegistry.ts +81 -81
- package/src/bootstrap/SDKBootstrapper.ts +585 -585
- package/src/bucketing/fnv1a32.ts +40 -40
- package/src/compat/codepush.ts +118 -118
- package/src/config/ConfigManager.ts +167 -167
- package/src/config/configTypes.ts +32 -32
- package/src/core/architecture.ts +39 -39
- package/src/core/clock/now.ts +6 -6
- package/src/core/config/schema.ts +231 -231
- package/src/core/constants/endpoints.ts +9 -9
- package/src/core/constants/timings.ts +23 -23
- package/src/core/constants/version.ts +6 -6
- package/src/core/context/user.ts +26 -26
- package/src/core/contracts/IFeature.ts +53 -53
- package/src/core/di/container.ts +26 -26
- package/src/core/encoding/base64.ts +46 -46
- package/src/core/id/deviceId.ts +51 -51
- package/src/core/lifecycle/appLifecycle.ts +33 -33
- package/src/core/lifecycle/crashSafe.ts +29 -29
- package/src/core/logger/errorClassification.ts +108 -108
- package/src/core/logger/internalLogger.ts +65 -65
- package/src/crypto/hmacSha256.ts +106 -106
- package/src/debug/bootstrap.ts +366 -366
- package/src/debug/commands.ts +597 -597
- package/src/debug/configBuilder.ts +56 -56
- package/src/debug/exportBridge.ts +153 -153
- package/src/debug/hostResolver.ts +34 -34
- package/src/debug/index.ts +25 -25
- package/src/debug/metrics.ts +29 -29
- package/src/debug/perf.ts +212 -212
- package/src/debug/perfWiring.ts +119 -119
- package/src/debug/protocol.ts +58 -58
- package/src/debug/redaction.ts +290 -290
- package/src/debug/replayWiring.ts +147 -147
- package/src/debug/screenTracking.ts +55 -55
- package/src/debug/sessionWiring.ts +59 -59
- package/src/debug/stream.ts +561 -561
- package/src/debug/transport.ts +439 -439
- package/src/features/crash/CrashFeature.ts +52 -52
- package/src/features/crash/CrashReporter.ts +140 -140
- package/src/features/crash/NativeCrashFeature.ts +42 -42
- package/src/features/crash/capture.ts +21 -21
- package/src/features/crash/globalHandler.ts +39 -39
- package/src/features/crash/index.ts +8 -8
- package/src/features/crash/nativeCrashBridge.ts +132 -132
- package/src/features/engage/EngageAnchor.tsx +159 -159
- package/src/features/engage/EngageArchetypeRenderers.tsx +3716 -3716
- package/src/features/engage/EngageInAppView.tsx +2678 -2678
- package/src/features/engage/EngageInlinePlacement.tsx +169 -169
- package/src/features/engage/EngagePromptProvider.tsx +1270 -1270
- package/src/features/engage/EngagePromptView.tsx +1364 -1364
- package/src/features/engage/EngageTransport.ts +668 -668
- package/src/features/engage/EngageVariantContent.tsx +1483 -1483
- package/src/features/engage/__test-support__/reactNativeStub.js +40 -40
- package/src/features/engage/attachmentCapture.ts +45 -45
- package/src/features/engage/captureVoiceAttachment.ts +81 -81
- package/src/features/engage/engageCoachmarkTour.ts +120 -120
- package/src/features/engage/engageGameLogic.ts +347 -347
- package/src/features/engage/engageMediaSizing.ts +76 -76
- package/src/features/engage/engageMultiStepSheet.ts +53 -53
- package/src/features/engage/engageOutcome.ts +157 -157
- package/src/features/engage/engagePushTokenBridge.ts +84 -84
- package/src/features/engage/engageShakeBridge.ts +67 -67
- package/src/features/engage/engageSignals.ts +40 -40
- package/src/features/engage/engageStoreReviewBridge.ts +48 -48
- package/src/features/engage/engageTestSeenStore.ts +95 -95
- package/src/features/engage/engageThrottle.ts +440 -440
- package/src/features/engage/engageTriggerEngine.ts +335 -335
- package/src/features/engage/engageTypes.ts +691 -691
- package/src/features/engage/engageVariantResolver.ts +364 -364
- package/src/features/engage/engageWindowInsets.ts +108 -108
- package/src/features/engage/gestureTriggerDetector.ts +83 -83
- package/src/features/engage/transcription/TranscriptionProvider.ts +68 -68
- package/src/features/install-referrer/installReferrer.ts +112 -112
- package/src/features/journey/ScaleBunDebugRoot.tsx +726 -726
- package/src/features/journey/ScaleBunFlatList.tsx +39 -39
- package/src/features/journey/ScaleBunImpression.tsx +109 -109
- package/src/features/journey/ScaleBunScrollView.tsx +72 -72
- package/src/features/journey/ScaleBunSectionList.tsx +39 -39
- package/src/features/journey/calibrationContext.ts +53 -53
- package/src/features/journey/gestureBuffer.ts +59 -59
- package/src/features/journey/gestureDetector.ts +162 -162
- package/src/features/journey/impression.ts +92 -92
- package/src/features/journey/journeyManager.ts +466 -466
- package/src/features/journey/journeyTypes.ts +215 -215
- package/src/features/journey/navDetector.ts +149 -149
- package/src/features/journey/screenshotHelper.ts +137 -137
- package/src/features/journey/targetRegistry.ts +43 -43
- package/src/features/journey/touchTarget.ts +128 -128
- package/src/features/navigation/AutoScreenDetector.ts +448 -448
- package/src/features/network/NetworkFeature.ts +144 -144
- package/src/features/network/index.ts +31 -31
- package/src/features/ota/OtaEventEmitter.ts +128 -128
- package/src/features/ota/OtaOrchestrator.ts +323 -323
- package/src/features/ota/OtaTypes.ts +62 -62
- package/src/features/ota/useOtaUpdate.ts +134 -134
- package/src/features/performance/PerformanceFeature.ts +584 -584
- package/src/features/performance/collectors/AppLaunchCollector.ts +117 -117
- package/src/features/performance/collectors/AutoScreenLoadCollector.ts +258 -258
- package/src/features/performance/collectors/CustomTraceCollector.ts +116 -116
- package/src/features/performance/collectors/FrameMetricsCollector.ts +119 -119
- package/src/features/performance/collectors/JsStallCollector.ts +165 -165
- package/src/features/performance/collectors/NetworkPerfCollector.ts +69 -69
- package/src/features/performance/collectors/ScreenLoadCollector.ts +95 -95
- package/src/features/performance/collectors/UiHangCollector.ts +98 -98
- package/src/features/performance/config.ts +136 -136
- package/src/features/performance/getNativePerformanceModule.ts +38 -38
- package/src/features/performance/index.ts +28 -28
- package/src/features/performance/metrics/MetricsEngine.ts +152 -152
- package/src/features/performance/models.ts +235 -235
- package/src/features/performance/transport/PerformanceTransport.ts +143 -143
- package/src/features/profiler/ProfilerFeature.ts +661 -661
- package/src/features/profiler/config.ts +230 -230
- package/src/features/profiler/contracts.ts +176 -176
- package/src/features/profiler/index.ts +45 -45
- package/src/features/profiler/models.ts +430 -430
- package/src/features/profiler/transport/ProfilerTransport.ts +93 -93
- package/src/features/replay/bridge/adapters/bridgeAdapter.ts +230 -230
- package/src/features/replay/bridge/eventEmitter.ts +176 -176
- package/src/features/replay/bridge/nativeModule.ts +241 -241
- package/src/features/replay/core/clock/clock.ts +38 -38
- package/src/features/replay/core/config/defaults.ts +66 -66
- package/src/features/replay/core/config/validator.ts +113 -113
- package/src/features/replay/core/env/environmentDetector.ts +21 -21
- package/src/features/replay/core/errors/safeCall.ts +34 -34
- package/src/features/replay/core/ids/sessionId.ts +44 -44
- package/src/features/replay/core/logger/logger.ts +40 -40
- package/src/features/replay/core/privacy/privacyTypes.ts +41 -41
- package/src/features/replay/core/queue/boundedQueue.ts +71 -71
- package/src/features/replay/integrations/alert/alertInstrumentation.ts +277 -277
- package/src/features/replay/integrations/logs/consoleIntegration.ts +116 -116
- package/src/features/replay/integrations/network/networkAdapter.ts +128 -128
- package/src/features/replay/integrations/react-navigation/navigationIntegration.ts +89 -89
- package/src/features/replay/integrations/touch/ReplayRoot.tsx +114 -114
- package/src/features/replay/pipeline/batching/batchManager.ts +133 -133
- package/src/features/replay/pipeline/envelope/envelopeBuilder.ts +66 -66
- package/src/features/replay/pipeline/retry/retryPolicy.ts +62 -62
- package/src/features/replay/pipeline/transport/transportTypes.ts +85 -85
- package/src/features/replay/public/api.ts +364 -364
- package/src/features/replay/public/enums.ts +78 -78
- package/src/features/replay/public/types.ts +297 -297
- package/src/features/replay/replay/breadcrumbs/breadcrumbCollector.ts +115 -115
- package/src/features/replay/replay/frames/frameModels.ts +45 -45
- package/src/features/replay/replay/session/sessionOrchestrator.ts +286 -286
- package/src/features/replay/replay/timeline/timelineModels.ts +129 -129
- package/src/features/replay/transport/BackendReplayTransport.ts +215 -215
- package/src/features/replay/transport/CompositeReplayTransport.ts +82 -82
- package/src/features/replay/transport/DesktopReplayTransport.ts +140 -140
- package/src/features/replay/transport/ReplayTransport.ts +84 -84
- package/src/features/session/BackendSessionAdapter.ts +1233 -1233
- package/src/features/session/DesktopSessionTransport.ts +128 -128
- package/src/features/session/JourneyEventPipeline.ts +273 -273
- package/src/features/session/ReplayCaptureManager.ts +946 -946
- package/src/features/session/ScrollTracker.ts +166 -166
- package/src/features/session/SessionManager.ts +1209 -1209
- package/src/features/session/SyncDecisionEngine.ts +117 -117
- package/src/features/session/index.ts +88 -88
- package/src/features/session/nativeCapture.ts +38 -38
- package/src/features/session/outboxFrameCapture.ts +74 -74
- package/src/features/session/sessionTypes.ts +491 -491
- package/src/features/skan/skanBridge.ts +61 -61
- package/src/features/skan/skanConversionManager.ts +173 -173
- package/src/index.ts +191 -191
- package/src/integrations/fetch/fetchInterceptor.ts +182 -182
- package/src/integrations/network/bodyCapture.ts +328 -328
- package/src/integrations/xhr/xhrInterceptor.ts +231 -231
- package/src/metro/index.ts +164 -164
- package/src/metro/optionalDependencyStub.ts +13 -13
- package/src/metro/optionalModules.ts +27 -27
- package/src/pipeline/dispatcher/dispatcher.ts +22 -22
- package/src/pipeline/envelope/envelope.ts +31 -31
- package/src/pipeline/envelope/serializer.ts +14 -14
- package/src/pipeline/processors/enrich.ts +11 -11
- package/src/pipeline/processors/sanitize.ts +23 -23
- package/src/pipeline/queue/flushQueue.ts +144 -144
- package/src/pipeline/queue/memoryQueue.ts +31 -31
- package/src/pipeline/queue/persistentQueue.ts +414 -414
- package/src/pipeline/scheduler/flushScheduler.ts +47 -47
- package/src/pipeline/scheduler/retryPolicy.ts +8 -8
- package/src/public/ScaleBunFacade.ts +1479 -1479
- package/src/public/ScaleBunProvider.tsx +91 -91
- package/src/public/typedTracker.ts +123 -123
- package/src/public/types.ts +312 -312
- package/src/push/PushManager.ts +318 -318
- package/src/push/adapters/ManualAdapter.ts +100 -100
- package/src/push/adapters/NativeBridgeAdapter.ts +142 -142
- package/src/push/adapters/NoopAdapter.ts +46 -46
- package/src/push/adapters/RNFirebaseMessagingAdapter.ts +271 -271
- package/src/push/adapters/loadMessaging.ts +24 -24
- package/src/push/adapters/loadNotifee.ts +29 -29
- package/src/push/adapters/selectAdapter.ts +176 -176
- package/src/push/detect/capabilities.ts +124 -124
- package/src/push/index.ts +22 -22
- package/src/push/native/nativeNotifications.ts +216 -216
- package/src/push/types.ts +159 -159
- package/src/specs/NativeReplaySdk.ts +99 -99
- package/src/specs/NativeScaleBunCrash.ts +36 -36
- package/src/specs/NativeScaleBunInstallReferrer.ts +29 -29
- package/src/specs/NativeScaleBunOta.ts +85 -85
- package/src/specs/NativeScaleBunPerformance.ts +34 -34
- package/src/specs/NativeScaleBunProfiler.ts +41 -41
- package/src/specs/NativeScaleBunStorage.ts +59 -59
- package/src/storage/StorageBackend.ts +272 -272
- package/src/transport/auth/sdkSession.ts +27 -27
- package/src/transport/backoff/exponentialJitter.ts +9 -9
- package/src/transport/http/endpoints.ts +33 -33
- package/src/transport/http/httpClient.ts +73 -73
- package/src/vendor/protocol/index.ts +391 -391
- package/src/vendor/protocol/internal/validation.ts +497 -497
- package/src/vendor/sdk-contracts/bridge.ts +162 -162
- package/src/vendor/sdk-contracts/config.ts +192 -192
- package/src/vendor/sdk-contracts/events.ts +50 -50
- package/src/vendor/sdk-contracts/features.ts +42 -42
- package/src/vendor/sdk-contracts/index.ts +98 -98
- package/src/vendor/sdk-contracts/platform.ts +42 -42
- package/src/vendor/sdk-contracts/session-boundary.ts +55 -55
- package/src/vendor/sdk-contracts/session.ts +225 -225
- package/src/vendor/vendor.manifest +10 -10
|
@@ -1,946 +1,946 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScaleBun SDK — Replay Capture Manager
|
|
3
|
-
*
|
|
4
|
-
* Orchestration-only component for frame capture:
|
|
5
|
-
* - Decides WHEN to capture (navigation, interaction, scroll, loading, frequency triggers)
|
|
6
|
-
* - Delegates ALL frame capture to native engines via sessionReplayAdapter
|
|
7
|
-
* - NEVER performs screenshot logic itself
|
|
8
|
-
* - If native capture unavailable, returns null and logs warning
|
|
9
|
-
* - Manages frame retention with crash-adjacent priority
|
|
10
|
-
* - Uses session-bound generation guard to invalidate stale async work
|
|
11
|
-
* - All pending timers are cancelled on stop()
|
|
12
|
-
*
|
|
13
|
-
* Semantic Capture Coordination:
|
|
14
|
-
* - Tracks the last completed capture's reason + screen to prevent semantic duplicates
|
|
15
|
-
* - Navigation supersedes pending interaction for the SAME screen (interaction is already
|
|
16
|
-
* visually represented by the navigation frame)
|
|
17
|
-
* - Loading completion for the SAME screen coalesces with a pending navigation capture
|
|
18
|
-
* by cancelling the navigation capture (loading's delayed capture shows the final state)
|
|
19
|
-
* - Scroll captures have per-cycle identity and do not conflict with navigation/loading
|
|
20
|
-
* - Manual and error-context captures ALWAYS bypass coordination (explicit intent)
|
|
21
|
-
* - Genuinely distinct states (different screens, different reasons after settle) are never deduped
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { logger } from '../../core/logger/internalLogger';
|
|
25
|
-
import type {
|
|
26
|
-
ReplayFrame,
|
|
27
|
-
CaptureMode,
|
|
28
|
-
CaptureReason,
|
|
29
|
-
ReplayQuality,
|
|
30
|
-
SessionReplayConfig,
|
|
31
|
-
PrivacyPolicy,
|
|
32
|
-
NativeFrameResult,
|
|
33
|
-
} from './sessionTypes';
|
|
34
|
-
import {
|
|
35
|
-
FrameRetentionPriority,
|
|
36
|
-
getFrameRetentionPriority,
|
|
37
|
-
QUALITY_PRESETS,
|
|
38
|
-
} from './sessionTypes';
|
|
39
|
-
|
|
40
|
-
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Native capture function provided by the adapter layer.
|
|
44
|
-
* Calls the platform native engine (PixelCopy on Android, UIWindow on iOS).
|
|
45
|
-
* Returns null if native capture is unavailable.
|
|
46
|
-
*/
|
|
47
|
-
export type NativeCaptureFn = (
|
|
48
|
-
sessionId: string,
|
|
49
|
-
reason: string,
|
|
50
|
-
quality: ReplayQuality,
|
|
51
|
-
) => Promise<NativeFrameResult | null>;
|
|
52
|
-
|
|
53
|
-
export type FrameEmitCallback = (frame: ReplayFrame, imageData: string) => void;
|
|
54
|
-
|
|
55
|
-
// ─── Native File-Outbox staged capture ───────────────────────────────────────
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Metadata returned by a native STAGED capture-to-file. The image bytes are
|
|
59
|
-
* already written to the native outbox (staged, not yet uploadable) — they NEVER
|
|
60
|
-
* cross the bridge. `frameHash` is a native content hash so JS change-detection
|
|
61
|
-
* works without base64.
|
|
62
|
-
*/
|
|
63
|
-
export interface StagedFrameResult {
|
|
64
|
-
frameId: string;
|
|
65
|
-
width: number;
|
|
66
|
-
height: number;
|
|
67
|
-
byteSize: number;
|
|
68
|
-
format: string;
|
|
69
|
-
contentType: string;
|
|
70
|
-
frameHash: string;
|
|
71
|
-
masked: boolean;
|
|
72
|
-
timestamp: number;
|
|
73
|
-
platform: 'android' | 'ios';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** JS-authoritative frame metadata written to the outbox on commit. */
|
|
77
|
-
export interface OutboxFrameMeta {
|
|
78
|
-
frameId: string;
|
|
79
|
-
sessionId: string;
|
|
80
|
-
timestamp: number;
|
|
81
|
-
sequenceNumber: number;
|
|
82
|
-
frameType: 'keyframe' | 'delta';
|
|
83
|
-
baseFrameId?: string;
|
|
84
|
-
screenName: string;
|
|
85
|
-
trigger: string;
|
|
86
|
-
format: string;
|
|
87
|
-
contentType: string;
|
|
88
|
-
width: number;
|
|
89
|
-
height: number;
|
|
90
|
-
sizeBytes: number;
|
|
91
|
-
masked: boolean;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Native file-outbox frame capture. `capture` stages an image and returns metadata
|
|
96
|
-
* only (or null when the outbox is off / capture fails → caller falls back to the
|
|
97
|
-
* legacy native capture). `commit` writes the JS-decided meta (making the frame
|
|
98
|
-
* uploadable); `discard` drops a staged frame the orchestrator suppressed.
|
|
99
|
-
*/
|
|
100
|
-
export interface OutboxFrameCapture {
|
|
101
|
-
capture(
|
|
102
|
-
sessionId: string,
|
|
103
|
-
screenName: string | undefined,
|
|
104
|
-
trigger: string,
|
|
105
|
-
): Promise<StagedFrameResult | null>;
|
|
106
|
-
commit(meta: OutboxFrameMeta): Promise<boolean>;
|
|
107
|
-
discard(sessionId: string, frameId: string): Promise<void>;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ─── Capture Intent ─────────────────────────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Represents the semantic identity of a completed capture.
|
|
114
|
-
* Used for dedup: two captures with the same intent fingerprint
|
|
115
|
-
* represent the same visual state and should not produce two frames.
|
|
116
|
-
*/
|
|
117
|
-
interface CaptureIntent {
|
|
118
|
-
reason: CaptureReason;
|
|
119
|
-
screen: string | undefined;
|
|
120
|
-
ts: number;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Reasons that always bypass semantic dedup.
|
|
125
|
-
* These are explicit user/system requests that should ALWAYS produce a frame.
|
|
126
|
-
*/
|
|
127
|
-
const BYPASS_DEDUP_REASONS: Set<CaptureReason> = new Set([
|
|
128
|
-
'manual',
|
|
129
|
-
'error-context',
|
|
130
|
-
'frequency',
|
|
131
|
-
]);
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Minimum time (ms) between captures of the same semantic intent
|
|
135
|
-
* (same reason + same screen). Secondary heuristic only — the primary
|
|
136
|
-
* check is semantic (reason + screen identity).
|
|
137
|
-
*/
|
|
138
|
-
const SAME_INTENT_COOLDOWN_MS = 300;
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Time (ms) to defer an interaction capture before finalizing.
|
|
142
|
-
* If onScreenChange fires within this window (i.e. the tap caused navigation),
|
|
143
|
-
* the interaction capture is cancelled and absorbed into the navigation capture.
|
|
144
|
-
* If no navigation follows, the interaction captures normally after this delay.
|
|
145
|
-
* 200ms is long enough for most React navigation timings but short enough to feel instant.
|
|
146
|
-
*/
|
|
147
|
-
const INTERACTION_SETTLE_MS = 200;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Grace window (ms) AFTER an interaction capture has already fired.
|
|
151
|
-
* If onScreenChange fires to a DIFFERENT screen within this window,
|
|
152
|
-
* the stale interaction frame is retroactively evicted and its tap
|
|
153
|
-
* metadata is carried forward to the navigation capture.
|
|
154
|
-
* Handles the intermittent case where navigation takes >INTERACTION_SETTLE_MS.
|
|
155
|
-
*/
|
|
156
|
-
const LATE_ABSORPTION_GRACE_MS = 400;
|
|
157
|
-
|
|
158
|
-
// ─── Manager ────────────────────────────────────────────────────────────────
|
|
159
|
-
|
|
160
|
-
export class ReplayCaptureManager {
|
|
161
|
-
private sessionId: string;
|
|
162
|
-
private config: SessionReplayConfig;
|
|
163
|
-
private nativeCapture: NativeCaptureFn;
|
|
164
|
-
/** Optional native file-outbox path. When ready, frames stage→commit natively. */
|
|
165
|
-
private outboxCapture: OutboxFrameCapture | null;
|
|
166
|
-
private onFrameEmit: FrameEmitCallback | null = null;
|
|
167
|
-
|
|
168
|
-
private frames: ReplayFrame[] = [];
|
|
169
|
-
/** Set of frameIds near crashes — never evict */
|
|
170
|
-
private protectedFrameIds = new Set<string>();
|
|
171
|
-
private frequencyTimer: ReturnType<typeof setInterval> | null = null;
|
|
172
|
-
private capturing = false;
|
|
173
|
-
private currentScreen: string | null = null;
|
|
174
|
-
private lastInteractionCapture = 0;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Session-bound generation counter.
|
|
178
|
-
* Incremented on stop(). All async capture work checks this before AND after
|
|
179
|
-
* native capture to ensure stale callbacks from a previous session lifecycle
|
|
180
|
-
* do not emit frames into a new session.
|
|
181
|
-
*/
|
|
182
|
-
private captureGeneration = 0;
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Tracked navigation capture timeout.
|
|
186
|
-
* Cancelled on stop() and on each new onScreenChange() call (debounce).
|
|
187
|
-
*/
|
|
188
|
-
private pendingNavTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
189
|
-
/** Screen associated with the pending navigation capture */
|
|
190
|
-
private pendingNavScreen: string | null = null;
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Tracked scroll settle capture timeout.
|
|
194
|
-
* Cancelled on stop().
|
|
195
|
-
*/
|
|
196
|
-
private pendingScrollTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Tracked loading end capture timeout.
|
|
200
|
-
* Cancelled on stop().
|
|
201
|
-
*/
|
|
202
|
-
private pendingLoadingTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
203
|
-
/** Screen associated with the pending loading capture */
|
|
204
|
-
private pendingLoadingScreen: string | null = null;
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Pending interaction capture timeout.
|
|
208
|
-
* When a tap/gesture occurs, the capture is DEFERRED by INTERACTION_SETTLE_MS.
|
|
209
|
-
* If onScreenChange fires within that window (tap caused navigation), the
|
|
210
|
-
* pending interaction is cancelled and its tap metadata is carried forward
|
|
211
|
-
* to the navigation capture — ensuring the destination screen is captured
|
|
212
|
-
* instead of a stale pre-navigation screenshot.
|
|
213
|
-
* If no navigation follows, the interaction capture fires normally.
|
|
214
|
-
*/
|
|
215
|
-
private pendingInteractionTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
216
|
-
/** Interaction point metadata held while pending (carried to nav if absorbed) */
|
|
217
|
-
private pendingInteractionPoint: ReplayFrame['interactionPoint'] | undefined = undefined;
|
|
218
|
-
/** Screen at the time the pending interaction was created */
|
|
219
|
-
private pendingInteractionScreen: string | undefined = undefined;
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Late absorption tracking.
|
|
223
|
-
* After an interaction capture fires, store its metadata so that
|
|
224
|
-
* a delayed onScreenChange can retroactively evict the stale frame
|
|
225
|
-
* and carry the tap metadata forward to the navigation capture.
|
|
226
|
-
*/
|
|
227
|
-
private lastCompletedInteraction: {
|
|
228
|
-
frameId: string;
|
|
229
|
-
screen: string | undefined;
|
|
230
|
-
interactionPoint: ReplayFrame['interactionPoint'] | undefined;
|
|
231
|
-
ts: number;
|
|
232
|
-
} | null = null;
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* In-flight interaction tracking.
|
|
236
|
-
* Set when triggerCapture('interaction') starts the async native call and cleared
|
|
237
|
-
* when it completes. If onScreenChange fires for a DIFFERENT screen while a capture
|
|
238
|
-
* is in-flight, the capture is suppressed — the navigation frame is the correct state.
|
|
239
|
-
* Covers the race window between pendingInteractionTimeout firing and native returning,
|
|
240
|
-
* which neither pending-absorption nor late-absorption can reach.
|
|
241
|
-
*/
|
|
242
|
-
private _inFlightInteractionScreen: string | undefined = undefined;
|
|
243
|
-
private _inFlightInteractionPoint: ReplayFrame['interactionPoint'] | undefined = undefined;
|
|
244
|
-
private _suppressInFlightInteraction = false;
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Last completed capture intent — used for semantic dedup.
|
|
248
|
-
* Captures with the same reason + screen within SAME_INTENT_COOLDOWN_MS are suppressed.
|
|
249
|
-
*/
|
|
250
|
-
private lastCaptureIntent: CaptureIntent | null = null;
|
|
251
|
-
|
|
252
|
-
// ── P2-0/1/5 capture state ──────────────────────────────────────────
|
|
253
|
-
/** P2-0: monotonic per-session sequence; first emitted frame is 1. */
|
|
254
|
-
private _sequenceCounter = 0;
|
|
255
|
-
/** P2-1: hash of the last EMITTED frame, for visual change detection. */
|
|
256
|
-
private _lastFrameHash: string | null = null;
|
|
257
|
-
/** P2-1/5: wall-clock of the last emitted keyframe (heartbeat base). */
|
|
258
|
-
private _lastKeyframeTs = 0;
|
|
259
|
-
/** P2-5: frameId of the last emitted keyframe — delta base reference. */
|
|
260
|
-
private _lastKeyframeId: string | null = null;
|
|
261
|
-
/** P2-5: emitted frames since the last keyframe (keyframe-interval guard). */
|
|
262
|
-
private _framesSinceKeyframe = 0;
|
|
263
|
-
|
|
264
|
-
constructor(
|
|
265
|
-
sessionId: string,
|
|
266
|
-
config: SessionReplayConfig,
|
|
267
|
-
nativeCapture: NativeCaptureFn,
|
|
268
|
-
outboxCapture?: OutboxFrameCapture | null,
|
|
269
|
-
) {
|
|
270
|
-
this.sessionId = sessionId;
|
|
271
|
-
this.config = config;
|
|
272
|
-
this.nativeCapture = nativeCapture;
|
|
273
|
-
this.outboxCapture = outboxCapture ?? null;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ─── Public API ─────────────────────────────────────────────────────
|
|
277
|
-
|
|
278
|
-
/** Set callback for when a frame is captured */
|
|
279
|
-
setFrameEmitCallback(cb: FrameEmitCallback): void {
|
|
280
|
-
this.onFrameEmit = cb;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/** Start capture according to configured mode */
|
|
284
|
-
start(): void {
|
|
285
|
-
if (this.capturing) return;
|
|
286
|
-
this.capturing = true;
|
|
287
|
-
|
|
288
|
-
// P2-0/1/5: reset per-session capture state so sequence + keyframe tracking
|
|
289
|
-
// start clean for this session lifecycle.
|
|
290
|
-
this._sequenceCounter = 0;
|
|
291
|
-
this._lastFrameHash = null;
|
|
292
|
-
this._lastKeyframeTs = 0;
|
|
293
|
-
this._lastKeyframeId = null;
|
|
294
|
-
this._framesSinceKeyframe = 0;
|
|
295
|
-
|
|
296
|
-
// Start frequency timer if in frequency mode
|
|
297
|
-
if (this.config.captureMode === 'frequency') {
|
|
298
|
-
const intervalMs = Math.max(500, this.config.intervalMs);
|
|
299
|
-
this.frequencyTimer = setInterval(() => {
|
|
300
|
-
this.triggerCapture('frequency').catch(() => { });
|
|
301
|
-
}, intervalMs);
|
|
302
|
-
logger.debug(`[ReplayCaptureManager] Frequency mode: every ${intervalMs}ms`);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
logger.debug(`[ReplayCaptureManager] Started (mode=${this.config.captureMode})`);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** Stop capture — cancels ALL pending timers and increments generation */
|
|
309
|
-
stop(): void {
|
|
310
|
-
this.capturing = false;
|
|
311
|
-
|
|
312
|
-
// Increment generation — invalidates ALL in-flight async captures
|
|
313
|
-
this.captureGeneration++;
|
|
314
|
-
|
|
315
|
-
// Cancel frequency timer
|
|
316
|
-
if (this.frequencyTimer) {
|
|
317
|
-
clearInterval(this.frequencyTimer);
|
|
318
|
-
this.frequencyTimer = null;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Cancel pending navigation capture
|
|
322
|
-
if (this.pendingNavTimeout) {
|
|
323
|
-
clearTimeout(this.pendingNavTimeout);
|
|
324
|
-
this.pendingNavTimeout = null;
|
|
325
|
-
this.pendingNavScreen = null;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Cancel pending scroll capture
|
|
329
|
-
if (this.pendingScrollTimeout) {
|
|
330
|
-
clearTimeout(this.pendingScrollTimeout);
|
|
331
|
-
this.pendingScrollTimeout = null;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Cancel pending loading capture
|
|
335
|
-
if (this.pendingLoadingTimeout) {
|
|
336
|
-
clearTimeout(this.pendingLoadingTimeout);
|
|
337
|
-
this.pendingLoadingTimeout = null;
|
|
338
|
-
this.pendingLoadingScreen = null;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Cancel pending interaction capture
|
|
342
|
-
if (this.pendingInteractionTimeout) {
|
|
343
|
-
clearTimeout(this.pendingInteractionTimeout);
|
|
344
|
-
this.pendingInteractionTimeout = null;
|
|
345
|
-
this.pendingInteractionPoint = undefined;
|
|
346
|
-
this.pendingInteractionScreen = undefined;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Clear late absorption tracking
|
|
350
|
-
this.lastCompletedInteraction = null;
|
|
351
|
-
|
|
352
|
-
// Clear in-flight interaction tracking
|
|
353
|
-
this._inFlightInteractionScreen = undefined;
|
|
354
|
-
this._inFlightInteractionPoint = undefined;
|
|
355
|
-
this._suppressInFlightInteraction = false;
|
|
356
|
-
|
|
357
|
-
// Clear dedup state
|
|
358
|
-
this.lastCaptureIntent = null;
|
|
359
|
-
|
|
360
|
-
logger.debug('[ReplayCaptureManager] Stopped (all timers cancelled, generation incremented)');
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/** Notify of a screen change — triggers cancellable delayed capture */
|
|
364
|
-
onScreenChange(screenName: string): void {
|
|
365
|
-
this.currentScreen = screenName;
|
|
366
|
-
|
|
367
|
-
if (!this.capturing) return;
|
|
368
|
-
if (this._isExcludedScreen(screenName)) return;
|
|
369
|
-
|
|
370
|
-
if (this.config.captureMode === 'navigation' || this.config.captureMode === 'interactions') {
|
|
371
|
-
// Cancel any previous pending navigation capture (debounce rapid navigations)
|
|
372
|
-
if (this.pendingNavTimeout) {
|
|
373
|
-
clearTimeout(this.pendingNavTimeout);
|
|
374
|
-
this.pendingNavTimeout = null;
|
|
375
|
-
this.pendingNavScreen = null;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Cancel any pending scroll capture — scroll on the old screen is now obsolete
|
|
379
|
-
if (this.pendingScrollTimeout) {
|
|
380
|
-
clearTimeout(this.pendingScrollTimeout);
|
|
381
|
-
this.pendingScrollTimeout = null;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Cancel pending loading capture ONLY if it was for a DIFFERENT screen.
|
|
385
|
-
if (this.pendingLoadingTimeout && this.pendingLoadingScreen !== screenName) {
|
|
386
|
-
clearTimeout(this.pendingLoadingTimeout);
|
|
387
|
-
this.pendingLoadingTimeout = null;
|
|
388
|
-
this.pendingLoadingScreen = null;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// ── Absorb pending interaction if tap caused this navigation ──────
|
|
392
|
-
// If a tap was pending and the screen changed (tap → navigation),
|
|
393
|
-
// cancel the stale interaction capture and carry its tap metadata
|
|
394
|
-
// forward into the navigation capture.
|
|
395
|
-
let absorbedInteractionPoint: ReplayFrame['interactionPoint'] | undefined;
|
|
396
|
-
if (this.pendingInteractionTimeout) {
|
|
397
|
-
clearTimeout(this.pendingInteractionTimeout);
|
|
398
|
-
absorbedInteractionPoint = this.pendingInteractionPoint;
|
|
399
|
-
this.pendingInteractionTimeout = null;
|
|
400
|
-
this.pendingInteractionPoint = undefined;
|
|
401
|
-
this.pendingInteractionScreen = undefined;
|
|
402
|
-
logger.debug(
|
|
403
|
-
`[ReplayCaptureManager] Pending interaction absorbed by navigation to ${screenName}`,
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// ── Late absorption: retroactively evict stale interaction frame ──
|
|
408
|
-
// If an interaction capture ALREADY completed (settle window expired)
|
|
409
|
-
// but navigation arrives within the grace window to a DIFFERENT screen,
|
|
410
|
-
// the interaction frame is stale (captured old screen). Evict it and
|
|
411
|
-
// carry its tap metadata forward to the navigation capture.
|
|
412
|
-
if (
|
|
413
|
-
!absorbedInteractionPoint &&
|
|
414
|
-
this.lastCompletedInteraction &&
|
|
415
|
-
this.lastCompletedInteraction.screen !== screenName &&
|
|
416
|
-
(Date.now() - this.lastCompletedInteraction.ts) < LATE_ABSORPTION_GRACE_MS
|
|
417
|
-
) {
|
|
418
|
-
const stale = this.lastCompletedInteraction;
|
|
419
|
-
absorbedInteractionPoint = stale.interactionPoint;
|
|
420
|
-
// Evict the stale frame from the frames list
|
|
421
|
-
this.frames = this.frames.filter(f => f.frameId !== stale.frameId);
|
|
422
|
-
logger.debug(
|
|
423
|
-
`[ReplayCaptureManager] Late absorption: evicted stale interaction frame ` +
|
|
424
|
-
`${stale.frameId} on ${stale.screen}, navigation to ${screenName}`,
|
|
425
|
-
);
|
|
426
|
-
this.lastCompletedInteraction = null;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// ── In-flight interaction suppression ─────────────────────────
|
|
430
|
-
// If a native interaction capture started (settle timer already fired)
|
|
431
|
-
// but hasn't returned yet, suppress it — the navigation represents
|
|
432
|
-
// the correct visual state. Carry the tap point forward if available.
|
|
433
|
-
if (
|
|
434
|
-
!absorbedInteractionPoint &&
|
|
435
|
-
this._inFlightInteractionScreen !== undefined &&
|
|
436
|
-
this._inFlightInteractionScreen !== screenName
|
|
437
|
-
) {
|
|
438
|
-
this._suppressInFlightInteraction = true;
|
|
439
|
-
if (this._inFlightInteractionPoint) {
|
|
440
|
-
absorbedInteractionPoint = this._inFlightInteractionPoint;
|
|
441
|
-
}
|
|
442
|
-
logger.debug(
|
|
443
|
-
`[ReplayCaptureManager] In-flight interaction suppressed by navigation to ${screenName}`,
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Track which screen this nav capture is for
|
|
448
|
-
this.pendingNavScreen = screenName;
|
|
449
|
-
|
|
450
|
-
// Brief delay to allow the new screen to render (but stay snappy)
|
|
451
|
-
this.pendingNavTimeout = setTimeout(() => {
|
|
452
|
-
this.pendingNavTimeout = null;
|
|
453
|
-
this.pendingNavScreen = null;
|
|
454
|
-
// Pass absorbed interaction point so the nav frame carries tap metadata
|
|
455
|
-
this.triggerCapture('navigation', screenName, absorbedInteractionPoint).catch(() => { });
|
|
456
|
-
}, 150);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Notify of a user interaction — deferred capture with navigation absorption.
|
|
462
|
-
*
|
|
463
|
-
* Instead of capturing immediately (which would snapshot the OLD screen
|
|
464
|
-
* when the tap causes navigation), the capture is deferred by
|
|
465
|
-
* INTERACTION_SETTLE_MS. If onScreenChange fires within that window,
|
|
466
|
-
* the pending interaction is absorbed into the navigation capture.
|
|
467
|
-
* If no navigation follows, the interaction capture fires normally.
|
|
468
|
-
*/
|
|
469
|
-
onInteraction(interactionPoint?: ReplayFrame['interactionPoint']): void {
|
|
470
|
-
if (!this.capturing) return;
|
|
471
|
-
if (this.currentScreen && this._isExcludedScreen(this.currentScreen)) return;
|
|
472
|
-
|
|
473
|
-
// Throttle: prevent duplicate captures from rapid gestures (500ms)
|
|
474
|
-
const now = Date.now();
|
|
475
|
-
if (now - this.lastInteractionCapture < 500) return;
|
|
476
|
-
this.lastInteractionCapture = now;
|
|
477
|
-
|
|
478
|
-
const screen = this.currentScreen ?? undefined;
|
|
479
|
-
|
|
480
|
-
// Semantic dedup: if a navigation capture is pending for the SAME screen,
|
|
481
|
-
// the navigation frame will represent the post-interaction state.
|
|
482
|
-
if (this.pendingNavTimeout && this.pendingNavScreen === screen) {
|
|
483
|
-
logger.debug('[ReplayCaptureManager] Interaction suppressed — navigation pending for same screen');
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Cancel any previous pending interaction (rapid tap replacement)
|
|
488
|
-
if (this.pendingInteractionTimeout) {
|
|
489
|
-
clearTimeout(this.pendingInteractionTimeout);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Defer the interaction capture to allow navigation to absorb it
|
|
493
|
-
this.pendingInteractionScreen = screen;
|
|
494
|
-
this.pendingInteractionPoint = interactionPoint;
|
|
495
|
-
this.pendingInteractionTimeout = setTimeout(() => {
|
|
496
|
-
this.pendingInteractionTimeout = null;
|
|
497
|
-
const captureScreen = this.pendingInteractionScreen;
|
|
498
|
-
const capturePoint = this.pendingInteractionPoint;
|
|
499
|
-
this.pendingInteractionScreen = undefined;
|
|
500
|
-
this.pendingInteractionPoint = undefined;
|
|
501
|
-
// No navigation followed → capture the interaction on the current screen
|
|
502
|
-
this.triggerCapture('interaction', captureScreen, capturePoint).catch(() => { });
|
|
503
|
-
}, INTERACTION_SETTLE_MS);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/** Notify of scroll settle — triggers delayed capture for post-scroll state */
|
|
507
|
-
onScrollSettle(screenName?: string): void {
|
|
508
|
-
if (!this.capturing) return;
|
|
509
|
-
|
|
510
|
-
// Cancel any previous pending scroll capture
|
|
511
|
-
if (this.pendingScrollTimeout) {
|
|
512
|
-
clearTimeout(this.pendingScrollTimeout);
|
|
513
|
-
this.pendingScrollTimeout = null;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Small delay to let post-scroll rendering settle
|
|
517
|
-
this.pendingScrollTimeout = setTimeout(() => {
|
|
518
|
-
this.pendingScrollTimeout = null;
|
|
519
|
-
this.triggerCapture('scroll', screenName ?? this.currentScreen ?? undefined).catch(() => { });
|
|
520
|
-
}, 150);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/** Notify of loading end — captures the settled loaded screen */
|
|
524
|
-
onLoadingEnd(screenName?: string): void {
|
|
525
|
-
if (!this.capturing) return;
|
|
526
|
-
|
|
527
|
-
const screen = screenName ?? this.currentScreen ?? undefined;
|
|
528
|
-
|
|
529
|
-
// Cancel any previous pending loading capture for ANY screen
|
|
530
|
-
if (this.pendingLoadingTimeout) {
|
|
531
|
-
clearTimeout(this.pendingLoadingTimeout);
|
|
532
|
-
this.pendingLoadingTimeout = null;
|
|
533
|
-
this.pendingLoadingScreen = null;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// If a navigation capture is pending for the SAME screen, cancel it.
|
|
537
|
-
// The loading-end capture represents the final settled state and supersedes
|
|
538
|
-
// the initial navigation capture (which would show loading/skeleton UI).
|
|
539
|
-
if (this.pendingNavTimeout && this.pendingNavScreen === screen) {
|
|
540
|
-
clearTimeout(this.pendingNavTimeout);
|
|
541
|
-
this.pendingNavTimeout = null;
|
|
542
|
-
this.pendingNavScreen = null;
|
|
543
|
-
logger.debug('[ReplayCaptureManager] Navigation capture cancelled — loading-end supersedes for same screen');
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// Track which screen this loading capture is for
|
|
547
|
-
this.pendingLoadingScreen = screen ?? null;
|
|
548
|
-
|
|
549
|
-
// Slight delay to allow the loaded content to render
|
|
550
|
-
this.pendingLoadingTimeout = setTimeout(() => {
|
|
551
|
-
this.pendingLoadingTimeout = null;
|
|
552
|
-
this.pendingLoadingScreen = null;
|
|
553
|
-
this.triggerCapture('screen_loaded', screen).catch(() => { });
|
|
554
|
-
}, 200);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/** Manual capture trigger (e.g. error-context) */
|
|
558
|
-
async captureManual(reason: CaptureReason): Promise<ReplayFrame | null> {
|
|
559
|
-
return this.triggerCapture(reason, this.currentScreen ?? undefined);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/** Protect frames near a crash from eviction */
|
|
563
|
-
protectFramesNearCrash(crashTimestamp: number, windowMs: number = 10_000): string[] {
|
|
564
|
-
const protectedIds: string[] = [];
|
|
565
|
-
for (const frame of this.frames) {
|
|
566
|
-
if (Math.abs(frame.ts - crashTimestamp) <= windowMs) {
|
|
567
|
-
this.protectedFrameIds.add(frame.frameId);
|
|
568
|
-
protectedIds.push(frame.frameId);
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
return protectedIds;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
/** Get all frames (read-only snapshot) */
|
|
575
|
-
getFrames(): readonly ReplayFrame[] {
|
|
576
|
-
return this.frames;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/** Get frame IDs for artifact index */
|
|
580
|
-
getFrameRefs(): string[] {
|
|
581
|
-
return this.frames.map(f => f.frameId);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
/** Current frame count */
|
|
585
|
-
get count(): number {
|
|
586
|
-
return this.frames.length;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/** Clear all frames */
|
|
590
|
-
clear(): void {
|
|
591
|
-
this.frames = [];
|
|
592
|
-
this.protectedFrameIds.clear();
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// ─── Core Capture ───────────────────────────────────────────────────
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Trigger a frame capture via native engine.
|
|
599
|
-
* This method ONLY orchestrates — native does the real work.
|
|
600
|
-
*
|
|
601
|
-
* Semantic dedup: if the last completed capture has the same reason + screen
|
|
602
|
-
* and happened within SAME_INTENT_COOLDOWN_MS, the capture is suppressed.
|
|
603
|
-
* Bypass reasons (manual, error-context, frequency) skip this check entirely.
|
|
604
|
-
*
|
|
605
|
-
* Session-bound generation guard: captures the generation counter before
|
|
606
|
-
* starting the async native capture and verifies it hasn't changed after.
|
|
607
|
-
* If it has, the capture result is silently discarded — the session that
|
|
608
|
-
* requested it no longer exists.
|
|
609
|
-
*/
|
|
610
|
-
private async triggerCapture(
|
|
611
|
-
reason: CaptureReason,
|
|
612
|
-
screenName?: string,
|
|
613
|
-
interactionPoint?: ReplayFrame['interactionPoint'],
|
|
614
|
-
): Promise<ReplayFrame | null> {
|
|
615
|
-
if (!this.capturing) return null;
|
|
616
|
-
|
|
617
|
-
// ── Semantic dedup check ────────────────────────────────────────
|
|
618
|
-
if (!BYPASS_DEDUP_REASONS.has(reason) && this.lastCaptureIntent) {
|
|
619
|
-
const last = this.lastCaptureIntent;
|
|
620
|
-
const sameScreen = last.screen === screenName;
|
|
621
|
-
const sameReason = last.reason === reason;
|
|
622
|
-
const withinCooldown = (Date.now() - last.ts) < SAME_INTENT_COOLDOWN_MS;
|
|
623
|
-
|
|
624
|
-
// Same reason + same screen within cooldown → semantic duplicate
|
|
625
|
-
if (sameReason && sameScreen && withinCooldown) {
|
|
626
|
-
logger.debug(
|
|
627
|
-
`[ReplayCaptureManager] Semantic dedup: ${reason}@${screenName} suppressed ` +
|
|
628
|
-
`(same intent within ${SAME_INTENT_COOLDOWN_MS}ms)`,
|
|
629
|
-
);
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// Capture generation at call time
|
|
635
|
-
const gen = this.captureGeneration;
|
|
636
|
-
|
|
637
|
-
// ── In-flight interaction tracking ─────────────────────────────
|
|
638
|
-
// Mark this capture as in-flight so onScreenChange can suppress it
|
|
639
|
-
// if navigation arrives before the native callback returns.
|
|
640
|
-
if (reason === 'interaction') {
|
|
641
|
-
this._inFlightInteractionScreen = screenName;
|
|
642
|
-
this._inFlightInteractionPoint = interactionPoint;
|
|
643
|
-
this._suppressInFlightInteraction = false;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
try {
|
|
647
|
-
// ── Capture path selection ──────────────────────────────────────
|
|
648
|
-
// Prefer the native file-outbox staged path when ready: it captures +
|
|
649
|
-
// masks + encodes natively and STAGES the image (bytes never cross the
|
|
650
|
-
// bridge). If the outbox is off / unavailable / the staged capture fails,
|
|
651
|
-
// fall back to the legacy native capture (base64 → JS upload). All
|
|
652
|
-
// orchestration below (dedup, change-detection, keyframe/delta, sequencing)
|
|
653
|
-
// is identical for both paths.
|
|
654
|
-
const screen = screenName ?? this.currentScreen ?? undefined;
|
|
655
|
-
let staged: StagedFrameResult | null = null;
|
|
656
|
-
if (this.outboxCapture) {
|
|
657
|
-
staged = await this.outboxCapture.capture(this.sessionId, screen, reason);
|
|
658
|
-
}
|
|
659
|
-
const usedStaged = staged !== null;
|
|
660
|
-
|
|
661
|
-
let result: NativeFrameResult | null;
|
|
662
|
-
if (staged) {
|
|
663
|
-
result = {
|
|
664
|
-
base64: '', // bytes stay native on the outbox path — never bridged
|
|
665
|
-
width: staged.width,
|
|
666
|
-
height: staged.height,
|
|
667
|
-
byteSize: staged.byteSize,
|
|
668
|
-
format: staged.format,
|
|
669
|
-
frameHash: staged.frameHash,
|
|
670
|
-
platform: staged.platform,
|
|
671
|
-
};
|
|
672
|
-
} else {
|
|
673
|
-
result = await this.nativeCapture(this.sessionId, reason, this.config.quality);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// Drop a staged frame if any guard below rejects it (keeps the outbox clean).
|
|
677
|
-
const discardStaged = (): void => {
|
|
678
|
-
if (usedStaged && staged) {
|
|
679
|
-
this.outboxCapture?.discard(this.sessionId, staged.frameId).catch(() => { });
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
|
-
|
|
683
|
-
// ── In-flight suppression check ─────────────────────────────
|
|
684
|
-
// Clear in-flight tracking first (before any early returns).
|
|
685
|
-
if (reason === 'interaction') {
|
|
686
|
-
this._inFlightInteractionScreen = undefined;
|
|
687
|
-
this._inFlightInteractionPoint = undefined;
|
|
688
|
-
if (this._suppressInFlightInteraction) {
|
|
689
|
-
this._suppressInFlightInteraction = false;
|
|
690
|
-
discardStaged();
|
|
691
|
-
logger.debug('[ReplayCaptureManager] In-flight interaction suppressed — navigation arrived during capture');
|
|
692
|
-
return null;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
// Generation guard: if session was stopped/restarted during async capture,
|
|
697
|
-
// discard the result to prevent stale frames
|
|
698
|
-
if (gen !== this.captureGeneration) {
|
|
699
|
-
discardStaged();
|
|
700
|
-
logger.debug('[ReplayCaptureManager] Stale capture discarded (generation mismatch)');
|
|
701
|
-
return null;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (!this.capturing) {
|
|
705
|
-
discardStaged();
|
|
706
|
-
return null;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
if (!result) {
|
|
710
|
-
// Native capture unavailable — log warning, return null
|
|
711
|
-
// NO JS fallback — this is by design
|
|
712
|
-
logger.debug('[ReplayCaptureManager] Native capture returned null — frame not captured');
|
|
713
|
-
return null;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
// ── P2-1: change-triggered capture + heartbeat keyframe ─────────
|
|
717
|
-
// Visual suppression applies ONLY to the periodic 'frequency' lane — the
|
|
718
|
-
// sole source of redundant, visually-identical consecutive frames during
|
|
719
|
-
// static viewing (the −40–60% lever). Semantic captures (navigation /
|
|
720
|
-
// interaction / scroll / screen_loaded) are already change-driven and are
|
|
721
|
-
// handled by the semantic dedup above, so they always emit — visual-hashing
|
|
722
|
-
// them risks dropping a meaningful frame whose pixels happen to match.
|
|
723
|
-
// manual / error-context are explicit intent and likewise always emit.
|
|
724
|
-
// The heartbeat (maxKeyframeIntervalMs) forces a keyframe even when nothing
|
|
725
|
-
// changed, so static periods still have a frame AND deltas keep a fresh base.
|
|
726
|
-
// Suppressed frames do NOT consume a sequence number.
|
|
727
|
-
const now = Date.now();
|
|
728
|
-
const hash = result.frameHash ?? hashBase64(result.base64);
|
|
729
|
-
const explicit = reason === 'manual' || reason === 'error-context';
|
|
730
|
-
const maxKf = this.config.maxKeyframeIntervalMs ?? 5000;
|
|
731
|
-
const heartbeatDue = (now - this._lastKeyframeTs) >= maxKf;
|
|
732
|
-
const changed = hash !== this._lastFrameHash;
|
|
733
|
-
const changeDetection = this.config.changeDetection !== false;
|
|
734
|
-
if (changeDetection && reason === 'frequency' && !changed && !heartbeatDue) {
|
|
735
|
-
discardStaged();
|
|
736
|
-
logger.debug('[ReplayCaptureManager] Change-trigger suppressed identical frequency frame');
|
|
737
|
-
return null;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// ── P2-5: keyframe vs delta decision ────────────────────────────
|
|
741
|
-
// Force a keyframe when: delta encoding is off, no base exists yet, the
|
|
742
|
-
// heartbeat is due, the keyframe-interval elapsed, or this is an explicit
|
|
743
|
-
// capture (full frame is safest). Otherwise emit a delta against the last
|
|
744
|
-
// keyframe. NOTE: real delta-byte encoding is native (pixel ops); JS owns
|
|
745
|
-
// the decision/tagging — see P2_CONTRACT.md §3/§6.
|
|
746
|
-
const deltaOn = this.config.deltaEncoding === true;
|
|
747
|
-
const kfInterval = this.config.deltaKeyframeInterval ?? 10;
|
|
748
|
-
const mustKeyframe =
|
|
749
|
-
!deltaOn ||
|
|
750
|
-
this._lastKeyframeId === null ||
|
|
751
|
-
heartbeatDue ||
|
|
752
|
-
explicit ||
|
|
753
|
-
this._framesSinceKeyframe >= kfInterval;
|
|
754
|
-
const frameType: 'keyframe' | 'delta' = mustKeyframe ? 'keyframe' : 'delta';
|
|
755
|
-
const baseFrameId = frameType === 'delta' ? this._lastKeyframeId ?? undefined : undefined;
|
|
756
|
-
|
|
757
|
-
// Build frame with artifact reference and screen context.
|
|
758
|
-
// On the native-outbox staged path the image is ALREADY written to disk
|
|
759
|
-
// under the native-assigned frameId; reuse it so commitOutboxFrame's
|
|
760
|
-
// lookup resolves (minting a fresh id here makes the staged image
|
|
761
|
-
// "missing" at commit → the frame is silently dropped → zero frames).
|
|
762
|
-
// Legacy (base64) path has no staged file, so mint a new id.
|
|
763
|
-
const frameId = staged?.frameId ?? generateFrameId();
|
|
764
|
-
|
|
765
|
-
// Fill interactionPoint screen dimensions from the capture result.
|
|
766
|
-
// interactionPoint may come from an absorbed pending interaction
|
|
767
|
-
// (tap → navigation), so attach it regardless of capture reason.
|
|
768
|
-
const resolvedInteraction = interactionPoint
|
|
769
|
-
? { ...interactionPoint, screenWidth: result.width, screenHeight: result.height }
|
|
770
|
-
: undefined;
|
|
771
|
-
|
|
772
|
-
const frame: ReplayFrame = {
|
|
773
|
-
frameId,
|
|
774
|
-
sessionId: this.sessionId,
|
|
775
|
-
ts: now,
|
|
776
|
-
sequenceNumber: ++this._sequenceCounter,
|
|
777
|
-
frameType,
|
|
778
|
-
...(baseFrameId ? { baseFrameId } : {}),
|
|
779
|
-
imageRef: frameId, // Artifact ref — transport resolves to actual content
|
|
780
|
-
width: result.width,
|
|
781
|
-
height: result.height,
|
|
782
|
-
byteSize: result.byteSize ?? 0,
|
|
783
|
-
format: result.format ?? 'jpeg',
|
|
784
|
-
quality: this.config.quality,
|
|
785
|
-
captureReason: reason,
|
|
786
|
-
sourcePlatform: result.platform,
|
|
787
|
-
screen: screenName ?? this.currentScreen ?? undefined,
|
|
788
|
-
// Attach interaction point if this was an interaction-driven capture
|
|
789
|
-
...(resolvedInteraction ? { interactionPoint: resolvedInteraction } : {}),
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
// ── Record capture intent for dedup ─────────────────────────
|
|
793
|
-
this.lastCaptureIntent = {
|
|
794
|
-
reason,
|
|
795
|
-
screen: screenName,
|
|
796
|
-
ts: Date.now(),
|
|
797
|
-
};
|
|
798
|
-
|
|
799
|
-
// Enforce frame limit with priority-based eviction
|
|
800
|
-
if (this.frames.length >= this.config.maxFrames) {
|
|
801
|
-
this._evictLowestPriorityFrame();
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
this.frames.push(frame);
|
|
805
|
-
|
|
806
|
-
// ── P2-1/5: commit change-detection + keyframe tracking ─────────
|
|
807
|
-
this._lastFrameHash = hash;
|
|
808
|
-
if (frameType === 'keyframe') {
|
|
809
|
-
this._lastKeyframeId = frameId;
|
|
810
|
-
this._lastKeyframeTs = now;
|
|
811
|
-
this._framesSinceKeyframe = 0;
|
|
812
|
-
} else {
|
|
813
|
-
this._framesSinceKeyframe++;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// ── Deliver the frame ───────────────────────────────────────────
|
|
817
|
-
// Staged (native outbox) path: commit JS-authoritative metadata so the
|
|
818
|
-
// native uploader owns delivery. Do NOT also emit base64 to the JS
|
|
819
|
-
// transport — that would double-upload the frame. If commit fails the
|
|
820
|
-
// image is left staged (no meta) and swept as an orphan on next recover().
|
|
821
|
-
// Legacy path: emit base64 to the JS transport as before.
|
|
822
|
-
if (usedStaged && staged) {
|
|
823
|
-
const meta: OutboxFrameMeta = {
|
|
824
|
-
frameId: frame.frameId,
|
|
825
|
-
sessionId: this.sessionId,
|
|
826
|
-
timestamp: frame.ts,
|
|
827
|
-
sequenceNumber: frame.sequenceNumber,
|
|
828
|
-
frameType,
|
|
829
|
-
...(baseFrameId ? { baseFrameId } : {}),
|
|
830
|
-
screenName: frame.screen ?? 'unknown',
|
|
831
|
-
trigger: reason,
|
|
832
|
-
format: staged.format,
|
|
833
|
-
contentType: staged.contentType,
|
|
834
|
-
width: staged.width,
|
|
835
|
-
height: staged.height,
|
|
836
|
-
sizeBytes: staged.byteSize,
|
|
837
|
-
masked: staged.masked,
|
|
838
|
-
};
|
|
839
|
-
try {
|
|
840
|
-
const committed = await this.outboxCapture?.commit(meta);
|
|
841
|
-
if (!committed) {
|
|
842
|
-
logger.debug('[ReplayCaptureManager] Outbox commit failed — frame staged but not uploadable');
|
|
843
|
-
}
|
|
844
|
-
} catch {
|
|
845
|
-
// Commit failure must not crash capture; orphan is swept later.
|
|
846
|
-
}
|
|
847
|
-
} else {
|
|
848
|
-
// Emit to transport — pass base64 as transport-layer data (not domain)
|
|
849
|
-
try {
|
|
850
|
-
this.onFrameEmit?.(frame, result.base64);
|
|
851
|
-
} catch {
|
|
852
|
-
// Transport emission must not crash capture
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// ── Track completed interaction for late absorption ──────────
|
|
857
|
-
// If this was an interaction capture, record its metadata so that
|
|
858
|
-
// a delayed onScreenChange can retroactively evict it if navigation
|
|
859
|
-
// follows within LATE_ABSORPTION_GRACE_MS.
|
|
860
|
-
if (reason === 'interaction') {
|
|
861
|
-
this.lastCompletedInteraction = {
|
|
862
|
-
frameId: frame.frameId,
|
|
863
|
-
screen: frame.screen,
|
|
864
|
-
interactionPoint: frame.interactionPoint,
|
|
865
|
-
ts: Date.now(),
|
|
866
|
-
};
|
|
867
|
-
} else {
|
|
868
|
-
// Non-interaction captures clear the tracker — no late absorption needed
|
|
869
|
-
this.lastCompletedInteraction = null;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
return frame;
|
|
873
|
-
} catch (err) {
|
|
874
|
-
// Clear in-flight tracking on error too
|
|
875
|
-
if (reason === 'interaction') {
|
|
876
|
-
this._inFlightInteractionScreen = undefined;
|
|
877
|
-
this._inFlightInteractionPoint = undefined;
|
|
878
|
-
this._suppressInFlightInteraction = false;
|
|
879
|
-
}
|
|
880
|
-
logger.error('[ReplayCaptureManager] Capture failed:', err);
|
|
881
|
-
return null;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
// ─── Frame Retention ────────────────────────────────────────────────
|
|
886
|
-
|
|
887
|
-
/**
|
|
888
|
-
* Evict the frame with the lowest retention priority.
|
|
889
|
-
* Crash-adjacent and error-context frames are NEVER evicted before generic frames.
|
|
890
|
-
*/
|
|
891
|
-
private _evictLowestPriorityFrame(): void {
|
|
892
|
-
let lowestIdx = -1;
|
|
893
|
-
let lowestPriority = Infinity;
|
|
894
|
-
let oldestTs = Infinity;
|
|
895
|
-
|
|
896
|
-
for (let i = 0; i < this.frames.length; i++) {
|
|
897
|
-
const frame = this.frames[i];
|
|
898
|
-
// Never evict protected (crash-adjacent) frames
|
|
899
|
-
if (this.protectedFrameIds.has(frame.frameId)) continue;
|
|
900
|
-
|
|
901
|
-
const priority = getFrameRetentionPriority(frame.captureReason);
|
|
902
|
-
if (priority < lowestPriority || (priority === lowestPriority && frame.ts < oldestTs)) {
|
|
903
|
-
lowestPriority = priority;
|
|
904
|
-
lowestIdx = i;
|
|
905
|
-
oldestTs = frame.ts;
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
if (lowestIdx >= 0) {
|
|
910
|
-
this.frames.splice(lowestIdx, 1);
|
|
911
|
-
} else {
|
|
912
|
-
// All protected — drop oldest anyway
|
|
913
|
-
this.frames.shift();
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// ─── Helpers ────────────────────────────────────────────────────────
|
|
918
|
-
|
|
919
|
-
private _isExcludedScreen(screenName: string): boolean {
|
|
920
|
-
return this.config.privacyPolicy.captureExclusions.includes(screenName);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// ─── Utils ──────────────────────────────────────────────────────────────────
|
|
925
|
-
|
|
926
|
-
function generateFrameId(): string {
|
|
927
|
-
return `frm-${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 8)}`;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
/**
|
|
931
|
-
* P2-1 change detection: cheap, allocation-light FNV-1a over the base64 string.
|
|
932
|
-
* Exact-hash only — a perceptual/near-identical match is a native concern (the
|
|
933
|
-
* native layer may supply `frameHash`; this is the JS fallback). Sampling every
|
|
934
|
-
* Nth char keeps it O(1)-ish on large frames while still being change-sensitive.
|
|
935
|
-
*/
|
|
936
|
-
function hashBase64(b64: string): string {
|
|
937
|
-
let h = 0x811c9dc5;
|
|
938
|
-
const len = b64.length;
|
|
939
|
-
const step = len > 4096 ? Math.ceil(len / 4096) : 1;
|
|
940
|
-
for (let i = 0; i < len; i += step) {
|
|
941
|
-
h ^= b64.charCodeAt(i);
|
|
942
|
-
h = Math.imul(h, 0x01000193);
|
|
943
|
-
}
|
|
944
|
-
// Fold in length so same-prefix different-length frames don't collide.
|
|
945
|
-
return `${(h >>> 0).toString(36)}-${len.toString(36)}`;
|
|
946
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* ScaleBun SDK — Replay Capture Manager
|
|
3
|
+
*
|
|
4
|
+
* Orchestration-only component for frame capture:
|
|
5
|
+
* - Decides WHEN to capture (navigation, interaction, scroll, loading, frequency triggers)
|
|
6
|
+
* - Delegates ALL frame capture to native engines via sessionReplayAdapter
|
|
7
|
+
* - NEVER performs screenshot logic itself
|
|
8
|
+
* - If native capture unavailable, returns null and logs warning
|
|
9
|
+
* - Manages frame retention with crash-adjacent priority
|
|
10
|
+
* - Uses session-bound generation guard to invalidate stale async work
|
|
11
|
+
* - All pending timers are cancelled on stop()
|
|
12
|
+
*
|
|
13
|
+
* Semantic Capture Coordination:
|
|
14
|
+
* - Tracks the last completed capture's reason + screen to prevent semantic duplicates
|
|
15
|
+
* - Navigation supersedes pending interaction for the SAME screen (interaction is already
|
|
16
|
+
* visually represented by the navigation frame)
|
|
17
|
+
* - Loading completion for the SAME screen coalesces with a pending navigation capture
|
|
18
|
+
* by cancelling the navigation capture (loading's delayed capture shows the final state)
|
|
19
|
+
* - Scroll captures have per-cycle identity and do not conflict with navigation/loading
|
|
20
|
+
* - Manual and error-context captures ALWAYS bypass coordination (explicit intent)
|
|
21
|
+
* - Genuinely distinct states (different screens, different reasons after settle) are never deduped
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { logger } from '../../core/logger/internalLogger';
|
|
25
|
+
import type {
|
|
26
|
+
ReplayFrame,
|
|
27
|
+
CaptureMode,
|
|
28
|
+
CaptureReason,
|
|
29
|
+
ReplayQuality,
|
|
30
|
+
SessionReplayConfig,
|
|
31
|
+
PrivacyPolicy,
|
|
32
|
+
NativeFrameResult,
|
|
33
|
+
} from './sessionTypes';
|
|
34
|
+
import {
|
|
35
|
+
FrameRetentionPriority,
|
|
36
|
+
getFrameRetentionPriority,
|
|
37
|
+
QUALITY_PRESETS,
|
|
38
|
+
} from './sessionTypes';
|
|
39
|
+
|
|
40
|
+
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Native capture function provided by the adapter layer.
|
|
44
|
+
* Calls the platform native engine (PixelCopy on Android, UIWindow on iOS).
|
|
45
|
+
* Returns null if native capture is unavailable.
|
|
46
|
+
*/
|
|
47
|
+
export type NativeCaptureFn = (
|
|
48
|
+
sessionId: string,
|
|
49
|
+
reason: string,
|
|
50
|
+
quality: ReplayQuality,
|
|
51
|
+
) => Promise<NativeFrameResult | null>;
|
|
52
|
+
|
|
53
|
+
export type FrameEmitCallback = (frame: ReplayFrame, imageData: string) => void;
|
|
54
|
+
|
|
55
|
+
// ─── Native File-Outbox staged capture ───────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Metadata returned by a native STAGED capture-to-file. The image bytes are
|
|
59
|
+
* already written to the native outbox (staged, not yet uploadable) — they NEVER
|
|
60
|
+
* cross the bridge. `frameHash` is a native content hash so JS change-detection
|
|
61
|
+
* works without base64.
|
|
62
|
+
*/
|
|
63
|
+
export interface StagedFrameResult {
|
|
64
|
+
frameId: string;
|
|
65
|
+
width: number;
|
|
66
|
+
height: number;
|
|
67
|
+
byteSize: number;
|
|
68
|
+
format: string;
|
|
69
|
+
contentType: string;
|
|
70
|
+
frameHash: string;
|
|
71
|
+
masked: boolean;
|
|
72
|
+
timestamp: number;
|
|
73
|
+
platform: 'android' | 'ios';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** JS-authoritative frame metadata written to the outbox on commit. */
|
|
77
|
+
export interface OutboxFrameMeta {
|
|
78
|
+
frameId: string;
|
|
79
|
+
sessionId: string;
|
|
80
|
+
timestamp: number;
|
|
81
|
+
sequenceNumber: number;
|
|
82
|
+
frameType: 'keyframe' | 'delta';
|
|
83
|
+
baseFrameId?: string;
|
|
84
|
+
screenName: string;
|
|
85
|
+
trigger: string;
|
|
86
|
+
format: string;
|
|
87
|
+
contentType: string;
|
|
88
|
+
width: number;
|
|
89
|
+
height: number;
|
|
90
|
+
sizeBytes: number;
|
|
91
|
+
masked: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Native file-outbox frame capture. `capture` stages an image and returns metadata
|
|
96
|
+
* only (or null when the outbox is off / capture fails → caller falls back to the
|
|
97
|
+
* legacy native capture). `commit` writes the JS-decided meta (making the frame
|
|
98
|
+
* uploadable); `discard` drops a staged frame the orchestrator suppressed.
|
|
99
|
+
*/
|
|
100
|
+
export interface OutboxFrameCapture {
|
|
101
|
+
capture(
|
|
102
|
+
sessionId: string,
|
|
103
|
+
screenName: string | undefined,
|
|
104
|
+
trigger: string,
|
|
105
|
+
): Promise<StagedFrameResult | null>;
|
|
106
|
+
commit(meta: OutboxFrameMeta): Promise<boolean>;
|
|
107
|
+
discard(sessionId: string, frameId: string): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── Capture Intent ─────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Represents the semantic identity of a completed capture.
|
|
114
|
+
* Used for dedup: two captures with the same intent fingerprint
|
|
115
|
+
* represent the same visual state and should not produce two frames.
|
|
116
|
+
*/
|
|
117
|
+
interface CaptureIntent {
|
|
118
|
+
reason: CaptureReason;
|
|
119
|
+
screen: string | undefined;
|
|
120
|
+
ts: number;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Reasons that always bypass semantic dedup.
|
|
125
|
+
* These are explicit user/system requests that should ALWAYS produce a frame.
|
|
126
|
+
*/
|
|
127
|
+
const BYPASS_DEDUP_REASONS: Set<CaptureReason> = new Set([
|
|
128
|
+
'manual',
|
|
129
|
+
'error-context',
|
|
130
|
+
'frequency',
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Minimum time (ms) between captures of the same semantic intent
|
|
135
|
+
* (same reason + same screen). Secondary heuristic only — the primary
|
|
136
|
+
* check is semantic (reason + screen identity).
|
|
137
|
+
*/
|
|
138
|
+
const SAME_INTENT_COOLDOWN_MS = 300;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Time (ms) to defer an interaction capture before finalizing.
|
|
142
|
+
* If onScreenChange fires within this window (i.e. the tap caused navigation),
|
|
143
|
+
* the interaction capture is cancelled and absorbed into the navigation capture.
|
|
144
|
+
* If no navigation follows, the interaction captures normally after this delay.
|
|
145
|
+
* 200ms is long enough for most React navigation timings but short enough to feel instant.
|
|
146
|
+
*/
|
|
147
|
+
const INTERACTION_SETTLE_MS = 200;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Grace window (ms) AFTER an interaction capture has already fired.
|
|
151
|
+
* If onScreenChange fires to a DIFFERENT screen within this window,
|
|
152
|
+
* the stale interaction frame is retroactively evicted and its tap
|
|
153
|
+
* metadata is carried forward to the navigation capture.
|
|
154
|
+
* Handles the intermittent case where navigation takes >INTERACTION_SETTLE_MS.
|
|
155
|
+
*/
|
|
156
|
+
const LATE_ABSORPTION_GRACE_MS = 400;
|
|
157
|
+
|
|
158
|
+
// ─── Manager ────────────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
export class ReplayCaptureManager {
|
|
161
|
+
private sessionId: string;
|
|
162
|
+
private config: SessionReplayConfig;
|
|
163
|
+
private nativeCapture: NativeCaptureFn;
|
|
164
|
+
/** Optional native file-outbox path. When ready, frames stage→commit natively. */
|
|
165
|
+
private outboxCapture: OutboxFrameCapture | null;
|
|
166
|
+
private onFrameEmit: FrameEmitCallback | null = null;
|
|
167
|
+
|
|
168
|
+
private frames: ReplayFrame[] = [];
|
|
169
|
+
/** Set of frameIds near crashes — never evict */
|
|
170
|
+
private protectedFrameIds = new Set<string>();
|
|
171
|
+
private frequencyTimer: ReturnType<typeof setInterval> | null = null;
|
|
172
|
+
private capturing = false;
|
|
173
|
+
private currentScreen: string | null = null;
|
|
174
|
+
private lastInteractionCapture = 0;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Session-bound generation counter.
|
|
178
|
+
* Incremented on stop(). All async capture work checks this before AND after
|
|
179
|
+
* native capture to ensure stale callbacks from a previous session lifecycle
|
|
180
|
+
* do not emit frames into a new session.
|
|
181
|
+
*/
|
|
182
|
+
private captureGeneration = 0;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Tracked navigation capture timeout.
|
|
186
|
+
* Cancelled on stop() and on each new onScreenChange() call (debounce).
|
|
187
|
+
*/
|
|
188
|
+
private pendingNavTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
189
|
+
/** Screen associated with the pending navigation capture */
|
|
190
|
+
private pendingNavScreen: string | null = null;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Tracked scroll settle capture timeout.
|
|
194
|
+
* Cancelled on stop().
|
|
195
|
+
*/
|
|
196
|
+
private pendingScrollTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Tracked loading end capture timeout.
|
|
200
|
+
* Cancelled on stop().
|
|
201
|
+
*/
|
|
202
|
+
private pendingLoadingTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
203
|
+
/** Screen associated with the pending loading capture */
|
|
204
|
+
private pendingLoadingScreen: string | null = null;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Pending interaction capture timeout.
|
|
208
|
+
* When a tap/gesture occurs, the capture is DEFERRED by INTERACTION_SETTLE_MS.
|
|
209
|
+
* If onScreenChange fires within that window (tap caused navigation), the
|
|
210
|
+
* pending interaction is cancelled and its tap metadata is carried forward
|
|
211
|
+
* to the navigation capture — ensuring the destination screen is captured
|
|
212
|
+
* instead of a stale pre-navigation screenshot.
|
|
213
|
+
* If no navigation follows, the interaction capture fires normally.
|
|
214
|
+
*/
|
|
215
|
+
private pendingInteractionTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
216
|
+
/** Interaction point metadata held while pending (carried to nav if absorbed) */
|
|
217
|
+
private pendingInteractionPoint: ReplayFrame['interactionPoint'] | undefined = undefined;
|
|
218
|
+
/** Screen at the time the pending interaction was created */
|
|
219
|
+
private pendingInteractionScreen: string | undefined = undefined;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Late absorption tracking.
|
|
223
|
+
* After an interaction capture fires, store its metadata so that
|
|
224
|
+
* a delayed onScreenChange can retroactively evict the stale frame
|
|
225
|
+
* and carry the tap metadata forward to the navigation capture.
|
|
226
|
+
*/
|
|
227
|
+
private lastCompletedInteraction: {
|
|
228
|
+
frameId: string;
|
|
229
|
+
screen: string | undefined;
|
|
230
|
+
interactionPoint: ReplayFrame['interactionPoint'] | undefined;
|
|
231
|
+
ts: number;
|
|
232
|
+
} | null = null;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* In-flight interaction tracking.
|
|
236
|
+
* Set when triggerCapture('interaction') starts the async native call and cleared
|
|
237
|
+
* when it completes. If onScreenChange fires for a DIFFERENT screen while a capture
|
|
238
|
+
* is in-flight, the capture is suppressed — the navigation frame is the correct state.
|
|
239
|
+
* Covers the race window between pendingInteractionTimeout firing and native returning,
|
|
240
|
+
* which neither pending-absorption nor late-absorption can reach.
|
|
241
|
+
*/
|
|
242
|
+
private _inFlightInteractionScreen: string | undefined = undefined;
|
|
243
|
+
private _inFlightInteractionPoint: ReplayFrame['interactionPoint'] | undefined = undefined;
|
|
244
|
+
private _suppressInFlightInteraction = false;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Last completed capture intent — used for semantic dedup.
|
|
248
|
+
* Captures with the same reason + screen within SAME_INTENT_COOLDOWN_MS are suppressed.
|
|
249
|
+
*/
|
|
250
|
+
private lastCaptureIntent: CaptureIntent | null = null;
|
|
251
|
+
|
|
252
|
+
// ── P2-0/1/5 capture state ──────────────────────────────────────────
|
|
253
|
+
/** P2-0: monotonic per-session sequence; first emitted frame is 1. */
|
|
254
|
+
private _sequenceCounter = 0;
|
|
255
|
+
/** P2-1: hash of the last EMITTED frame, for visual change detection. */
|
|
256
|
+
private _lastFrameHash: string | null = null;
|
|
257
|
+
/** P2-1/5: wall-clock of the last emitted keyframe (heartbeat base). */
|
|
258
|
+
private _lastKeyframeTs = 0;
|
|
259
|
+
/** P2-5: frameId of the last emitted keyframe — delta base reference. */
|
|
260
|
+
private _lastKeyframeId: string | null = null;
|
|
261
|
+
/** P2-5: emitted frames since the last keyframe (keyframe-interval guard). */
|
|
262
|
+
private _framesSinceKeyframe = 0;
|
|
263
|
+
|
|
264
|
+
constructor(
|
|
265
|
+
sessionId: string,
|
|
266
|
+
config: SessionReplayConfig,
|
|
267
|
+
nativeCapture: NativeCaptureFn,
|
|
268
|
+
outboxCapture?: OutboxFrameCapture | null,
|
|
269
|
+
) {
|
|
270
|
+
this.sessionId = sessionId;
|
|
271
|
+
this.config = config;
|
|
272
|
+
this.nativeCapture = nativeCapture;
|
|
273
|
+
this.outboxCapture = outboxCapture ?? null;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ─── Public API ─────────────────────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
/** Set callback for when a frame is captured */
|
|
279
|
+
setFrameEmitCallback(cb: FrameEmitCallback): void {
|
|
280
|
+
this.onFrameEmit = cb;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** Start capture according to configured mode */
|
|
284
|
+
start(): void {
|
|
285
|
+
if (this.capturing) return;
|
|
286
|
+
this.capturing = true;
|
|
287
|
+
|
|
288
|
+
// P2-0/1/5: reset per-session capture state so sequence + keyframe tracking
|
|
289
|
+
// start clean for this session lifecycle.
|
|
290
|
+
this._sequenceCounter = 0;
|
|
291
|
+
this._lastFrameHash = null;
|
|
292
|
+
this._lastKeyframeTs = 0;
|
|
293
|
+
this._lastKeyframeId = null;
|
|
294
|
+
this._framesSinceKeyframe = 0;
|
|
295
|
+
|
|
296
|
+
// Start frequency timer if in frequency mode
|
|
297
|
+
if (this.config.captureMode === 'frequency') {
|
|
298
|
+
const intervalMs = Math.max(500, this.config.intervalMs);
|
|
299
|
+
this.frequencyTimer = setInterval(() => {
|
|
300
|
+
this.triggerCapture('frequency').catch(() => { });
|
|
301
|
+
}, intervalMs);
|
|
302
|
+
logger.debug(`[ReplayCaptureManager] Frequency mode: every ${intervalMs}ms`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
logger.debug(`[ReplayCaptureManager] Started (mode=${this.config.captureMode})`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** Stop capture — cancels ALL pending timers and increments generation */
|
|
309
|
+
stop(): void {
|
|
310
|
+
this.capturing = false;
|
|
311
|
+
|
|
312
|
+
// Increment generation — invalidates ALL in-flight async captures
|
|
313
|
+
this.captureGeneration++;
|
|
314
|
+
|
|
315
|
+
// Cancel frequency timer
|
|
316
|
+
if (this.frequencyTimer) {
|
|
317
|
+
clearInterval(this.frequencyTimer);
|
|
318
|
+
this.frequencyTimer = null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Cancel pending navigation capture
|
|
322
|
+
if (this.pendingNavTimeout) {
|
|
323
|
+
clearTimeout(this.pendingNavTimeout);
|
|
324
|
+
this.pendingNavTimeout = null;
|
|
325
|
+
this.pendingNavScreen = null;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Cancel pending scroll capture
|
|
329
|
+
if (this.pendingScrollTimeout) {
|
|
330
|
+
clearTimeout(this.pendingScrollTimeout);
|
|
331
|
+
this.pendingScrollTimeout = null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Cancel pending loading capture
|
|
335
|
+
if (this.pendingLoadingTimeout) {
|
|
336
|
+
clearTimeout(this.pendingLoadingTimeout);
|
|
337
|
+
this.pendingLoadingTimeout = null;
|
|
338
|
+
this.pendingLoadingScreen = null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Cancel pending interaction capture
|
|
342
|
+
if (this.pendingInteractionTimeout) {
|
|
343
|
+
clearTimeout(this.pendingInteractionTimeout);
|
|
344
|
+
this.pendingInteractionTimeout = null;
|
|
345
|
+
this.pendingInteractionPoint = undefined;
|
|
346
|
+
this.pendingInteractionScreen = undefined;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Clear late absorption tracking
|
|
350
|
+
this.lastCompletedInteraction = null;
|
|
351
|
+
|
|
352
|
+
// Clear in-flight interaction tracking
|
|
353
|
+
this._inFlightInteractionScreen = undefined;
|
|
354
|
+
this._inFlightInteractionPoint = undefined;
|
|
355
|
+
this._suppressInFlightInteraction = false;
|
|
356
|
+
|
|
357
|
+
// Clear dedup state
|
|
358
|
+
this.lastCaptureIntent = null;
|
|
359
|
+
|
|
360
|
+
logger.debug('[ReplayCaptureManager] Stopped (all timers cancelled, generation incremented)');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** Notify of a screen change — triggers cancellable delayed capture */
|
|
364
|
+
onScreenChange(screenName: string): void {
|
|
365
|
+
this.currentScreen = screenName;
|
|
366
|
+
|
|
367
|
+
if (!this.capturing) return;
|
|
368
|
+
if (this._isExcludedScreen(screenName)) return;
|
|
369
|
+
|
|
370
|
+
if (this.config.captureMode === 'navigation' || this.config.captureMode === 'interactions') {
|
|
371
|
+
// Cancel any previous pending navigation capture (debounce rapid navigations)
|
|
372
|
+
if (this.pendingNavTimeout) {
|
|
373
|
+
clearTimeout(this.pendingNavTimeout);
|
|
374
|
+
this.pendingNavTimeout = null;
|
|
375
|
+
this.pendingNavScreen = null;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Cancel any pending scroll capture — scroll on the old screen is now obsolete
|
|
379
|
+
if (this.pendingScrollTimeout) {
|
|
380
|
+
clearTimeout(this.pendingScrollTimeout);
|
|
381
|
+
this.pendingScrollTimeout = null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Cancel pending loading capture ONLY if it was for a DIFFERENT screen.
|
|
385
|
+
if (this.pendingLoadingTimeout && this.pendingLoadingScreen !== screenName) {
|
|
386
|
+
clearTimeout(this.pendingLoadingTimeout);
|
|
387
|
+
this.pendingLoadingTimeout = null;
|
|
388
|
+
this.pendingLoadingScreen = null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// ── Absorb pending interaction if tap caused this navigation ──────
|
|
392
|
+
// If a tap was pending and the screen changed (tap → navigation),
|
|
393
|
+
// cancel the stale interaction capture and carry its tap metadata
|
|
394
|
+
// forward into the navigation capture.
|
|
395
|
+
let absorbedInteractionPoint: ReplayFrame['interactionPoint'] | undefined;
|
|
396
|
+
if (this.pendingInteractionTimeout) {
|
|
397
|
+
clearTimeout(this.pendingInteractionTimeout);
|
|
398
|
+
absorbedInteractionPoint = this.pendingInteractionPoint;
|
|
399
|
+
this.pendingInteractionTimeout = null;
|
|
400
|
+
this.pendingInteractionPoint = undefined;
|
|
401
|
+
this.pendingInteractionScreen = undefined;
|
|
402
|
+
logger.debug(
|
|
403
|
+
`[ReplayCaptureManager] Pending interaction absorbed by navigation to ${screenName}`,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// ── Late absorption: retroactively evict stale interaction frame ──
|
|
408
|
+
// If an interaction capture ALREADY completed (settle window expired)
|
|
409
|
+
// but navigation arrives within the grace window to a DIFFERENT screen,
|
|
410
|
+
// the interaction frame is stale (captured old screen). Evict it and
|
|
411
|
+
// carry its tap metadata forward to the navigation capture.
|
|
412
|
+
if (
|
|
413
|
+
!absorbedInteractionPoint &&
|
|
414
|
+
this.lastCompletedInteraction &&
|
|
415
|
+
this.lastCompletedInteraction.screen !== screenName &&
|
|
416
|
+
(Date.now() - this.lastCompletedInteraction.ts) < LATE_ABSORPTION_GRACE_MS
|
|
417
|
+
) {
|
|
418
|
+
const stale = this.lastCompletedInteraction;
|
|
419
|
+
absorbedInteractionPoint = stale.interactionPoint;
|
|
420
|
+
// Evict the stale frame from the frames list
|
|
421
|
+
this.frames = this.frames.filter(f => f.frameId !== stale.frameId);
|
|
422
|
+
logger.debug(
|
|
423
|
+
`[ReplayCaptureManager] Late absorption: evicted stale interaction frame ` +
|
|
424
|
+
`${stale.frameId} on ${stale.screen}, navigation to ${screenName}`,
|
|
425
|
+
);
|
|
426
|
+
this.lastCompletedInteraction = null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// ── In-flight interaction suppression ─────────────────────────
|
|
430
|
+
// If a native interaction capture started (settle timer already fired)
|
|
431
|
+
// but hasn't returned yet, suppress it — the navigation represents
|
|
432
|
+
// the correct visual state. Carry the tap point forward if available.
|
|
433
|
+
if (
|
|
434
|
+
!absorbedInteractionPoint &&
|
|
435
|
+
this._inFlightInteractionScreen !== undefined &&
|
|
436
|
+
this._inFlightInteractionScreen !== screenName
|
|
437
|
+
) {
|
|
438
|
+
this._suppressInFlightInteraction = true;
|
|
439
|
+
if (this._inFlightInteractionPoint) {
|
|
440
|
+
absorbedInteractionPoint = this._inFlightInteractionPoint;
|
|
441
|
+
}
|
|
442
|
+
logger.debug(
|
|
443
|
+
`[ReplayCaptureManager] In-flight interaction suppressed by navigation to ${screenName}`,
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Track which screen this nav capture is for
|
|
448
|
+
this.pendingNavScreen = screenName;
|
|
449
|
+
|
|
450
|
+
// Brief delay to allow the new screen to render (but stay snappy)
|
|
451
|
+
this.pendingNavTimeout = setTimeout(() => {
|
|
452
|
+
this.pendingNavTimeout = null;
|
|
453
|
+
this.pendingNavScreen = null;
|
|
454
|
+
// Pass absorbed interaction point so the nav frame carries tap metadata
|
|
455
|
+
this.triggerCapture('navigation', screenName, absorbedInteractionPoint).catch(() => { });
|
|
456
|
+
}, 150);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Notify of a user interaction — deferred capture with navigation absorption.
|
|
462
|
+
*
|
|
463
|
+
* Instead of capturing immediately (which would snapshot the OLD screen
|
|
464
|
+
* when the tap causes navigation), the capture is deferred by
|
|
465
|
+
* INTERACTION_SETTLE_MS. If onScreenChange fires within that window,
|
|
466
|
+
* the pending interaction is absorbed into the navigation capture.
|
|
467
|
+
* If no navigation follows, the interaction capture fires normally.
|
|
468
|
+
*/
|
|
469
|
+
onInteraction(interactionPoint?: ReplayFrame['interactionPoint']): void {
|
|
470
|
+
if (!this.capturing) return;
|
|
471
|
+
if (this.currentScreen && this._isExcludedScreen(this.currentScreen)) return;
|
|
472
|
+
|
|
473
|
+
// Throttle: prevent duplicate captures from rapid gestures (500ms)
|
|
474
|
+
const now = Date.now();
|
|
475
|
+
if (now - this.lastInteractionCapture < 500) return;
|
|
476
|
+
this.lastInteractionCapture = now;
|
|
477
|
+
|
|
478
|
+
const screen = this.currentScreen ?? undefined;
|
|
479
|
+
|
|
480
|
+
// Semantic dedup: if a navigation capture is pending for the SAME screen,
|
|
481
|
+
// the navigation frame will represent the post-interaction state.
|
|
482
|
+
if (this.pendingNavTimeout && this.pendingNavScreen === screen) {
|
|
483
|
+
logger.debug('[ReplayCaptureManager] Interaction suppressed — navigation pending for same screen');
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Cancel any previous pending interaction (rapid tap replacement)
|
|
488
|
+
if (this.pendingInteractionTimeout) {
|
|
489
|
+
clearTimeout(this.pendingInteractionTimeout);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Defer the interaction capture to allow navigation to absorb it
|
|
493
|
+
this.pendingInteractionScreen = screen;
|
|
494
|
+
this.pendingInteractionPoint = interactionPoint;
|
|
495
|
+
this.pendingInteractionTimeout = setTimeout(() => {
|
|
496
|
+
this.pendingInteractionTimeout = null;
|
|
497
|
+
const captureScreen = this.pendingInteractionScreen;
|
|
498
|
+
const capturePoint = this.pendingInteractionPoint;
|
|
499
|
+
this.pendingInteractionScreen = undefined;
|
|
500
|
+
this.pendingInteractionPoint = undefined;
|
|
501
|
+
// No navigation followed → capture the interaction on the current screen
|
|
502
|
+
this.triggerCapture('interaction', captureScreen, capturePoint).catch(() => { });
|
|
503
|
+
}, INTERACTION_SETTLE_MS);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** Notify of scroll settle — triggers delayed capture for post-scroll state */
|
|
507
|
+
onScrollSettle(screenName?: string): void {
|
|
508
|
+
if (!this.capturing) return;
|
|
509
|
+
|
|
510
|
+
// Cancel any previous pending scroll capture
|
|
511
|
+
if (this.pendingScrollTimeout) {
|
|
512
|
+
clearTimeout(this.pendingScrollTimeout);
|
|
513
|
+
this.pendingScrollTimeout = null;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Small delay to let post-scroll rendering settle
|
|
517
|
+
this.pendingScrollTimeout = setTimeout(() => {
|
|
518
|
+
this.pendingScrollTimeout = null;
|
|
519
|
+
this.triggerCapture('scroll', screenName ?? this.currentScreen ?? undefined).catch(() => { });
|
|
520
|
+
}, 150);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** Notify of loading end — captures the settled loaded screen */
|
|
524
|
+
onLoadingEnd(screenName?: string): void {
|
|
525
|
+
if (!this.capturing) return;
|
|
526
|
+
|
|
527
|
+
const screen = screenName ?? this.currentScreen ?? undefined;
|
|
528
|
+
|
|
529
|
+
// Cancel any previous pending loading capture for ANY screen
|
|
530
|
+
if (this.pendingLoadingTimeout) {
|
|
531
|
+
clearTimeout(this.pendingLoadingTimeout);
|
|
532
|
+
this.pendingLoadingTimeout = null;
|
|
533
|
+
this.pendingLoadingScreen = null;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// If a navigation capture is pending for the SAME screen, cancel it.
|
|
537
|
+
// The loading-end capture represents the final settled state and supersedes
|
|
538
|
+
// the initial navigation capture (which would show loading/skeleton UI).
|
|
539
|
+
if (this.pendingNavTimeout && this.pendingNavScreen === screen) {
|
|
540
|
+
clearTimeout(this.pendingNavTimeout);
|
|
541
|
+
this.pendingNavTimeout = null;
|
|
542
|
+
this.pendingNavScreen = null;
|
|
543
|
+
logger.debug('[ReplayCaptureManager] Navigation capture cancelled — loading-end supersedes for same screen');
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Track which screen this loading capture is for
|
|
547
|
+
this.pendingLoadingScreen = screen ?? null;
|
|
548
|
+
|
|
549
|
+
// Slight delay to allow the loaded content to render
|
|
550
|
+
this.pendingLoadingTimeout = setTimeout(() => {
|
|
551
|
+
this.pendingLoadingTimeout = null;
|
|
552
|
+
this.pendingLoadingScreen = null;
|
|
553
|
+
this.triggerCapture('screen_loaded', screen).catch(() => { });
|
|
554
|
+
}, 200);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** Manual capture trigger (e.g. error-context) */
|
|
558
|
+
async captureManual(reason: CaptureReason): Promise<ReplayFrame | null> {
|
|
559
|
+
return this.triggerCapture(reason, this.currentScreen ?? undefined);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/** Protect frames near a crash from eviction */
|
|
563
|
+
protectFramesNearCrash(crashTimestamp: number, windowMs: number = 10_000): string[] {
|
|
564
|
+
const protectedIds: string[] = [];
|
|
565
|
+
for (const frame of this.frames) {
|
|
566
|
+
if (Math.abs(frame.ts - crashTimestamp) <= windowMs) {
|
|
567
|
+
this.protectedFrameIds.add(frame.frameId);
|
|
568
|
+
protectedIds.push(frame.frameId);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return protectedIds;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** Get all frames (read-only snapshot) */
|
|
575
|
+
getFrames(): readonly ReplayFrame[] {
|
|
576
|
+
return this.frames;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/** Get frame IDs for artifact index */
|
|
580
|
+
getFrameRefs(): string[] {
|
|
581
|
+
return this.frames.map(f => f.frameId);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/** Current frame count */
|
|
585
|
+
get count(): number {
|
|
586
|
+
return this.frames.length;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** Clear all frames */
|
|
590
|
+
clear(): void {
|
|
591
|
+
this.frames = [];
|
|
592
|
+
this.protectedFrameIds.clear();
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// ─── Core Capture ───────────────────────────────────────────────────
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Trigger a frame capture via native engine.
|
|
599
|
+
* This method ONLY orchestrates — native does the real work.
|
|
600
|
+
*
|
|
601
|
+
* Semantic dedup: if the last completed capture has the same reason + screen
|
|
602
|
+
* and happened within SAME_INTENT_COOLDOWN_MS, the capture is suppressed.
|
|
603
|
+
* Bypass reasons (manual, error-context, frequency) skip this check entirely.
|
|
604
|
+
*
|
|
605
|
+
* Session-bound generation guard: captures the generation counter before
|
|
606
|
+
* starting the async native capture and verifies it hasn't changed after.
|
|
607
|
+
* If it has, the capture result is silently discarded — the session that
|
|
608
|
+
* requested it no longer exists.
|
|
609
|
+
*/
|
|
610
|
+
private async triggerCapture(
|
|
611
|
+
reason: CaptureReason,
|
|
612
|
+
screenName?: string,
|
|
613
|
+
interactionPoint?: ReplayFrame['interactionPoint'],
|
|
614
|
+
): Promise<ReplayFrame | null> {
|
|
615
|
+
if (!this.capturing) return null;
|
|
616
|
+
|
|
617
|
+
// ── Semantic dedup check ────────────────────────────────────────
|
|
618
|
+
if (!BYPASS_DEDUP_REASONS.has(reason) && this.lastCaptureIntent) {
|
|
619
|
+
const last = this.lastCaptureIntent;
|
|
620
|
+
const sameScreen = last.screen === screenName;
|
|
621
|
+
const sameReason = last.reason === reason;
|
|
622
|
+
const withinCooldown = (Date.now() - last.ts) < SAME_INTENT_COOLDOWN_MS;
|
|
623
|
+
|
|
624
|
+
// Same reason + same screen within cooldown → semantic duplicate
|
|
625
|
+
if (sameReason && sameScreen && withinCooldown) {
|
|
626
|
+
logger.debug(
|
|
627
|
+
`[ReplayCaptureManager] Semantic dedup: ${reason}@${screenName} suppressed ` +
|
|
628
|
+
`(same intent within ${SAME_INTENT_COOLDOWN_MS}ms)`,
|
|
629
|
+
);
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Capture generation at call time
|
|
635
|
+
const gen = this.captureGeneration;
|
|
636
|
+
|
|
637
|
+
// ── In-flight interaction tracking ─────────────────────────────
|
|
638
|
+
// Mark this capture as in-flight so onScreenChange can suppress it
|
|
639
|
+
// if navigation arrives before the native callback returns.
|
|
640
|
+
if (reason === 'interaction') {
|
|
641
|
+
this._inFlightInteractionScreen = screenName;
|
|
642
|
+
this._inFlightInteractionPoint = interactionPoint;
|
|
643
|
+
this._suppressInFlightInteraction = false;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
try {
|
|
647
|
+
// ── Capture path selection ──────────────────────────────────────
|
|
648
|
+
// Prefer the native file-outbox staged path when ready: it captures +
|
|
649
|
+
// masks + encodes natively and STAGES the image (bytes never cross the
|
|
650
|
+
// bridge). If the outbox is off / unavailable / the staged capture fails,
|
|
651
|
+
// fall back to the legacy native capture (base64 → JS upload). All
|
|
652
|
+
// orchestration below (dedup, change-detection, keyframe/delta, sequencing)
|
|
653
|
+
// is identical for both paths.
|
|
654
|
+
const screen = screenName ?? this.currentScreen ?? undefined;
|
|
655
|
+
let staged: StagedFrameResult | null = null;
|
|
656
|
+
if (this.outboxCapture) {
|
|
657
|
+
staged = await this.outboxCapture.capture(this.sessionId, screen, reason);
|
|
658
|
+
}
|
|
659
|
+
const usedStaged = staged !== null;
|
|
660
|
+
|
|
661
|
+
let result: NativeFrameResult | null;
|
|
662
|
+
if (staged) {
|
|
663
|
+
result = {
|
|
664
|
+
base64: '', // bytes stay native on the outbox path — never bridged
|
|
665
|
+
width: staged.width,
|
|
666
|
+
height: staged.height,
|
|
667
|
+
byteSize: staged.byteSize,
|
|
668
|
+
format: staged.format,
|
|
669
|
+
frameHash: staged.frameHash,
|
|
670
|
+
platform: staged.platform,
|
|
671
|
+
};
|
|
672
|
+
} else {
|
|
673
|
+
result = await this.nativeCapture(this.sessionId, reason, this.config.quality);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Drop a staged frame if any guard below rejects it (keeps the outbox clean).
|
|
677
|
+
const discardStaged = (): void => {
|
|
678
|
+
if (usedStaged && staged) {
|
|
679
|
+
this.outboxCapture?.discard(this.sessionId, staged.frameId).catch(() => { });
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// ── In-flight suppression check ─────────────────────────────
|
|
684
|
+
// Clear in-flight tracking first (before any early returns).
|
|
685
|
+
if (reason === 'interaction') {
|
|
686
|
+
this._inFlightInteractionScreen = undefined;
|
|
687
|
+
this._inFlightInteractionPoint = undefined;
|
|
688
|
+
if (this._suppressInFlightInteraction) {
|
|
689
|
+
this._suppressInFlightInteraction = false;
|
|
690
|
+
discardStaged();
|
|
691
|
+
logger.debug('[ReplayCaptureManager] In-flight interaction suppressed — navigation arrived during capture');
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Generation guard: if session was stopped/restarted during async capture,
|
|
697
|
+
// discard the result to prevent stale frames
|
|
698
|
+
if (gen !== this.captureGeneration) {
|
|
699
|
+
discardStaged();
|
|
700
|
+
logger.debug('[ReplayCaptureManager] Stale capture discarded (generation mismatch)');
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (!this.capturing) {
|
|
705
|
+
discardStaged();
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
if (!result) {
|
|
710
|
+
// Native capture unavailable — log warning, return null
|
|
711
|
+
// NO JS fallback — this is by design
|
|
712
|
+
logger.debug('[ReplayCaptureManager] Native capture returned null — frame not captured');
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// ── P2-1: change-triggered capture + heartbeat keyframe ─────────
|
|
717
|
+
// Visual suppression applies ONLY to the periodic 'frequency' lane — the
|
|
718
|
+
// sole source of redundant, visually-identical consecutive frames during
|
|
719
|
+
// static viewing (the −40–60% lever). Semantic captures (navigation /
|
|
720
|
+
// interaction / scroll / screen_loaded) are already change-driven and are
|
|
721
|
+
// handled by the semantic dedup above, so they always emit — visual-hashing
|
|
722
|
+
// them risks dropping a meaningful frame whose pixels happen to match.
|
|
723
|
+
// manual / error-context are explicit intent and likewise always emit.
|
|
724
|
+
// The heartbeat (maxKeyframeIntervalMs) forces a keyframe even when nothing
|
|
725
|
+
// changed, so static periods still have a frame AND deltas keep a fresh base.
|
|
726
|
+
// Suppressed frames do NOT consume a sequence number.
|
|
727
|
+
const now = Date.now();
|
|
728
|
+
const hash = result.frameHash ?? hashBase64(result.base64);
|
|
729
|
+
const explicit = reason === 'manual' || reason === 'error-context';
|
|
730
|
+
const maxKf = this.config.maxKeyframeIntervalMs ?? 5000;
|
|
731
|
+
const heartbeatDue = (now - this._lastKeyframeTs) >= maxKf;
|
|
732
|
+
const changed = hash !== this._lastFrameHash;
|
|
733
|
+
const changeDetection = this.config.changeDetection !== false;
|
|
734
|
+
if (changeDetection && reason === 'frequency' && !changed && !heartbeatDue) {
|
|
735
|
+
discardStaged();
|
|
736
|
+
logger.debug('[ReplayCaptureManager] Change-trigger suppressed identical frequency frame');
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// ── P2-5: keyframe vs delta decision ────────────────────────────
|
|
741
|
+
// Force a keyframe when: delta encoding is off, no base exists yet, the
|
|
742
|
+
// heartbeat is due, the keyframe-interval elapsed, or this is an explicit
|
|
743
|
+
// capture (full frame is safest). Otherwise emit a delta against the last
|
|
744
|
+
// keyframe. NOTE: real delta-byte encoding is native (pixel ops); JS owns
|
|
745
|
+
// the decision/tagging — see P2_CONTRACT.md §3/§6.
|
|
746
|
+
const deltaOn = this.config.deltaEncoding === true;
|
|
747
|
+
const kfInterval = this.config.deltaKeyframeInterval ?? 10;
|
|
748
|
+
const mustKeyframe =
|
|
749
|
+
!deltaOn ||
|
|
750
|
+
this._lastKeyframeId === null ||
|
|
751
|
+
heartbeatDue ||
|
|
752
|
+
explicit ||
|
|
753
|
+
this._framesSinceKeyframe >= kfInterval;
|
|
754
|
+
const frameType: 'keyframe' | 'delta' = mustKeyframe ? 'keyframe' : 'delta';
|
|
755
|
+
const baseFrameId = frameType === 'delta' ? this._lastKeyframeId ?? undefined : undefined;
|
|
756
|
+
|
|
757
|
+
// Build frame with artifact reference and screen context.
|
|
758
|
+
// On the native-outbox staged path the image is ALREADY written to disk
|
|
759
|
+
// under the native-assigned frameId; reuse it so commitOutboxFrame's
|
|
760
|
+
// lookup resolves (minting a fresh id here makes the staged image
|
|
761
|
+
// "missing" at commit → the frame is silently dropped → zero frames).
|
|
762
|
+
// Legacy (base64) path has no staged file, so mint a new id.
|
|
763
|
+
const frameId = staged?.frameId ?? generateFrameId();
|
|
764
|
+
|
|
765
|
+
// Fill interactionPoint screen dimensions from the capture result.
|
|
766
|
+
// interactionPoint may come from an absorbed pending interaction
|
|
767
|
+
// (tap → navigation), so attach it regardless of capture reason.
|
|
768
|
+
const resolvedInteraction = interactionPoint
|
|
769
|
+
? { ...interactionPoint, screenWidth: result.width, screenHeight: result.height }
|
|
770
|
+
: undefined;
|
|
771
|
+
|
|
772
|
+
const frame: ReplayFrame = {
|
|
773
|
+
frameId,
|
|
774
|
+
sessionId: this.sessionId,
|
|
775
|
+
ts: now,
|
|
776
|
+
sequenceNumber: ++this._sequenceCounter,
|
|
777
|
+
frameType,
|
|
778
|
+
...(baseFrameId ? { baseFrameId } : {}),
|
|
779
|
+
imageRef: frameId, // Artifact ref — transport resolves to actual content
|
|
780
|
+
width: result.width,
|
|
781
|
+
height: result.height,
|
|
782
|
+
byteSize: result.byteSize ?? 0,
|
|
783
|
+
format: result.format ?? 'jpeg',
|
|
784
|
+
quality: this.config.quality,
|
|
785
|
+
captureReason: reason,
|
|
786
|
+
sourcePlatform: result.platform,
|
|
787
|
+
screen: screenName ?? this.currentScreen ?? undefined,
|
|
788
|
+
// Attach interaction point if this was an interaction-driven capture
|
|
789
|
+
...(resolvedInteraction ? { interactionPoint: resolvedInteraction } : {}),
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// ── Record capture intent for dedup ─────────────────────────
|
|
793
|
+
this.lastCaptureIntent = {
|
|
794
|
+
reason,
|
|
795
|
+
screen: screenName,
|
|
796
|
+
ts: Date.now(),
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
// Enforce frame limit with priority-based eviction
|
|
800
|
+
if (this.frames.length >= this.config.maxFrames) {
|
|
801
|
+
this._evictLowestPriorityFrame();
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
this.frames.push(frame);
|
|
805
|
+
|
|
806
|
+
// ── P2-1/5: commit change-detection + keyframe tracking ─────────
|
|
807
|
+
this._lastFrameHash = hash;
|
|
808
|
+
if (frameType === 'keyframe') {
|
|
809
|
+
this._lastKeyframeId = frameId;
|
|
810
|
+
this._lastKeyframeTs = now;
|
|
811
|
+
this._framesSinceKeyframe = 0;
|
|
812
|
+
} else {
|
|
813
|
+
this._framesSinceKeyframe++;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// ── Deliver the frame ───────────────────────────────────────────
|
|
817
|
+
// Staged (native outbox) path: commit JS-authoritative metadata so the
|
|
818
|
+
// native uploader owns delivery. Do NOT also emit base64 to the JS
|
|
819
|
+
// transport — that would double-upload the frame. If commit fails the
|
|
820
|
+
// image is left staged (no meta) and swept as an orphan on next recover().
|
|
821
|
+
// Legacy path: emit base64 to the JS transport as before.
|
|
822
|
+
if (usedStaged && staged) {
|
|
823
|
+
const meta: OutboxFrameMeta = {
|
|
824
|
+
frameId: frame.frameId,
|
|
825
|
+
sessionId: this.sessionId,
|
|
826
|
+
timestamp: frame.ts,
|
|
827
|
+
sequenceNumber: frame.sequenceNumber,
|
|
828
|
+
frameType,
|
|
829
|
+
...(baseFrameId ? { baseFrameId } : {}),
|
|
830
|
+
screenName: frame.screen ?? 'unknown',
|
|
831
|
+
trigger: reason,
|
|
832
|
+
format: staged.format,
|
|
833
|
+
contentType: staged.contentType,
|
|
834
|
+
width: staged.width,
|
|
835
|
+
height: staged.height,
|
|
836
|
+
sizeBytes: staged.byteSize,
|
|
837
|
+
masked: staged.masked,
|
|
838
|
+
};
|
|
839
|
+
try {
|
|
840
|
+
const committed = await this.outboxCapture?.commit(meta);
|
|
841
|
+
if (!committed) {
|
|
842
|
+
logger.debug('[ReplayCaptureManager] Outbox commit failed — frame staged but not uploadable');
|
|
843
|
+
}
|
|
844
|
+
} catch {
|
|
845
|
+
// Commit failure must not crash capture; orphan is swept later.
|
|
846
|
+
}
|
|
847
|
+
} else {
|
|
848
|
+
// Emit to transport — pass base64 as transport-layer data (not domain)
|
|
849
|
+
try {
|
|
850
|
+
this.onFrameEmit?.(frame, result.base64);
|
|
851
|
+
} catch {
|
|
852
|
+
// Transport emission must not crash capture
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// ── Track completed interaction for late absorption ──────────
|
|
857
|
+
// If this was an interaction capture, record its metadata so that
|
|
858
|
+
// a delayed onScreenChange can retroactively evict it if navigation
|
|
859
|
+
// follows within LATE_ABSORPTION_GRACE_MS.
|
|
860
|
+
if (reason === 'interaction') {
|
|
861
|
+
this.lastCompletedInteraction = {
|
|
862
|
+
frameId: frame.frameId,
|
|
863
|
+
screen: frame.screen,
|
|
864
|
+
interactionPoint: frame.interactionPoint,
|
|
865
|
+
ts: Date.now(),
|
|
866
|
+
};
|
|
867
|
+
} else {
|
|
868
|
+
// Non-interaction captures clear the tracker — no late absorption needed
|
|
869
|
+
this.lastCompletedInteraction = null;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
return frame;
|
|
873
|
+
} catch (err) {
|
|
874
|
+
// Clear in-flight tracking on error too
|
|
875
|
+
if (reason === 'interaction') {
|
|
876
|
+
this._inFlightInteractionScreen = undefined;
|
|
877
|
+
this._inFlightInteractionPoint = undefined;
|
|
878
|
+
this._suppressInFlightInteraction = false;
|
|
879
|
+
}
|
|
880
|
+
logger.error('[ReplayCaptureManager] Capture failed:', err);
|
|
881
|
+
return null;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// ─── Frame Retention ────────────────────────────────────────────────
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Evict the frame with the lowest retention priority.
|
|
889
|
+
* Crash-adjacent and error-context frames are NEVER evicted before generic frames.
|
|
890
|
+
*/
|
|
891
|
+
private _evictLowestPriorityFrame(): void {
|
|
892
|
+
let lowestIdx = -1;
|
|
893
|
+
let lowestPriority = Infinity;
|
|
894
|
+
let oldestTs = Infinity;
|
|
895
|
+
|
|
896
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
897
|
+
const frame = this.frames[i];
|
|
898
|
+
// Never evict protected (crash-adjacent) frames
|
|
899
|
+
if (this.protectedFrameIds.has(frame.frameId)) continue;
|
|
900
|
+
|
|
901
|
+
const priority = getFrameRetentionPriority(frame.captureReason);
|
|
902
|
+
if (priority < lowestPriority || (priority === lowestPriority && frame.ts < oldestTs)) {
|
|
903
|
+
lowestPriority = priority;
|
|
904
|
+
lowestIdx = i;
|
|
905
|
+
oldestTs = frame.ts;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (lowestIdx >= 0) {
|
|
910
|
+
this.frames.splice(lowestIdx, 1);
|
|
911
|
+
} else {
|
|
912
|
+
// All protected — drop oldest anyway
|
|
913
|
+
this.frames.shift();
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
918
|
+
|
|
919
|
+
private _isExcludedScreen(screenName: string): boolean {
|
|
920
|
+
return this.config.privacyPolicy.captureExclusions.includes(screenName);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// ─── Utils ──────────────────────────────────────────────────────────────────
|
|
925
|
+
|
|
926
|
+
function generateFrameId(): string {
|
|
927
|
+
return `frm-${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 8)}`;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* P2-1 change detection: cheap, allocation-light FNV-1a over the base64 string.
|
|
932
|
+
* Exact-hash only — a perceptual/near-identical match is a native concern (the
|
|
933
|
+
* native layer may supply `frameHash`; this is the JS fallback). Sampling every
|
|
934
|
+
* Nth char keeps it O(1)-ish on large frames while still being change-sensitive.
|
|
935
|
+
*/
|
|
936
|
+
function hashBase64(b64: string): string {
|
|
937
|
+
let h = 0x811c9dc5;
|
|
938
|
+
const len = b64.length;
|
|
939
|
+
const step = len > 4096 ? Math.ceil(len / 4096) : 1;
|
|
940
|
+
for (let i = 0; i < len; i += step) {
|
|
941
|
+
h ^= b64.charCodeAt(i);
|
|
942
|
+
h = Math.imul(h, 0x01000193);
|
|
943
|
+
}
|
|
944
|
+
// Fold in length so same-prefix different-length frames don't collide.
|
|
945
|
+
return `${(h >>> 0).toString(36)}-${len.toString(36)}`;
|
|
946
|
+
}
|