@rejourneyco/react-native 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/android/build.gradle.kts +135 -0
  2. package/android/consumer-rules.pro +10 -0
  3. package/android/proguard-rules.pro +1 -0
  4. package/android/src/main/AndroidManifest.xml +15 -0
  5. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +2981 -0
  6. package/android/src/main/java/com/rejourney/capture/ANRHandler.kt +206 -0
  7. package/android/src/main/java/com/rejourney/capture/ActivityTracker.kt +98 -0
  8. package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +1553 -0
  9. package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +375 -0
  10. package/android/src/main/java/com/rejourney/capture/CrashHandler.kt +153 -0
  11. package/android/src/main/java/com/rejourney/capture/MotionEvent.kt +215 -0
  12. package/android/src/main/java/com/rejourney/capture/SegmentUploader.kt +512 -0
  13. package/android/src/main/java/com/rejourney/capture/VideoEncoder.kt +773 -0
  14. package/android/src/main/java/com/rejourney/capture/ViewHierarchyScanner.kt +633 -0
  15. package/android/src/main/java/com/rejourney/capture/ViewSerializer.kt +286 -0
  16. package/android/src/main/java/com/rejourney/core/Constants.kt +117 -0
  17. package/android/src/main/java/com/rejourney/core/Logger.kt +93 -0
  18. package/android/src/main/java/com/rejourney/core/Types.kt +124 -0
  19. package/android/src/main/java/com/rejourney/lifecycle/SessionLifecycleService.kt +162 -0
  20. package/android/src/main/java/com/rejourney/network/DeviceAuthManager.kt +747 -0
  21. package/android/src/main/java/com/rejourney/network/HttpClientProvider.kt +16 -0
  22. package/android/src/main/java/com/rejourney/network/NetworkMonitor.kt +272 -0
  23. package/android/src/main/java/com/rejourney/network/UploadManager.kt +1363 -0
  24. package/android/src/main/java/com/rejourney/network/UploadWorker.kt +492 -0
  25. package/android/src/main/java/com/rejourney/privacy/PrivacyMask.kt +645 -0
  26. package/android/src/main/java/com/rejourney/touch/GestureClassifier.kt +233 -0
  27. package/android/src/main/java/com/rejourney/touch/KeyboardTracker.kt +158 -0
  28. package/android/src/main/java/com/rejourney/touch/TextInputTracker.kt +181 -0
  29. package/android/src/main/java/com/rejourney/touch/TouchInterceptor.kt +591 -0
  30. package/android/src/main/java/com/rejourney/utils/EventBuffer.kt +284 -0
  31. package/android/src/main/java/com/rejourney/utils/OEMDetector.kt +154 -0
  32. package/android/src/main/java/com/rejourney/utils/PerfTiming.kt +235 -0
  33. package/android/src/main/java/com/rejourney/utils/Telemetry.kt +297 -0
  34. package/android/src/main/java/com/rejourney/utils/WindowUtils.kt +84 -0
  35. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +187 -0
  36. package/android/src/newarch/java/com/rejourney/RejourneyPackage.kt +40 -0
  37. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +218 -0
  38. package/android/src/oldarch/java/com/rejourney/RejourneyPackage.kt +23 -0
  39. package/ios/Capture/RJANRHandler.h +42 -0
  40. package/ios/Capture/RJANRHandler.m +328 -0
  41. package/ios/Capture/RJCaptureEngine.h +275 -0
  42. package/ios/Capture/RJCaptureEngine.m +2062 -0
  43. package/ios/Capture/RJCaptureHeuristics.h +80 -0
  44. package/ios/Capture/RJCaptureHeuristics.m +903 -0
  45. package/ios/Capture/RJCrashHandler.h +46 -0
  46. package/ios/Capture/RJCrashHandler.m +313 -0
  47. package/ios/Capture/RJMotionEvent.h +183 -0
  48. package/ios/Capture/RJMotionEvent.m +183 -0
  49. package/ios/Capture/RJPerformanceManager.h +100 -0
  50. package/ios/Capture/RJPerformanceManager.m +373 -0
  51. package/ios/Capture/RJPixelBufferDownscaler.h +42 -0
  52. package/ios/Capture/RJPixelBufferDownscaler.m +85 -0
  53. package/ios/Capture/RJSegmentUploader.h +146 -0
  54. package/ios/Capture/RJSegmentUploader.m +778 -0
  55. package/ios/Capture/RJVideoEncoder.h +247 -0
  56. package/ios/Capture/RJVideoEncoder.m +1036 -0
  57. package/ios/Capture/RJViewControllerTracker.h +73 -0
  58. package/ios/Capture/RJViewControllerTracker.m +508 -0
  59. package/ios/Capture/RJViewHierarchyScanner.h +215 -0
  60. package/ios/Capture/RJViewHierarchyScanner.m +1464 -0
  61. package/ios/Capture/RJViewSerializer.h +119 -0
  62. package/ios/Capture/RJViewSerializer.m +498 -0
  63. package/ios/Core/RJConstants.h +124 -0
  64. package/ios/Core/RJConstants.m +88 -0
  65. package/ios/Core/RJLifecycleManager.h +85 -0
  66. package/ios/Core/RJLifecycleManager.m +308 -0
  67. package/ios/Core/RJLogger.h +61 -0
  68. package/ios/Core/RJLogger.m +211 -0
  69. package/ios/Core/RJTypes.h +176 -0
  70. package/ios/Core/RJTypes.m +66 -0
  71. package/ios/Core/Rejourney.h +64 -0
  72. package/ios/Core/Rejourney.mm +2495 -0
  73. package/ios/Network/RJDeviceAuthManager.h +94 -0
  74. package/ios/Network/RJDeviceAuthManager.m +967 -0
  75. package/ios/Network/RJNetworkMonitor.h +68 -0
  76. package/ios/Network/RJNetworkMonitor.m +267 -0
  77. package/ios/Network/RJRetryManager.h +73 -0
  78. package/ios/Network/RJRetryManager.m +325 -0
  79. package/ios/Network/RJUploadManager.h +267 -0
  80. package/ios/Network/RJUploadManager.m +2296 -0
  81. package/ios/Privacy/RJPrivacyMask.h +163 -0
  82. package/ios/Privacy/RJPrivacyMask.m +922 -0
  83. package/ios/Rejourney.h +63 -0
  84. package/ios/Touch/RJGestureClassifier.h +130 -0
  85. package/ios/Touch/RJGestureClassifier.m +333 -0
  86. package/ios/Touch/RJTouchInterceptor.h +169 -0
  87. package/ios/Touch/RJTouchInterceptor.m +772 -0
  88. package/ios/Utils/RJEventBuffer.h +112 -0
  89. package/ios/Utils/RJEventBuffer.m +358 -0
  90. package/ios/Utils/RJGzipUtils.h +33 -0
  91. package/ios/Utils/RJGzipUtils.m +89 -0
  92. package/ios/Utils/RJKeychainManager.h +48 -0
  93. package/ios/Utils/RJKeychainManager.m +111 -0
  94. package/ios/Utils/RJPerfTiming.h +209 -0
  95. package/ios/Utils/RJPerfTiming.m +264 -0
  96. package/ios/Utils/RJTelemetry.h +92 -0
  97. package/ios/Utils/RJTelemetry.m +320 -0
  98. package/ios/Utils/RJWindowUtils.h +66 -0
  99. package/ios/Utils/RJWindowUtils.m +133 -0
  100. package/lib/commonjs/NativeRejourney.js +40 -0
  101. package/lib/commonjs/components/Mask.js +79 -0
  102. package/lib/commonjs/index.js +1381 -0
  103. package/lib/commonjs/sdk/autoTracking.js +1259 -0
  104. package/lib/commonjs/sdk/constants.js +151 -0
  105. package/lib/commonjs/sdk/errorTracking.js +199 -0
  106. package/lib/commonjs/sdk/index.js +50 -0
  107. package/lib/commonjs/sdk/metricsTracking.js +204 -0
  108. package/lib/commonjs/sdk/navigation.js +151 -0
  109. package/lib/commonjs/sdk/networkInterceptor.js +412 -0
  110. package/lib/commonjs/sdk/utils.js +363 -0
  111. package/lib/commonjs/types/expo-router.d.js +2 -0
  112. package/lib/commonjs/types/index.js +2 -0
  113. package/lib/module/NativeRejourney.js +38 -0
  114. package/lib/module/components/Mask.js +72 -0
  115. package/lib/module/index.js +1284 -0
  116. package/lib/module/sdk/autoTracking.js +1233 -0
  117. package/lib/module/sdk/constants.js +145 -0
  118. package/lib/module/sdk/errorTracking.js +189 -0
  119. package/lib/module/sdk/index.js +12 -0
  120. package/lib/module/sdk/metricsTracking.js +187 -0
  121. package/lib/module/sdk/navigation.js +143 -0
  122. package/lib/module/sdk/networkInterceptor.js +401 -0
  123. package/lib/module/sdk/utils.js +342 -0
  124. package/lib/module/types/expo-router.d.js +2 -0
  125. package/lib/module/types/index.js +2 -0
  126. package/lib/typescript/NativeRejourney.d.ts +147 -0
  127. package/lib/typescript/components/Mask.d.ts +39 -0
  128. package/lib/typescript/index.d.ts +117 -0
  129. package/lib/typescript/sdk/autoTracking.d.ts +204 -0
  130. package/lib/typescript/sdk/constants.d.ts +120 -0
  131. package/lib/typescript/sdk/errorTracking.d.ts +32 -0
  132. package/lib/typescript/sdk/index.d.ts +9 -0
  133. package/lib/typescript/sdk/metricsTracking.d.ts +58 -0
  134. package/lib/typescript/sdk/navigation.d.ts +33 -0
  135. package/lib/typescript/sdk/networkInterceptor.d.ts +47 -0
  136. package/lib/typescript/sdk/utils.d.ts +148 -0
  137. package/lib/typescript/types/index.d.ts +624 -0
  138. package/package.json +102 -0
  139. package/rejourney.podspec +21 -0
  140. package/src/NativeRejourney.ts +165 -0
  141. package/src/components/Mask.tsx +80 -0
  142. package/src/index.ts +1459 -0
  143. package/src/sdk/autoTracking.ts +1373 -0
  144. package/src/sdk/constants.ts +134 -0
  145. package/src/sdk/errorTracking.ts +231 -0
  146. package/src/sdk/index.ts +11 -0
  147. package/src/sdk/metricsTracking.ts +232 -0
  148. package/src/sdk/navigation.ts +157 -0
  149. package/src/sdk/networkInterceptor.ts +440 -0
  150. package/src/sdk/utils.ts +369 -0
  151. package/src/types/expo-router.d.ts +7 -0
  152. package/src/types/index.ts +739 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * ANR (Application Not Responding) detection handler.
