@multiplayer-app/session-recorder-react-native 1.0.1-beta.2 → 1.0.1-beta.4

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 (465) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +216 -155
  3. package/SessionRecorderNative.podspec +9 -14
  4. package/android/build.gradle +21 -41
  5. package/android/gradle.properties +4 -4
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeConfig.kt +52 -0
  8. package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModule.kt +860 -0
  9. package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModuleSpec.kt +51 -0
  10. package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativePackage.kt +33 -0
  11. package/android/src/main/java/com/multiplayer/sessionrecordernative/model/TargetInfo.kt +9 -0
  12. package/android/src/main/java/com/multiplayer/sessionrecordernative/util/ViewUtils.kt +72 -0
  13. package/android/src/main/java/com/xxx/XxxModule.kt +23 -0
  14. package/ios/GestureTargetFinder.swift +50 -0
  15. package/ios/SessionRecorderNative.podspec +4 -2
  16. package/ios/SessionRecorderNative.swift +10 -1
  17. package/ios/SessionRecorderNativeSpec.swift +55 -0
  18. package/ios/Xxx.h +5 -0
  19. package/ios/Xxx.mm +21 -0
  20. package/lib/module/components/ScreenRecorderView/ScreenRecorderView.js +23 -0
  21. package/lib/module/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -0
  22. package/lib/module/components/ScreenRecorderView/index.js +4 -0
  23. package/lib/module/components/ScreenRecorderView/index.js.map +1 -0
  24. package/lib/module/components/SessionRecorderWidget/ErrorBanner.js +64 -0
  25. package/lib/module/components/SessionRecorderWidget/ErrorBanner.js.map +1 -0
  26. package/lib/module/components/SessionRecorderWidget/FinalPopover.js +74 -0
  27. package/lib/module/components/SessionRecorderWidget/FinalPopover.js.map +1 -0
  28. package/lib/module/components/SessionRecorderWidget/FloatingButton.js +191 -0
  29. package/lib/module/components/SessionRecorderWidget/FloatingButton.js.map +1 -0
  30. package/lib/module/components/SessionRecorderWidget/InitialPopover.js +138 -0
  31. package/lib/module/components/SessionRecorderWidget/InitialPopover.js.map +1 -0
  32. package/lib/module/components/SessionRecorderWidget/ModalContainer.js +177 -0
  33. package/lib/module/components/SessionRecorderWidget/ModalContainer.js.map +1 -0
  34. package/lib/module/components/SessionRecorderWidget/ModalHeader.js +27 -0
  35. package/lib/module/components/SessionRecorderWidget/ModalHeader.js.map +1 -0
  36. package/lib/module/components/SessionRecorderWidget/SessionRecorderWidget.js +133 -0
  37. package/lib/module/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -0
  38. package/lib/module/components/SessionRecorderWidget/icons.js +93 -0
  39. package/lib/module/components/SessionRecorderWidget/icons.js.map +1 -0
  40. package/lib/module/components/SessionRecorderWidget/index.js +5 -0
  41. package/lib/module/components/SessionRecorderWidget/index.js.map +1 -0
  42. package/lib/module/components/SessionRecorderWidget/styles.js +173 -0
  43. package/lib/module/components/SessionRecorderWidget/styles.js.map +1 -0
  44. package/lib/module/components/index.js +5 -0
  45. package/lib/module/components/index.js.map +1 -0
  46. package/lib/module/config/constants.js +42 -0
  47. package/lib/module/config/constants.js.map +1 -0
  48. package/lib/module/config/defaults.js +81 -0
  49. package/lib/module/config/defaults.js.map +1 -0
  50. package/lib/module/config/index.js +9 -0
  51. package/lib/module/config/index.js.map +1 -0
  52. package/lib/module/config/masking.js +35 -0
  53. package/lib/module/config/masking.js.map +1 -0
  54. package/lib/module/config/session-recorder.js +44 -0
  55. package/lib/module/config/session-recorder.js.map +1 -0
  56. package/lib/module/config/validators.js +28 -0
  57. package/lib/module/config/validators.js.map +1 -0
  58. package/lib/module/config/widget.js +35 -0
  59. package/lib/module/config/widget.js.map +1 -0
  60. package/lib/module/context/SessionRecorderContext.js +93 -0
  61. package/lib/module/context/SessionRecorderContext.js.map +1 -0
  62. package/lib/module/context/SessionRecorderStore.js +12 -0
  63. package/lib/module/context/SessionRecorderStore.js.map +1 -0
  64. package/lib/module/context/useSessionRecorderStore.js +20 -0
  65. package/lib/module/context/useSessionRecorderStore.js.map +1 -0
  66. package/lib/module/context/useStoreSelector.js +27 -0
  67. package/lib/module/context/useStoreSelector.js.map +1 -0
  68. package/lib/module/index.js +13 -0
  69. package/lib/module/index.js.map +1 -0
  70. package/lib/module/native/SessionRecorderNative.js +74 -0
  71. package/lib/module/native/SessionRecorderNative.js.map +1 -0
  72. package/lib/module/native/index.js +4 -0
  73. package/lib/module/native/index.js.map +1 -0
  74. package/lib/module/otel/helpers.js +218 -0
  75. package/lib/module/otel/helpers.js.map +1 -0
  76. package/lib/module/otel/index.js +95 -0
  77. package/lib/module/otel/index.js.map +1 -0
  78. package/lib/module/otel/instrumentations/index.js +102 -0
  79. package/lib/module/otel/instrumentations/index.js.map +1 -0
  80. package/lib/module/package.json +1 -0
  81. package/lib/module/patch/index.js +4 -0
  82. package/lib/module/patch/index.js.map +1 -0
  83. package/lib/module/patch/xhr.js +116 -0
  84. package/lib/module/patch/xhr.js.map +1 -0
  85. package/lib/module/recorder/eventExporter.js +130 -0
  86. package/lib/module/recorder/eventExporter.js.map +1 -0
  87. package/lib/module/recorder/gestureRecorder.js +641 -0
  88. package/lib/module/recorder/gestureRecorder.js.map +1 -0
  89. package/lib/module/recorder/index.js +168 -0
  90. package/lib/module/recorder/index.js.map +1 -0
  91. package/lib/module/recorder/navigationTracker.js +228 -0
  92. package/lib/module/recorder/navigationTracker.js.map +1 -0
  93. package/lib/module/recorder/screenRecorder.js +495 -0
  94. package/lib/module/recorder/screenRecorder.js.map +1 -0
  95. package/lib/module/services/api.service.js +149 -0
  96. package/lib/module/services/api.service.js.map +1 -0
  97. package/lib/module/services/network.service.js +178 -0
  98. package/lib/module/services/network.service.js.map +1 -0
  99. package/lib/module/services/screenMaskingService.js +107 -0
  100. package/lib/module/services/screenMaskingService.js.map +1 -0
  101. package/lib/module/services/storage.service.js +179 -0
  102. package/lib/module/services/storage.service.js.map +1 -0
  103. package/lib/module/session-recorder.js +541 -0
  104. package/lib/module/session-recorder.js.map +1 -0
  105. package/lib/module/types/configs.js +4 -0
  106. package/lib/module/types/configs.js.map +1 -0
  107. package/lib/module/types/expo-constants.d.js +2 -0
  108. package/lib/module/types/expo-constants.d.js.map +1 -0
  109. package/lib/module/types/index.js +11 -0
  110. package/lib/module/types/index.js.map +1 -0
  111. package/lib/module/types/session-recorder.js +68 -0
  112. package/lib/module/types/session-recorder.js.map +1 -0
  113. package/lib/module/types/session.js +9 -0
  114. package/lib/module/types/session.js.map +1 -0
  115. package/lib/module/utils/app-metadata.js +28 -0
  116. package/lib/module/utils/app-metadata.js.map +1 -0
  117. package/lib/module/utils/constants.optional.expo.js +6 -0
  118. package/lib/module/utils/constants.optional.expo.js.map +1 -0
  119. package/lib/module/utils/constants.optional.js +8 -0
  120. package/lib/module/utils/constants.optional.js.map +1 -0
  121. package/lib/module/utils/createStore.js +27 -0
  122. package/lib/module/utils/createStore.js.map +1 -0
  123. package/lib/module/utils/index.js +11 -0
  124. package/lib/module/utils/index.js.map +1 -0
  125. package/lib/module/utils/logger.js +193 -0
  126. package/lib/module/utils/logger.js.map +1 -0
  127. package/lib/module/utils/platform.js +340 -0
  128. package/lib/module/utils/platform.js.map +1 -0
  129. package/lib/module/utils/request-utils.js +58 -0
  130. package/lib/module/utils/request-utils.js.map +1 -0
  131. package/lib/module/utils/rrweb-events.js +276 -0
  132. package/lib/module/utils/rrweb-events.js.map +1 -0
  133. package/lib/module/utils/session.js +21 -0
  134. package/lib/module/utils/session.js.map +1 -0
  135. package/lib/module/utils/shallowEqual.js +17 -0
  136. package/lib/module/utils/shallowEqual.js.map +1 -0
  137. package/lib/module/utils/time.js +17 -0
  138. package/lib/module/utils/time.js.map +1 -0
  139. package/lib/module/utils/type-utils.js +69 -0
  140. package/lib/module/utils/type-utils.js.map +1 -0
  141. package/lib/module/version.js +4 -0
  142. package/lib/module/version.js.map +1 -0
  143. package/lib/typescript/package.json +1 -0
  144. package/lib/typescript/src/components/ScreenRecorderView/ScreenRecorderView.d.ts +6 -0
  145. package/lib/typescript/src/components/ScreenRecorderView/ScreenRecorderView.d.ts.map +1 -0
  146. package/lib/typescript/src/components/ScreenRecorderView/index.d.ts +2 -0
  147. package/lib/typescript/src/components/ScreenRecorderView/index.d.ts.map +1 -0
  148. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/ErrorBanner.d.ts +1 -0
  149. package/lib/typescript/src/components/SessionRecorderWidget/ErrorBanner.d.ts.map +1 -0
  150. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/FinalPopover.d.ts +2 -1
  151. package/lib/typescript/src/components/SessionRecorderWidget/FinalPopover.d.ts.map +1 -0
  152. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/FloatingButton.d.ts +1 -0
  153. package/lib/typescript/src/components/SessionRecorderWidget/FloatingButton.d.ts.map +1 -0
  154. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/InitialPopover.d.ts +2 -1
  155. package/lib/typescript/src/components/SessionRecorderWidget/InitialPopover.d.ts.map +1 -0
  156. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/ModalContainer.d.ts +1 -0
  157. package/lib/typescript/src/components/SessionRecorderWidget/ModalContainer.d.ts.map +1 -0
  158. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/ModalHeader.d.ts +1 -0
  159. package/lib/typescript/src/components/SessionRecorderWidget/ModalHeader.d.ts.map +1 -0
  160. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/SessionRecorderWidget.d.ts +1 -0
  161. package/lib/typescript/src/components/SessionRecorderWidget/SessionRecorderWidget.d.ts.map +1 -0
  162. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/icons.d.ts +1 -0
  163. package/lib/typescript/src/components/SessionRecorderWidget/icons.d.ts.map +1 -0
  164. package/lib/typescript/src/components/SessionRecorderWidget/index.d.ts +3 -0
  165. package/lib/typescript/src/components/SessionRecorderWidget/index.d.ts.map +1 -0
  166. package/{dist → lib/typescript/src}/components/SessionRecorderWidget/styles.d.ts +4 -3
  167. package/lib/typescript/src/components/SessionRecorderWidget/styles.d.ts.map +1 -0
  168. package/{dist → lib/typescript/src}/components/index.d.ts +1 -0
  169. package/lib/typescript/src/components/index.d.ts.map +1 -0
  170. package/{dist → lib/typescript/src}/config/constants.d.ts +1 -0
  171. package/lib/typescript/src/config/constants.d.ts.map +1 -0
  172. package/{dist → lib/typescript/src}/config/defaults.d.ts +2 -1
  173. package/lib/typescript/src/config/defaults.d.ts.map +1 -0
  174. package/{dist → lib/typescript/src}/config/index.d.ts +1 -0
  175. package/lib/typescript/src/config/index.d.ts.map +1 -0
  176. package/lib/typescript/src/config/masking.d.ts +3 -0
  177. package/lib/typescript/src/config/masking.d.ts.map +1 -0
  178. package/lib/typescript/src/config/session-recorder.d.ts +3 -0
  179. package/lib/typescript/src/config/session-recorder.d.ts.map +1 -0
  180. package/{dist → lib/typescript/src}/config/validators.d.ts +1 -0
  181. package/lib/typescript/src/config/validators.d.ts.map +1 -0
  182. package/{dist → lib/typescript/src}/config/widget.d.ts +2 -1
  183. package/lib/typescript/src/config/widget.d.ts.map +1 -0
  184. package/{dist → lib/typescript/src}/context/SessionRecorderContext.d.ts +3 -2
  185. package/lib/typescript/src/context/SessionRecorderContext.d.ts.map +1 -0
  186. package/{dist → lib/typescript/src}/context/SessionRecorderStore.d.ts +2 -1
  187. package/lib/typescript/src/context/SessionRecorderStore.d.ts.map +1 -0
  188. package/{dist → lib/typescript/src}/context/useSessionRecorderStore.d.ts +2 -1
  189. package/lib/typescript/src/context/useSessionRecorderStore.d.ts.map +1 -0
  190. package/{dist → lib/typescript/src}/context/useStoreSelector.d.ts +2 -1
  191. package/lib/typescript/src/context/useStoreSelector.d.ts.map +1 -0
  192. package/{dist → lib/typescript/src}/index.d.ts +1 -0
  193. package/lib/typescript/src/index.d.ts.map +1 -0
  194. package/{dist → lib/typescript/src}/native/SessionRecorderNative.d.ts +21 -3
  195. package/lib/typescript/src/native/SessionRecorderNative.d.ts.map +1 -0
  196. package/{dist → lib/typescript/src}/native/index.d.ts +1 -0
  197. package/lib/typescript/src/native/index.d.ts.map +1 -0
  198. package/{dist → lib/typescript/src}/otel/helpers.d.ts +3 -2
  199. package/lib/typescript/src/otel/helpers.d.ts.map +1 -0
  200. package/{dist → lib/typescript/src}/otel/index.d.ts +2 -2
  201. package/lib/typescript/src/otel/index.d.ts.map +1 -0
  202. package/{dist → lib/typescript/src}/otel/instrumentations/index.d.ts +2 -1
  203. package/lib/typescript/src/otel/instrumentations/index.d.ts.map +1 -0
  204. package/lib/typescript/src/patch/index.d.ts +2 -0
  205. package/lib/typescript/src/patch/index.d.ts.map +1 -0
  206. package/{dist → lib/typescript/src}/patch/xhr.d.ts +1 -0
  207. package/lib/typescript/src/patch/xhr.d.ts.map +1 -0
  208. package/{dist → lib/typescript/src}/recorder/eventExporter.d.ts +2 -1
  209. package/lib/typescript/src/recorder/eventExporter.d.ts.map +1 -0
  210. package/{dist → lib/typescript/src}/recorder/gestureRecorder.d.ts +3 -2
  211. package/lib/typescript/src/recorder/gestureRecorder.d.ts.map +1 -0
  212. package/{dist → lib/typescript/src}/recorder/index.d.ts +3 -2
  213. package/lib/typescript/src/recorder/index.d.ts.map +1 -0
  214. package/{dist → lib/typescript/src}/recorder/navigationTracker.d.ts +2 -1
  215. package/lib/typescript/src/recorder/navigationTracker.d.ts.map +1 -0
  216. package/{dist → lib/typescript/src}/recorder/screenRecorder.d.ts +4 -4
  217. package/lib/typescript/src/recorder/screenRecorder.d.ts.map +1 -0
  218. package/{dist → lib/typescript/src}/services/api.service.d.ts +2 -1
  219. package/lib/typescript/src/services/api.service.d.ts.map +1 -0
  220. package/{dist → lib/typescript/src}/services/network.service.d.ts +1 -0
  221. package/lib/typescript/src/services/network.service.d.ts.map +1 -0
  222. package/{dist → lib/typescript/src}/services/screenMaskingService.d.ts +2 -1
  223. package/lib/typescript/src/services/screenMaskingService.d.ts.map +1 -0
  224. package/{dist → lib/typescript/src}/services/storage.service.d.ts +2 -1
  225. package/lib/typescript/src/services/storage.service.d.ts.map +1 -0
  226. package/{dist → lib/typescript/src}/session-recorder.d.ts +3 -2
  227. package/lib/typescript/src/session-recorder.d.ts.map +1 -0
  228. package/{dist → lib/typescript/src}/types/configs.d.ts +3 -2
  229. package/lib/typescript/src/types/configs.d.ts.map +1 -0
  230. package/{dist → lib/typescript/src}/types/index.d.ts +1 -0
  231. package/lib/typescript/src/types/index.d.ts.map +1 -0
  232. package/{dist → lib/typescript/src}/types/session-recorder.d.ts +3 -2
  233. package/lib/typescript/src/types/session-recorder.d.ts.map +1 -0
  234. package/{dist → lib/typescript/src}/types/session.d.ts +1 -0
  235. package/lib/typescript/src/types/session.d.ts.map +1 -0
  236. package/{dist → lib/typescript/src}/utils/app-metadata.d.ts +1 -0
  237. package/lib/typescript/src/utils/app-metadata.d.ts.map +1 -0
  238. package/{dist → lib/typescript/src}/utils/constants.optional.d.ts +1 -0
  239. package/lib/typescript/src/utils/constants.optional.d.ts.map +1 -0
  240. package/{dist → lib/typescript/src}/utils/constants.optional.expo.d.ts +1 -0
  241. package/lib/typescript/src/utils/constants.optional.expo.d.ts.map +1 -0
  242. package/{dist → lib/typescript/src}/utils/createStore.d.ts +1 -0
  243. package/lib/typescript/src/utils/createStore.d.ts.map +1 -0
  244. package/{dist → lib/typescript/src}/utils/index.d.ts +1 -0
  245. package/lib/typescript/src/utils/index.d.ts.map +1 -0
  246. package/{dist → lib/typescript/src}/utils/logger.d.ts +1 -0
  247. package/lib/typescript/src/utils/logger.d.ts.map +1 -0
  248. package/{dist → lib/typescript/src}/utils/platform.d.ts +2 -1
  249. package/lib/typescript/src/utils/platform.d.ts.map +1 -0
  250. package/{dist → lib/typescript/src}/utils/request-utils.d.ts +1 -0
  251. package/lib/typescript/src/utils/request-utils.d.ts.map +1 -0
  252. package/{dist → lib/typescript/src}/utils/rrweb-events.d.ts +2 -1
  253. package/lib/typescript/src/utils/rrweb-events.d.ts.map +1 -0
  254. package/{dist → lib/typescript/src}/utils/session.d.ts +1 -0
  255. package/lib/typescript/src/utils/session.d.ts.map +1 -0
  256. package/{dist → lib/typescript/src}/utils/shallowEqual.d.ts +1 -0
  257. package/lib/typescript/src/utils/shallowEqual.d.ts.map +1 -0
  258. package/{dist → lib/typescript/src}/utils/time.d.ts +1 -0
  259. package/lib/typescript/src/utils/time.d.ts.map +1 -0
  260. package/{dist → lib/typescript/src}/utils/type-utils.d.ts +1 -0
  261. package/lib/typescript/src/utils/type-utils.d.ts.map +1 -0
  262. package/lib/typescript/src/version.d.ts +2 -0
  263. package/lib/typescript/src/version.d.ts.map +1 -0
  264. package/package.json +140 -39
  265. package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +20 -0
  266. package/src/components/SessionRecorderWidget/ErrorBanner.tsx +58 -0
  267. package/src/components/SessionRecorderWidget/FinalPopover.tsx +96 -0
  268. package/src/components/SessionRecorderWidget/FloatingButton.tsx +176 -0
  269. package/src/components/SessionRecorderWidget/InitialPopover.tsx +167 -0
  270. package/src/components/SessionRecorderWidget/ModalContainer.tsx +189 -0
  271. package/src/components/SessionRecorderWidget/ModalHeader.tsx +24 -0
  272. package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +136 -0
  273. package/src/components/SessionRecorderWidget/icons.tsx +52 -0
  274. package/{dist/components/SessionRecorderWidget/index.d.ts → src/components/SessionRecorderWidget/index.ts} +1 -0
  275. package/src/components/SessionRecorderWidget/styles.ts +169 -0
  276. package/src/components/index.ts +2 -0
  277. package/src/config/constants.ts +68 -0
  278. package/src/config/defaults.ts +101 -0
  279. package/src/config/index.ts +6 -0
  280. package/src/config/masking.ts +34 -0
  281. package/src/config/session-recorder.ts +59 -0
  282. package/src/config/validators.ts +31 -0
  283. package/src/config/widget.ts +38 -0
  284. package/src/context/SessionRecorderContext.tsx +138 -0
  285. package/src/context/SessionRecorderStore.ts +21 -0
  286. package/src/context/useSessionRecorderStore.ts +27 -0
  287. package/src/context/useStoreSelector.ts +34 -0
  288. package/src/index.ts +10 -0
  289. package/src/native/SessionRecorderNative.ts +164 -0
  290. package/src/native/index.ts +1 -0
  291. package/src/otel/helpers.ts +274 -0
  292. package/src/otel/index.ts +135 -0
  293. package/src/otel/instrumentations/index.ts +115 -0
  294. package/src/patch/index.ts +1 -0
  295. package/src/patch/xhr.ts +149 -0
  296. package/src/recorder/eventExporter.ts +155 -0
  297. package/src/recorder/gestureRecorder.ts +681 -0
  298. package/src/recorder/index.ts +190 -0
  299. package/src/recorder/navigationTracker.ts +245 -0
  300. package/src/recorder/screenRecorder.ts +549 -0
  301. package/src/services/api.service.ts +215 -0
  302. package/src/services/network.service.ts +182 -0
  303. package/src/services/screenMaskingService.ts +122 -0
  304. package/src/services/storage.service.ts +219 -0
  305. package/src/session-recorder.ts +591 -0
  306. package/src/types/configs.ts +96 -0
  307. package/src/types/expo-constants.d.ts +7 -0
  308. package/src/types/index.ts +29 -0
  309. package/src/types/session-recorder.ts +386 -0
  310. package/src/types/session.ts +65 -0
  311. package/src/utils/app-metadata.ts +31 -0
  312. package/src/utils/constants.optional.expo.ts +5 -0
  313. package/src/utils/constants.optional.ts +16 -0
  314. package/src/utils/createStore.ts +29 -0
  315. package/src/utils/index.ts +8 -0
  316. package/src/utils/logger.ts +216 -0
  317. package/src/utils/platform.ts +370 -0
  318. package/src/utils/request-utils.ts +61 -0
  319. package/src/utils/rrweb-events.ts +316 -0
  320. package/src/utils/session.ts +19 -0
  321. package/src/utils/shallowEqual.ts +14 -0
  322. package/src/utils/time.ts +17 -0
  323. package/src/utils/type-utils.ts +75 -0
  324. package/src/version.ts +1 -0
  325. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  326. package/android/gradle/wrapper/gradle-wrapper.properties +0 -7
  327. package/android/gradlew +0 -249
  328. package/android/gradlew.bat +0 -92
  329. package/copy-react-native-dist.sh +0 -56
  330. package/dist/components/ScreenRecorderView/ScreenRecorderView.d.ts +0 -5
  331. package/dist/components/ScreenRecorderView/ScreenRecorderView.js +0 -1
  332. package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +0 -1
  333. package/dist/components/ScreenRecorderView/index.js +0 -1
  334. package/dist/components/ScreenRecorderView/index.js.map +0 -1
  335. package/dist/components/SessionRecorderWidget/ErrorBanner.js +0 -1
  336. package/dist/components/SessionRecorderWidget/ErrorBanner.js.map +0 -1
  337. package/dist/components/SessionRecorderWidget/FinalPopover.js +0 -1
  338. package/dist/components/SessionRecorderWidget/FinalPopover.js.map +0 -1
  339. package/dist/components/SessionRecorderWidget/FloatingButton.js +0 -1
  340. package/dist/components/SessionRecorderWidget/FloatingButton.js.map +0 -1
  341. package/dist/components/SessionRecorderWidget/InitialPopover.js +0 -1
  342. package/dist/components/SessionRecorderWidget/InitialPopover.js.map +0 -1
  343. package/dist/components/SessionRecorderWidget/ModalContainer.js +0 -1
  344. package/dist/components/SessionRecorderWidget/ModalContainer.js.map +0 -1
  345. package/dist/components/SessionRecorderWidget/ModalHeader.js +0 -1
  346. package/dist/components/SessionRecorderWidget/ModalHeader.js.map +0 -1
  347. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js +0 -1
  348. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js.map +0 -1
  349. package/dist/components/SessionRecorderWidget/icons.js +0 -1
  350. package/dist/components/SessionRecorderWidget/icons.js.map +0 -1
  351. package/dist/components/SessionRecorderWidget/index.js +0 -1
  352. package/dist/components/SessionRecorderWidget/index.js.map +0 -1
  353. package/dist/components/SessionRecorderWidget/styles.js +0 -1
  354. package/dist/components/SessionRecorderWidget/styles.js.map +0 -1
  355. package/dist/components/index.js +0 -1
  356. package/dist/components/index.js.map +0 -1
  357. package/dist/config/constants.js +0 -1
  358. package/dist/config/constants.js.map +0 -1
  359. package/dist/config/defaults.js +0 -1
  360. package/dist/config/defaults.js.map +0 -1
  361. package/dist/config/index.js +0 -1
  362. package/dist/config/index.js.map +0 -1
  363. package/dist/config/masking.d.ts +0 -2
  364. package/dist/config/masking.js +0 -1
  365. package/dist/config/masking.js.map +0 -1
  366. package/dist/config/session-recorder.d.ts +0 -2
  367. package/dist/config/session-recorder.js +0 -1
  368. package/dist/config/session-recorder.js.map +0 -1
  369. package/dist/config/validators.js +0 -1
  370. package/dist/config/validators.js.map +0 -1
  371. package/dist/config/widget.js +0 -1
  372. package/dist/config/widget.js.map +0 -1
  373. package/dist/context/SessionRecorderContext.js +0 -1
  374. package/dist/context/SessionRecorderContext.js.map +0 -1
  375. package/dist/context/SessionRecorderStore.js +0 -1
  376. package/dist/context/SessionRecorderStore.js.map +0 -1
  377. package/dist/context/useSessionRecorderStore.js +0 -1
  378. package/dist/context/useSessionRecorderStore.js.map +0 -1
  379. package/dist/context/useStoreSelector.js +0 -1
  380. package/dist/context/useStoreSelector.js.map +0 -1
  381. package/dist/index.js +0 -1
  382. package/dist/index.js.map +0 -1
  383. package/dist/native/GestureRecorderNative.d.ts +0 -57
  384. package/dist/native/GestureRecorderNative.js +0 -1
  385. package/dist/native/GestureRecorderNative.js.map +0 -1
  386. package/dist/native/GestureRecorderNativeTurboSpec.d.ts +0 -31
  387. package/dist/native/GestureRecorderNativeTurboSpec.js +0 -1
  388. package/dist/native/GestureRecorderNativeTurboSpec.js.map +0 -1
  389. package/dist/native/SessionRecorderNative.js +0 -1
  390. package/dist/native/SessionRecorderNative.js.map +0 -1
  391. package/dist/native/SessionRecorderNativeTurboSpec.d.ts +0 -17
  392. package/dist/native/SessionRecorderNativeTurboSpec.js +0 -1
  393. package/dist/native/SessionRecorderNativeTurboSpec.js.map +0 -1
  394. package/dist/native/index.js +0 -1
  395. package/dist/native/index.js.map +0 -1
  396. package/dist/otel/helpers.js +0 -1
  397. package/dist/otel/helpers.js.map +0 -1
  398. package/dist/otel/index.js +0 -1
  399. package/dist/otel/index.js.map +0 -1
  400. package/dist/otel/instrumentations/index.js +0 -1
  401. package/dist/otel/instrumentations/index.js.map +0 -1
  402. package/dist/patch/index.d.ts +0 -1
  403. package/dist/patch/index.js +0 -1
  404. package/dist/patch/index.js.map +0 -1
  405. package/dist/patch/xhr.js +0 -1
  406. package/dist/patch/xhr.js.map +0 -1
  407. package/dist/recorder/eventExporter.js +0 -1
  408. package/dist/recorder/eventExporter.js.map +0 -1
  409. package/dist/recorder/gestureRecorder.js +0 -1
  410. package/dist/recorder/gestureRecorder.js.map +0 -1
  411. package/dist/recorder/index.js +0 -1
  412. package/dist/recorder/index.js.map +0 -1
  413. package/dist/recorder/navigationTracker.js +0 -1
  414. package/dist/recorder/navigationTracker.js.map +0 -1
  415. package/dist/recorder/screenRecorder.js +0 -1
  416. package/dist/recorder/screenRecorder.js.map +0 -1
  417. package/dist/services/api.service.js +0 -1
  418. package/dist/services/api.service.js.map +0 -1
  419. package/dist/services/network.service.js +0 -1
  420. package/dist/services/network.service.js.map +0 -1
  421. package/dist/services/screenMaskingService.js +0 -1
  422. package/dist/services/screenMaskingService.js.map +0 -1
  423. package/dist/services/storage.service.js +0 -1
  424. package/dist/services/storage.service.js.map +0 -1
  425. package/dist/session-recorder.js +0 -1
  426. package/dist/session-recorder.js.map +0 -1
  427. package/dist/types/configs.js +0 -1
  428. package/dist/types/configs.js.map +0 -1
  429. package/dist/types/index.js +0 -1
  430. package/dist/types/index.js.map +0 -1
  431. package/dist/types/session-recorder.js +0 -1
  432. package/dist/types/session-recorder.js.map +0 -1
  433. package/dist/types/session.js +0 -1
  434. package/dist/types/session.js.map +0 -1
  435. package/dist/utils/app-metadata.js +0 -1
  436. package/dist/utils/app-metadata.js.map +0 -1
  437. package/dist/utils/constants.optional.expo.js +0 -1
  438. package/dist/utils/constants.optional.expo.js.map +0 -1
  439. package/dist/utils/constants.optional.js +0 -1
  440. package/dist/utils/constants.optional.js.map +0 -1
  441. package/dist/utils/createStore.js +0 -1
  442. package/dist/utils/createStore.js.map +0 -1
  443. package/dist/utils/index.js +0 -1
  444. package/dist/utils/index.js.map +0 -1
  445. package/dist/utils/logger.js +0 -1
  446. package/dist/utils/logger.js.map +0 -1
  447. package/dist/utils/platform.js +0 -1
  448. package/dist/utils/platform.js.map +0 -1
  449. package/dist/utils/request-utils.js +0 -1
  450. package/dist/utils/request-utils.js.map +0 -1
  451. package/dist/utils/rrweb-events.js +0 -1
  452. package/dist/utils/rrweb-events.js.map +0 -1
  453. package/dist/utils/session.js +0 -1
  454. package/dist/utils/session.js.map +0 -1
  455. package/dist/utils/shallowEqual.js +0 -1
  456. package/dist/utils/shallowEqual.js.map +0 -1
  457. package/dist/utils/time.js +0 -1
  458. package/dist/utils/time.js.map +0 -1
  459. package/dist/utils/type-utils.js +0 -1
  460. package/dist/utils/type-utils.js.map +0 -1
  461. package/dist/version.d.ts +0 -1
  462. package/dist/version.js +0 -1
  463. package/dist/version.js.map +0 -1
  464. package/docs/AUTO_METADATA_DETECTION.md +0 -108
  465. /package/{dist/components/ScreenRecorderView/index.d.ts → src/components/ScreenRecorderView/index.ts} +0 -0