3
+ * Uses a watchdog pattern to detect when the main thread is unresponsive.
4
+ */
5
+ package com.rejourney.capture
6
+
7
+ import android.content.Context
8
+ import android.content.SharedPreferences
9
+ import android.os.Handler
10
+ import android.os.Looper
11
+ import com.rejourney.core.Logger
12
+ import org.json.JSONObject
13
+ import java.util.concurrent.atomic.AtomicBoolean
14
+ import java.util.concurrent.atomic.AtomicLong
15
+
16
+ class ANRHandler private constructor(private val context: Context) {
17
+
18
+ companion object {
19
+ @Volatile
20
+ private var instance: ANRHandler? = null
21
+
22
+ private const val PREFS_NAME = "rejourney_anr"
23
+ private const val KEY_ANR_REPORT = "pending_anr_report"
24
+ private const val KEY_HAS_PENDING = "has_pending_anr"
25
+
26
+ // Default ANR threshold: 5 seconds
27
+ private const val DEFAULT_THRESHOLD_MS = 5000L
28
+ // OPTIMIZATION: Watchdog check interval increased to 3 seconds (33% CPU reduction)
29
+ // Still catches ANRs reliably while reducing background thread overhead
30
+ private const val CHECK_INTERVAL_MS = 3000L
31
+
32
+ fun getInstance(context: Context): ANRHandler {
33
+ return instance ?: synchronized(this) {
34
+ instance ?: ANRHandler(context.applicationContext).also { instance = it }
35
+ }
36
+ }
37
+ }
38
+
39
+ interface ANRListener {
40
+ fun onANRDetected(durationMs: Long, threadState: String?)
41
+ }
42
+
43
+ private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
44
+ private val mainHandler = Handler(Looper.getMainLooper())
45
+ private var watchdogThread: Thread? = null
46
+ private val isMonitoring = AtomicBoolean(false)
47
+ private val mainThreadResponded = AtomicBoolean(true)
48
+ private val lastPingTime = AtomicLong(0)
49
+
50
+ var thresholdMs: Long = DEFAULT_THRESHOLD_MS
51
+ var listener: ANRListener? = null
52
+
53
+ fun startMonitoring() {
54
+ if (isMonitoring.getAndSet(true)) {
55
+ return
56
+ }
57
+
58
+ watchdogThread = Thread({
59
+ while (isMonitoring.get()) {
60
+ checkMainThread()
61
+ try {
62
+ Thread.sleep(CHECK_INTERVAL_MS)
63
+ } catch (e: InterruptedException) {
64
+ break
65
+ }
66
+ }
67
+ }, "RejourneyANRWatchdog").apply {
68
+ priority = Thread.NORM_PRIORITY
69
+ start()
70
+ }
71
+
72
+ Logger.debug("ANR monitoring started (threshold: ${thresholdMs}ms, interval: ${CHECK_INTERVAL_MS}ms)")
73
+ }
74
+
75
+ fun stopMonitoring() {
76
+ if (!isMonitoring.getAndSet(false)) {
77
+ return
78
+ }
79
+
80
+ watchdogThread?.interrupt()
81
+ watchdogThread = null
82
+ Logger.debug("ANR monitoring stopped")
83
+ }
84
+
85
+ private fun checkMainThread() {
86
+ if (!isMonitoring.get()) return
87
+
88
+ val now = System.currentTimeMillis()
89
+
90
+ // Check if main thread responded to the last ping
91
+ if (!mainThreadResponded.get()) {
92
+ val elapsed = now - lastPingTime.get()
93
+
94
+ if (elapsed >= thresholdMs) {
95
+ handleANR(elapsed)
96
+ mainThreadResponded.set(true)
97
+ }
98
+ return
99
+ }
100
+
101
+ // Send new ping to main thread
102
+ mainThreadResponded.set(false)
103
+ lastPingTime.set(now)
104
+
105
+ mainHandler.post {
106
+ mainThreadResponded.set(true)
107
+ }
108
+ }
109
+
110
+ private fun handleANR(durationMs: Long) {
111
+ Logger.debug("[ANR] ANR DETECTED! Duration: ${durationMs}ms - main thread blocked")
112
+
113
+ // Capture thread state
114
+ val threadState = captureThreadState()
115
+ Logger.debug("[ANR] Captured main thread stack (${threadState.length} chars)")
116
+
117
+ // Build ANR report
118
+ val report = buildANRReport(durationMs, threadState)
119
+
120
+ // Persist to disk
121
+ persistANRReport(report)
122
+
123
+ // Notify listener handling thread safety internally
124
+ listener?.onANRDetected(durationMs, threadState)
125
+ }
126
+
127
+ private fun captureThreadState(): String {
128
+ return try {
129
+ val mainThread = Looper.getMainLooper().thread
130
+ mainThread.stackTrace.joinToString("\n") { element ->
131
+ "\tat $element"
132
+ }
133
+ } catch (e: Exception) {
134
+ "Unable to capture thread state: ${e.message}"
135
+ }
136
+ }
137
+
138
+ private fun buildANRReport(durationMs: Long, threadState: String?): JSONObject {
139
+ val mainPrefs = context.getSharedPreferences("rejourney", Context.MODE_PRIVATE)
140
+ val sessionId = mainPrefs.getString("rj_current_session_id", null)
141
+
142
+ return JSONObject().apply {
143
+ put("timestamp", System.currentTimeMillis())
144
+ put("durationMs", durationMs)
145
+ put("type", "anr")
146
+ put("sessionId", sessionId)
147
+ put("threadState", threadState)
148
+ put("platform", "android")
149
+ put("sdkVersion", com.rejourney.core.Constants.SDK_VERSION)
150
+
151
+ put("deviceMetadata", JSONObject().apply {
152
+ put("manufacturer", android.os.Build.MANUFACTURER)
153
+ put("model", android.os.Build.MODEL)
154
+ put("osVersion", android.os.Build.VERSION.RELEASE)
155
+ put("sdkInt", android.os.Build.VERSION.SDK_INT)
156
+ })
157
+ }
158
+ }
159
+
160
+ private fun persistANRReport(report: JSONObject) {
161
+ try {
162
+ prefs.edit()
163
+ .putString(KEY_ANR_REPORT, report.toString())
164
+ .putBoolean(KEY_HAS_PENDING, true)
165
+ .commit()
166
+ Logger.debug("ANR report persisted to disk")
167
+ } catch (e: Exception) {
168
+ Logger.error("Failed to persist ANR report", e)
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Check if there's a pending ANR report from previous session.
174
+ */
175
+ fun hasPendingANRReport(): Boolean {
176
+ return prefs.getBoolean(KEY_HAS_PENDING, false)
177
+ }
178
+
179
+ /**
180
+ * Load and purge the pending ANR report.
181
+ * Returns the ANR report as a map, or null if none exists.
182
+ */
183
+ fun loadAndPurgePendingANRReport(): Map<String, Any?>? {
184
+ if (!hasPendingANRReport()) return null
185
+
186
+ return try {
187
+ val jsonString = prefs.getString(KEY_ANR_REPORT, null) ?: return null
188
+ val json = JSONObject(jsonString)
189
+
190
+ // Clear the pending report
191
+ prefs.edit()
192
+ .remove(KEY_ANR_REPORT)
193
+ .putBoolean(KEY_HAS_PENDING, false)
194
+ .apply()
195
+
196
+ // Convert to map
197
+ json.keys().asSequence().associateWith { key ->
198
+ json.opt(key)
199
+ }
200
+ } catch (e: Exception) {
201
+ Logger.error("Failed to load pending ANR report", e)
202
+ prefs.edit().putBoolean(KEY_HAS_PENDING, false).apply()
203
+ null
204
+ }
205
+ }
206
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Activity lifecycle tracking for screen changes.
3
+ * Android equivalent of iOS RJViewControllerTracker.
4
+ *
5
+ * NOTE: Like iOS, native Activity tracking is DISABLED for React Native apps.
6
+ * RN apps run inside a single Activity, so native tracking produces noise.
7
+ * Screen names are tracked via JS-side `screenChanged()`.
8
+ */
9
+ package com.rejourney.capture
10
+
11
+ import android.app.Activity
12
+ import android.app.Application
13
+ import android.os.Bundle
14
+ import com.rejourney.core.Logger
15
+
16
+ /**
17
+ * Callback interface for activity lifecycle events.
18
+ */
19
+ interface ActivityTrackerDelegate {
20
+ fun onActivityChanged(activityName: String, previousActivityName: String?)
21
+ }
22
+
23
+ class ActivityTracker private constructor() : Application.ActivityLifecycleCallbacks {
24
+
25
+ companion object {
26
+ @Volatile
27
+ private var instance: ActivityTracker? = null
28
+
29
+ fun getInstance(): ActivityTracker {
30
+ return instance ?: synchronized(this) {
31
+ instance ?: ActivityTracker().also { instance = it }
32
+ }
33
+ }
34
+ }
35
+
36
+ var delegate: ActivityTrackerDelegate? = null
37
+ private var isEnabled: Boolean = false
38
+ private var currentActivityName: String? = null
39
+ private var previousActivityName: String? = null
40
+ private var application: Application? = null
41
+
42
+ /**
43
+ * Enable activity tracking.
44
+ * NOTE: For React Native apps, this should NOT be called - use JS tracking instead.
45
+ */
46
+ fun enableTracking(application: Application) {
47
+ if (isEnabled) return
48
+
49
+ this.application = application
50
+ application.registerActivityLifecycleCallbacks(this)
51
+ isEnabled = true
52
+ Logger.debug("Activity tracking enabled (not recommended for React Native)")
53
+ }
54
+
55
+ /**
56
+ * Disable activity tracking.
57
+ */
58
+ fun disableTracking() {
59
+ if (!isEnabled) return
60
+
61
+ application?.unregisterActivityLifecycleCallbacks(this)
62
+ isEnabled = false
63
+ currentActivityName = null
64
+ previousActivityName = null
65
+ Logger.debug("Activity tracking disabled")
66
+ }
67
+
68
+ override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
69
+
70
+ override fun onActivityStarted(activity: Activity) {}
71
+
72
+ override fun onActivityResumed(activity: Activity) {
73
+ if (!isEnabled) return
74
+
75
+ val activityName = activity.javaClass.simpleName
76
+
77
+ // Only notify if activity actually changed
78
+ if (activityName != currentActivityName) {
79
+ previousActivityName = currentActivityName
80
+ currentActivityName = activityName
81
+
82
+ delegate?.onActivityChanged(activityName, previousActivityName)
83
+ }
84
+ }
85
+
86
+ override fun onActivityPaused(activity: Activity) {}
87
+
88
+ override fun onActivityStopped(activity: Activity) {}
89
+
90
+ override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
91
+
92
+ override fun onActivityDestroyed(activity: Activity) {}
93
+
94
+ /**
95
+ * Get the current activity name (if tracking is enabled).
96
+ */
97
+ fun getCurrentActivityName(): String? = currentActivityName
98
+ }