@@ -0,0 +1,681 @@
1
+ import { Dimensions, Platform } from 'react-native'
2
+ import { trace, SpanStatusCode, type Span } from '@opentelemetry/api'
3
+ import { logger } from '../utils'
4
+ import { type GestureEvent, type RecorderConfig, type EventRecorder } from '../types'
5
+ import { MouseInteractions, type eventWithTime, EventType, IncrementalSource } from '@rrweb/types'
6
+ import { type NativeGestureEvent, SessionRecorderNative, gestureEventEmitter } from '../native'
7
+ // Force TypeScript recompilation
8
+
9
+
10
+ export class GestureRecorder implements EventRecorder {
11
+ // @ts-ignore
12
+ private config?: RecorderConfig
13
+ private isRecording = false
14
+ private events: GestureEvent[] = []
15
+ private screenDimensions: { width: number; height: number } | null = null
16
+ private lastGestureTime: number = 0
17
+ private gestureThrottleMs: number = 50 // Throttle gestures to avoid spam
18
+ private lastTouchTime: number = 0
19
+ private touchThrottleMs: number = 100 // Throttle touch events to max 10 per second
20
+ private eventRecorder?: EventRecorder
21
+ private imageNodeId: number = 1 // ID of the image node for touch interactions
22
+ private screenRecorder?: any // Reference to screen recorder for force capture
23
+ private gestureEventListener?: any // Native event listener
24
+ private currentPanSpan?: Span // Aggregated span for pan gesture
25
+ private panMoveCount: number = 0
26
+
27
+ init(config: RecorderConfig, eventRecorder?: EventRecorder, screenRecorder?: any): void {
28
+ this.config = config
29
+ this.eventRecorder = eventRecorder
30
+ this.screenRecorder = screenRecorder
31
+ this._getScreenDimensions()
32
+ }
33
+
34
+ start(): void {
35
+ logger.info('GestureRecorder', 'Native gesture recording started')
36
+ this.isRecording = true
37
+ this.events = []
38
+
39
+ // Check if we're on web platform
40
+ if (Platform.OS === 'web') {
41
+ logger.warn('GestureRecorder', 'Native gesture recording not available on web platform')
42
+ return
43
+ }
44
+
45
+ // Start native gesture recording
46
+ SessionRecorderNative.startGestureRecording()
47
+ .then(() => {
48
+ logger.info('GestureRecorder', 'Native gesture recording started successfully')
49
+ this._setupGestureEventListener()
50
+ })
51
+ .catch((error) => {
52
+ logger.error('GestureRecorder', 'Failed to start native gesture recording', error)
53
+ })
54
+ }
55
+
56
+ stop(): void {
57
+ this.isRecording = false
58
+ this._removeGestureEventListener()
59
+
60
+ // Check if we're on web platform
61
+ if (Platform.OS === 'web') {
62
+ logger.warn('GestureRecorder', 'Native gesture recording not available on web platform')
63
+ return
64
+ }
65
+
66
+ // Stop native gesture recording
67
+ SessionRecorderNative.stopGestureRecording()
68
+ .then(() => {
69
+ logger.info('GestureRecorder', 'Native gesture recording stopped successfully')
70
+ })
71
+ .catch((error) => {
72
+ logger.error('GestureRecorder', 'Failed to stop native gesture recording', error)
73
+ })
74
+ }
75
+
76
+ private _getScreenDimensions(): void {
77
+ try {
78
+ this.screenDimensions = Dimensions.get('window')
79
+ } catch (error) {
80
+ // Failed to get screen dimensions - silently continue
81
+ this.screenDimensions = { width: 375, height: 667 } // Default fallback
82
+ }
83
+ }
84
+
85
+ private _setupGestureEventListener(): void {
86
+ if (!gestureEventEmitter) {
87
+ logger.warn('GestureRecorder', 'Gesture event emitter not available')
88
+ return
89
+ }
90
+
91
+ this.gestureEventListener = gestureEventEmitter.addListener(
92
+ 'onGestureDetected',
93
+ (nativeGesture: any) => {
94
+ this._handleNativeGesture(nativeGesture as NativeGestureEvent)
95
+ }
96
+ )
97
+ }
98
+
99
+ private _removeGestureEventListener(): void {
100
+ if (this.gestureEventListener) {
101
+ this.gestureEventListener.remove()
102
+ this.gestureEventListener = undefined
103
+ }
104
+ }
105
+
106
+ private _handleNativeGesture(nativeGesture: NativeGestureEvent): void {
107
+ if (!this.isRecording) return
108
+
109
+ // Throttle gestures to avoid spam
110
+ const now = Date.now()
111
+ if (now - this.lastGestureTime < this.gestureThrottleMs) {
112
+ return
113
+ }
114
+ this.lastGestureTime = now
115
+
116
+ // Convert native gesture to our format
117
+ const gesture: GestureEvent = {
118
+ type: nativeGesture.type as any,
119
+ timestamp: nativeGesture.timestamp,
120
+ coordinates: { x: nativeGesture.x, y: nativeGesture.y },
121
+ target: nativeGesture.target,
122
+ targetInfo: nativeGesture.targetInfo, // Pass through targetInfo from native
123
+ metadata: {
124
+ ...nativeGesture.metadata,
125
+ screenWidth: this.screenDimensions?.width,
126
+ screenHeight: this.screenDimensions?.height,
127
+ },
128
+ }
129
+
130
+ this.events.push(gesture)
131
+ this._sendEvent(gesture)
132
+ this._recordOpenTelemetrySpan(gesture)
133
+
134
+ // Handle specific gesture types
135
+ switch (nativeGesture.type) {
136
+ case 'tap':
137
+ this._handleTapGesture(nativeGesture)
138
+ break
139
+ case 'pan_start':
140
+ this._handlePanStartGesture(nativeGesture)
141
+ break
142
+ case 'pan_move':
143
+ this._handlePanMoveGesture(nativeGesture)
144
+ break
145
+ case 'pan_end':
146
+ this._handlePanEndGesture(nativeGesture)
147
+ break
148
+ case 'long_press':
149
+ this._handleLongPressGesture(nativeGesture)
150
+ break
151
+ case 'pinch':
152
+ this._handlePinchGesture(nativeGesture)
153
+ break
154
+ case 'swipe':
155
+ this._handleSwipeGesture(nativeGesture)
156
+ break
157
+ }
158
+ }
159
+
160
+ private _handleTapGesture(nativeGesture: NativeGestureEvent): void {
161
+ this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
162
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
163
+ }
164
+
165
+ private _handlePanStartGesture(nativeGesture: NativeGestureEvent): void {
166
+ this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
167
+ }
168
+
169
+ private _handlePanMoveGesture(nativeGesture: NativeGestureEvent): void {
170
+ this.recordTouchMove(nativeGesture.x, nativeGesture.y, nativeGesture.target)
171
+ }
172
+
173
+ private _handlePanEndGesture(nativeGesture: NativeGestureEvent): void {
174
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
175
+ }
176
+
177
+ private _handleLongPressGesture(nativeGesture: NativeGestureEvent): void {
178
+ this.recordTouchStart(nativeGesture.x, nativeGesture.y, nativeGesture.target)
179
+ this.recordTouchEnd(nativeGesture.x, nativeGesture.y, nativeGesture.target)
180
+ }
181
+
182
+ private _handlePinchGesture(nativeGesture: NativeGestureEvent): void {
183
+ this.recordPinch(
184
+ nativeGesture.metadata?.scale || 1.0,
185
+ nativeGesture.target,
186
+ nativeGesture.metadata?.velocity || 0
187
+ )
188
+ }
189
+
190
+ private _handleSwipeGesture(nativeGesture: NativeGestureEvent): void {
191
+ this.recordSwipe(
192
+ nativeGesture.metadata?.direction || 'unknown',
193
+ nativeGesture.target,
194
+ nativeGesture.metadata?.velocity || 0
195
+ )
196
+ }
197
+
198
+ private _sendEvent(event: GestureEvent): void {
199
+ // Send event to backend or store locally
200
+ logger.debug('GestureRecorder', 'Gesture event recorded', { type: event.type, target: event.target })
201
+ }
202
+
203
+ private _recordOpenTelemetrySpan(event: GestureEvent): void {
204
+ try {
205
+ logger.debug('GestureRecorder', 'Creating OTEL span for native gesture', {
206
+ type: event.type,
207
+ target: event.target,
208
+ targetInfo: event.targetInfo,
209
+ hasTargetInfo: !!event.targetInfo
210
+ })
211
+ // Special handling to aggregate pan gestures into a single span
212
+ if (event.type === 'pan_start') {
213
+ // End any previously dangling pan span defensively
214
+ if (this.currentPanSpan) {
215
+ this.currentPanSpan.setStatus({ code: SpanStatusCode.OK })
216
+ this.currentPanSpan.end()
217
+ }
218
+ this.panMoveCount = 0
219
+ const panSpan = trace
220
+ .getTracer('@opentelemetry/instrumentation-user-interaction')
221
+ .startSpan('NativeGesture.pan', {
222
+ startTime: event.timestamp,
223
+ })
224
+
225
+ panSpan.setAttribute('gesture.type', 'pan')
226
+ panSpan.setAttribute('gesture.timestamp', event.timestamp)
227
+ panSpan.setAttribute('gesture.platform', 'react-native')
228
+ panSpan.setAttribute('gesture.source', 'native-module')
229
+
230
+ if (event.coordinates) {
231
+ panSpan.setAttribute('gesture.start.x', event.coordinates.x)
232
+ panSpan.setAttribute('gesture.start.y', event.coordinates.y)
233
+ }
234
+ if (event.target) {
235
+ panSpan.setAttribute('gesture.target', this._truncateText(event.target, 50))
236
+ }
237
+ // Enrich with target info if provided
238
+ const info = event.targetInfo
239
+ if (info) {
240
+ if (info.label) {
241
+ const truncatedLabel = this._truncateText(String(info.label), 50)
242
+ panSpan.setAttribute('gesture.target.label', truncatedLabel)
243
+ }
244
+ if (info.role) {
245
+ panSpan.setAttribute('gesture.target.role', String(info.role))
246
+ }
247
+ if (info.testId) {
248
+ panSpan.setAttribute('gesture.target.test_id', String(info.testId))
249
+ }
250
+ if (info.text) {
251
+ const truncatedText = this._truncateText(String(info.text), 50)
252
+ panSpan.setAttribute('gesture.target.text', truncatedText)
253
+ }
254
+ }
255
+ // Save the span for subsequent move/end events
256
+ this.currentPanSpan = panSpan
257
+ return
258
+ }
259
+
260
+ if (event.type === 'pan_move') {
261
+ if (this.currentPanSpan) {
262
+ this.panMoveCount += 1
263
+ this.currentPanSpan.setAttribute('gesture.pan.move_count', this.panMoveCount)
264
+ if (event.coordinates) {
265
+ this.currentPanSpan.setAttribute('gesture.last.x', event.coordinates.x)
266
+ this.currentPanSpan.setAttribute('gesture.last.y', event.coordinates.y)
267
+ }
268
+ // Don't end the span here; just update it
269
+ return
270
+ }
271
+ // If we received a move without a start, fall through to single-shot span below
272
+ }
273
+
274
+ if (event.type === 'pan_end') {
275
+ if (this.currentPanSpan) {
276
+ if (event.coordinates) {
277
+ this.currentPanSpan.setAttribute('gesture.end.x', event.coordinates.x)
278
+ this.currentPanSpan.setAttribute('gesture.end.y', event.coordinates.y)
279
+ }
280
+ this.currentPanSpan.setStatus({ code: SpanStatusCode.OK })
281
+ this.currentPanSpan.end()
282
+ this.currentPanSpan = undefined
283
+ this.panMoveCount = 0
284
+ return
285
+ }
286
+ // If no current span, fall through and create a single-shot span for the end event
287
+ }
288
+
289
+ // Default behavior: create a short-lived span per non-pan event
290
+ const span = trace
291
+ .getTracer('@opentelemetry/instrumentation-user-interaction')
292
+ .startSpan(`NativeGesture.${event.type}`, {
293
+ startTime: event.timestamp,
294
+ attributes: {
295
+ 'gesture.type': event.type,
296
+ 'gesture.timestamp': event.timestamp,
297
+ 'gesture.platform': 'react-native',
298
+ 'gesture.source': 'native-module',
299
+ },
300
+ })
301
+
302
+ if (event.coordinates) {
303
+ span.setAttribute('gesture.coordinates.x', event.coordinates.x)
304
+ span.setAttribute('gesture.coordinates.y', event.coordinates.y)
305
+
306
+ // Calculate relative position
307
+ if (this.screenDimensions) {
308
+ const relativeX = event.coordinates.x / this.screenDimensions.width
309
+ const relativeY = event.coordinates.y / this.screenDimensions.height
310
+ span.setAttribute('gesture.coordinates.relative_x', relativeX)
311
+ span.setAttribute('gesture.coordinates.relative_y', relativeY)
312
+ }
313
+ }
314
+
315
+ if (event.target) {
316
+ span.setAttribute('gesture.target', this._truncateText(event.target, 100))
317
+ }
318
+
319
+ // Enrich with target info if provided
320
+ const info = event.targetInfo
321
+ if (info) {
322
+ if (info.label) {
323
+ const truncatedLabel = this._truncateText(String(info.label), 100)
324
+ span.setAttribute('gesture.target.label', truncatedLabel)
325
+ }
326
+ if (info.role) {
327
+ span.setAttribute('gesture.target.role', String(info.role))
328
+ }
329
+ if (info.testId) {
330
+ span.setAttribute('gesture.target.test_id', String(info.testId))
331
+ }
332
+ if (info.text) {
333
+ const truncatedText = this._truncateText(String(info.text), 200)
334
+ span.setAttribute('gesture.target.text', truncatedText)
335
+ }
336
+ }
337
+
338
+ if (event.metadata) {
339
+ Object.entries(event.metadata).forEach(([key, value]) => {
340
+ span.setAttribute(`gesture.metadata.${key}`, String(value))
341
+ })
342
+ }
343
+
344
+ span.setStatus({ code: SpanStatusCode.OK })
345
+ span.end()
346
+ logger.debug('GestureRecorder', 'OTEL span created and ended successfully')
347
+ } catch (error) {
348
+ logger.error('GestureRecorder', 'Failed to record OpenTelemetry span for native gesture', error)
349
+ }
350
+ }
351
+
352
+ // Public methods for manual event recording (same as before)
353
+ recordTap(x: number, y: number, target?: string, pressure?: number, timestamp?: number): void {
354
+ const event: GestureEvent = {
355
+ type: 'tap',
356
+ timestamp: timestamp || Date.now(),
357
+ coordinates: { x, y },
358
+ target,
359
+ metadata: {
360
+ pressure: pressure || 1.0,
361
+ screenWidth: this.screenDimensions?.width,
362
+ screenHeight: this.screenDimensions?.height,
363
+ },
364
+ }
365
+
366
+ this._recordEvent(event)
367
+ }
368
+
369
+ recordSwipe(direction: string, target?: string, velocity?: number, distance?: number): void {
370
+ const event: GestureEvent = {
371
+ type: 'swipe',
372
+ timestamp: Date.now(),
373
+ target,
374
+ metadata: {
375
+ direction,
376
+ velocity: velocity || 0,
377
+ distance: distance || 0,
378
+ screenWidth: this.screenDimensions?.width,
379
+ screenHeight: this.screenDimensions?.height,
380
+ },
381
+ }
382
+
383
+ this._recordEvent(event)
384
+ }
385
+
386
+ recordPinch(scale: number, target?: string, velocity?: number): void {
387
+ const event: GestureEvent = {
388
+ type: 'pinch',
389
+ timestamp: Date.now(),
390
+ target,
391
+ metadata: {
392
+ scale,
393
+ velocity: velocity || 0,
394
+ screenWidth: this.screenDimensions?.width,
395
+ screenHeight: this.screenDimensions?.height,
396
+ },
397
+ }
398
+
399
+ this._recordEvent(event)
400
+ }
401
+
402
+ recordPan(deltaX: number, deltaY: number, target?: string, velocity?: number): void {
403
+ const event: GestureEvent = {
404
+ type: 'pan',
405
+ timestamp: Date.now(),
406
+ target,
407
+ metadata: {
408
+ deltaX,
409
+ deltaY,
410
+ velocity: velocity || 0,
411
+ screenWidth: this.screenDimensions?.width,
412
+ screenHeight: this.screenDimensions?.height,
413
+ },
414
+ }
415
+
416
+ this._recordEvent(event)
417
+ }
418
+
419
+ recordLongPress(duration: number, target?: string, pressure?: number): void {
420
+ const event: GestureEvent = {
421
+ type: 'longPress',
422
+ timestamp: Date.now(),
423
+ target,
424
+ metadata: {
425
+ duration,
426
+ pressure: pressure || 1.0,
427
+ screenWidth: this.screenDimensions?.width,
428
+ screenHeight: this.screenDimensions?.height,
429
+ },
430
+ }
431
+
432
+ this._recordEvent(event)
433
+ }
434
+
435
+ recordDoubleTap(x: number, y: number, target?: string): void {
436
+ const event: GestureEvent = {
437
+ type: 'doubleTap',
438
+ timestamp: Date.now(),
439
+ coordinates: { x, y },
440
+ target,
441
+ metadata: {
442
+ screenWidth: this.screenDimensions?.width,
443
+ screenHeight: this.screenDimensions?.height,
444
+ },
445
+ }
446
+
447
+ this._recordEvent(event)
448
+ }
449
+
450
+ recordRotate(rotation: number, target?: string, velocity?: number): void {
451
+ const event: GestureEvent = {
452
+ type: 'rotate',
453
+ timestamp: Date.now(),
454
+ target,
455
+ metadata: {
456
+ rotation,
457
+ velocity: velocity || 0,
458
+ screenWidth: this.screenDimensions?.width,
459
+ screenHeight: this.screenDimensions?.height,
460
+ },
461
+ }
462
+
463
+ this._recordEvent(event)
464
+ }
465
+
466
+ recordFling(direction: string, velocity: number, target?: string): void {
467
+ const event: GestureEvent = {
468
+ type: 'fling',
469
+ timestamp: Date.now(),
470
+ target,
471
+ metadata: {
472
+ direction,
473
+ velocity,
474
+ screenWidth: this.screenDimensions?.width,
475
+ screenHeight: this.screenDimensions?.height,
476
+ },
477
+ }
478
+
479
+ this._recordEvent(event)
480
+ }
481
+
482
+ recordMultiTouch(touchCount: number, target?: string): void {
483
+ const event: GestureEvent = {
484
+ type: 'multiTouch',
485
+ timestamp: Date.now(),
486
+ target,
487
+ metadata: {
488
+ touchCount,
489
+ screenWidth: this.screenDimensions?.width,
490
+ screenHeight: this.screenDimensions?.height,
491
+ },
492
+ }
493
+
494
+ this._recordEvent(event)
495
+ }
496
+
497
+ recordScroll(direction: string, distance: number, velocity: number, target?: string): void {
498
+ const event: GestureEvent = {
499
+ type: 'scroll',
500
+ timestamp: Date.now(),
501
+ target,
502
+ metadata: {
503
+ direction,
504
+ distance,
505
+ velocity,
506
+ screenWidth: this.screenDimensions?.width,
507
+ screenHeight: this.screenDimensions?.height,
508
+ },
509
+ }
510
+
511
+ this._recordEvent(event)
512
+ }
513
+
514
+ recordZoom(scale: number, target?: string, velocity?: number): void {
515
+ const event: GestureEvent = {
516
+ type: 'zoom',
517
+ timestamp: Date.now(),
518
+ target,
519
+ metadata: {
520
+ scale,
521
+ velocity: velocity || 0,
522
+ screenWidth: this.screenDimensions?.width,
523
+ screenHeight: this.screenDimensions?.height,
524
+ },
525
+ }
526
+
527
+ this._recordEvent(event)
528
+ }
529
+
530
+ // Touch event methods (same as before)
531
+ recordTouchStart(x: number, y: number, target?: string, pressure?: number): void {
532
+ // Throttle touch events to prevent spam
533
+ const now = Date.now()
534
+ if (now - this.lastTouchTime < this.touchThrottleMs) {
535
+ logger.debug('GestureRecorder', `Touch start throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs}ms)`)
536
+ return
537
+ }
538
+ this.lastTouchTime = now
539
+
540
+ logger.debug('GestureRecorder', 'Touch start recorded', { x, y, target, pressure })
541
+ this._createMouseInteractionEvent(x, y, MouseInteractions.TouchStart, now)
542
+ }
543
+
544
+ recordTouchMove(x: number, y: number, target?: string, pressure?: number): void {
545
+ // Throttle touch move events more aggressively
546
+ const now = Date.now()
547
+ if (now - this.lastTouchTime < this.touchThrottleMs * 2) { // 200ms throttle for move events
548
+ logger.debug('GestureRecorder', `Touch move throttled (${now - this.lastTouchTime}ms < ${this.touchThrottleMs * 2}ms)`)
549
+ return
550
+ }
551
+ this.lastTouchTime = now
552
+
553
+ logger.debug('GestureRecorder', 'Touch move recorded', { x, y, target, pressure })
554
+ this._createMouseMoveEvent(x, y, target)
555
+ }
556
+
557
+ recordTouchEnd(x: number, y: number, target?: string, pressure?: number): void {
558
+ const timestamp = Date.now()
559
+
560
+ logger.debug('GestureRecorder', 'Touch end recorded', { x, y, target, pressure, timestamp })
561
+
562
+ this.recordTap(x, y, target, pressure, timestamp)
563
+ this._createMouseInteractionEvent(x, y, MouseInteractions.TouchEnd, timestamp)
564
+
565
+ // Only force screen capture on touch end (not on every touch event)
566
+ this.screenRecorder?.forceCapture(timestamp)
567
+ }
568
+
569
+ recordTouchCancel(x: number, y: number, _target?: string): void {
570
+ this._createMouseInteractionEvent(x, y, MouseInteractions.TouchCancel)
571
+ }
572
+
573
+ setImageNodeId(nodeId: number): void {
574
+ this.imageNodeId = nodeId
575
+ }
576
+
577
+ private _recordEvent(event: GestureEvent): void {
578
+ if (!this.isRecording) return
579
+
580
+ // Throttle gestures to avoid spam
581
+ const now = Date.now()
582
+ if (now - this.lastGestureTime < this.gestureThrottleMs) {
583
+ return
584
+ }
585
+ this.lastGestureTime = now
586
+
587
+ this.events.push(event)
588
+ this._sendEvent(event)
589
+ this._recordOpenTelemetrySpan(event)
590
+ }
591
+
592
+ private _createMouseInteractionEvent(
593
+ x: number,
594
+ y: number,
595
+ interactionType: MouseInteractions,
596
+ timestamp?: number,
597
+ ): void {
598
+ const incrementalSnapshotEvent: eventWithTime = {
599
+ type: EventType.IncrementalSnapshot,
600
+ data: {
601
+ source: IncrementalSource.MouseInteraction,
602
+ type: interactionType,
603
+ id: this.imageNodeId, // Reference to the image node
604
+ x: x, // Preserve decimal precision like web rrweb
605
+ y: y, // Preserve decimal precision like web rrweb
606
+ pointerType: 2, // 2 = Touch for React Native (0=Mouse, 1=Pen, 2=Touch)
607
+ },
608
+ timestamp: timestamp || Date.now(),
609
+ }
610
+
611
+ this.recordEvent(incrementalSnapshotEvent)
612
+ }
613
+
614
+ private _createMouseMoveEvent(x: number, y: number, _target?: string): void {
615
+ const incrementalSnapshotEvent: eventWithTime = {
616
+ type: EventType.IncrementalSnapshot,
617
+ data: {
618
+ source: IncrementalSource.TouchMove, // Use MouseMove instead of MouseInteraction
619
+ positions: [
620
+ {
621
+ x: x, // Preserve decimal precision like web rrweb
622
+ y: y, // Preserve decimal precision like web rrweb
623
+ id: this.imageNodeId, // Reference to the image node
624
+ timeOffset: 0, // No time offset for single position
625
+ },
626
+ ],
627
+ },
628
+ timestamp: Date.now(),
629
+ }
630
+
631
+ this.recordEvent(incrementalSnapshotEvent)
632
+ }
633
+
634
+ recordEvent(event: any): void {
635
+ if (this.eventRecorder) {
636
+ this.eventRecorder.recordEvent(event)
637
+ }
638
+ }
639
+
640
+ // Get recorded events
641
+ getEvents(): GestureEvent[] {
642
+ return [...this.events]
643
+ }
644
+
645
+ // Clear events
646
+ clearEvents(): void {
647
+ this.events = []
648
+ }
649
+
650
+ // Get event statistics
651
+ getEventStats(): Record<string, number> {
652
+ const stats: Record<string, number> = {}
653
+ this.events.forEach(event => {
654
+ stats[event.type] = (stats[event.type] || 0) + 1
655
+ })
656
+ return stats
657
+ }
658
+
659
+ // Set gesture throttle
660
+ setGestureThrottle(throttleMs: number): void {
661
+ this.gestureThrottleMs = throttleMs
662
+ }
663
+
664
+ // Get recording status
665
+ isRecordingEnabled(): boolean {
666
+ return this.isRecording
667
+ }
668
+
669
+ /**
670
+ * Truncate text to prevent large span attributes
671
+ * @param text - Text to truncate
672
+ * @param maxLength - Maximum length (default: 100)
673
+ * @returns Truncated text with ellipsis if needed
674
+ */
675
+ private _truncateText(text: string, maxLength: number = 100): string {
676
+ if (!text || text.length <= maxLength) {
677
+ return text
678
+ }
679
+ return text.substring(0, maxLength - 3) + '...'
680
+ }
681
+ }