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

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.
@@ -0,0 +1,91 @@
1
+ # React Native Setup Guide
2
+
3
+ This package provides native session recording capabilities for React Native applications with automatic masking of sensitive UI elements.
4
+
5
+ ## Installation
6
+
7
+ ### For React Native CLI projects:
8
+
9
+ ```bash
10
+ npm install @multiplayer-app/session-recorder-react-native
11
+ ```
12
+
13
+ ### For Expo projects:
14
+
15
+ ```bash
16
+ npx expo install @multiplayer-app/session-recorder-react-native
17
+ ```
18
+
19
+ ## Platform-specific Setup
20
+
21
+ ### Android
22
+
23
+ The Android native module is automatically linked. No additional setup required.
24
+
25
+ ### iOS
26
+
27
+ The iOS native module uses CocoaPods for dependency management. Run:
28
+
29
+ ```bash
30
+ cd ios && pod install
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```typescript
36
+ import { SessionRecorder } from '@multiplayer-app/session-recorder-react-native'
37
+
38
+ // Initialize the session recorder
39
+ const sessionRecorder = new SessionRecorder({
40
+ // Configuration options
41
+ })
42
+
43
+ // Start recording
44
+ await sessionRecorder.start()
45
+
46
+ // Stop recording
47
+ await sessionRecorder.stop()
48
+ ```
49
+
50
+ ## Native Module Structure
51
+
52
+ ### Android
53
+
54
+ - `SessionRecorderNativeModule.kt` - Main native module implementation
55
+ - `SessionRecorderNativePackage.kt` - React Native package registration
56
+ - `SessionRecorderNativeConfig.kt` - Configuration class
57
+ - `ViewUtils.kt` - View utility functions
58
+ - `TargetInfo.kt` - Data model for target information
59
+
60
+ ### iOS
61
+
62
+ - `SessionRecorderNative.swift` - Main native module implementation
63
+ - `GestureTargetFinder.swift` - Gesture target detection utilities
64
+ - `SessionRecorderNative.m` - Objective-C bridge
65
+ - `SessionRecorderNative.podspec` - CocoaPods specification
66
+
67
+ ## Features
68
+
69
+ - **Screen Capture**: Capture screenshots with automatic masking
70
+ - **Gesture Recording**: Record user interactions (tap, pan, long press, pinch)
71
+ - **Sensitive Content Masking**: Automatically mask text inputs, images, and other sensitive elements
72
+ - **Cross-platform**: Works on both Android and iOS
73
+ - **Expo Compatible**: Supports Expo managed workflow
74
+
75
+ ## Troubleshooting
76
+
77
+ ### Android Build Issues
78
+
79
+ - Ensure Android SDK is properly configured
80
+ - Check that the package is properly linked in `MainApplication.java`
81
+
82
+ ### iOS Build Issues
83
+
84
+ - Run `pod install` in the iOS directory
85
+ - Ensure Xcode is properly configured
86
+ - Check that the podspec is correctly configured
87
+
88
+ ### Expo Issues
89
+
90
+ - Use `npx expo install` instead of `npm install`
91
+ - Ensure you're using a compatible Expo SDK version
@@ -94,4 +94,7 @@ dependencies {
94
94
  //noinspection GradleDynamicVersion
95
95
  implementation "com.facebook.react:react-native:+"
96
96
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
97
+
98
+ // TurboModule support
99
+ implementation "com.facebook.react:react-native-codegen:+"
97
100
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "1.0.1-beta.2";
1
+ export declare const version = "1.0.1-beta.3";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.version=void 0;var version=exports.version="1.0.1-beta.2";
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.version=void 0;var version=exports.version="1.0.1-beta.3";
@@ -0,0 +1,50 @@
1
+ import UIKit
2
+
3
+ struct GestureTargetInfo {
4
+ let identifier: String
5
+ let label: String?
6
+ let role: String?
7
+ let testId: String?
8
+ let text: String?
9
+ }
10
+
11
+ enum GestureTargetFinder {
12
+ static func findTargetView(at point: CGPoint, in view: UIView) -> GestureTargetInfo {
13
+ let targetView = view.hitTest(point, with: nil)
14
+
15
+ guard let target = targetView else {
16
+ return GestureTargetInfo(identifier: "unknown", label: nil, role: nil, testId: nil, text: nil)
17
+ }
18
+
19
+ let identifier = target.accessibilityIdentifier ?? target.accessibilityLabel ?? "view-\(target.hash)"
20
+ let label = target.accessibilityLabel
21
+ let role = roleFromAccessibilityTraits(target.accessibilityTraits)
22
+ let testId = target.accessibilityIdentifier
23
+
24
+ var text: String?
25
+ if let labelView = target as? UILabel {
26
+ text = labelView.text
27
+ } else if let button = target as? UIButton {
28
+ text = button.titleLabel?.text
29
+ } else if let textField = target as? UITextField {
30
+ text = textField.text ?? textField.placeholder
31
+ } else if let textView = target as? UITextView {
32
+ text = textView.text
33
+ }
34
+
35
+ return GestureTargetInfo(identifier: identifier, label: label, role: role, testId: testId, text: text)
36
+ }
37
+
38
+ static func roleFromAccessibilityTraits(_ traits: UIAccessibilityTraits) -> String? {
39
+ if traits.contains(.button) { return "button" }
40
+ if traits.contains(.link) { return "link" }
41
+ if traits.contains(.image) { return "image" }
42
+ if traits.contains(.staticText) { return "text" }
43
+ if traits.contains(.header) { return "header" }
44
+ if traits.contains(.searchField) { return "search" }
45
+ if traits.contains(.keyboardKey) { return "key" }
46
+ if traits.contains(.adjustable) { return "adjustable" }
47
+ if traits.contains(.tabBar) { return "tabbar" }
48
+ return nil
49
+ }
50
+ }
@@ -3,7 +3,7 @@ import React
3
3
  import WebKit
4
4
 
5
5
  @objc(SessionRecorderNative)
6
- class SessionRecorderNative: RCTEventEmitter {
6
+ class SessionRecorderNative: RCTEventEmitter, UIGestureRecognizerDelegate {
7
7
 
8
8
  // Configuration options
9
9
  private var maskTextInputs: Bool = true
@@ -755,6 +755,15 @@ class SessionRecorderNative: RCTEventEmitter {
755
755
  self.sendEvent(withName: "onGestureDetected", body: gestureEvent)
756
756
  if let cb = gestureCallback { cb([gestureEvent]) }
757
757
  }
758
+
759
+ // MARK: - UIGestureRecognizerDelegate
760
+ func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
761
+ return true
762
+ }
763
+
764
+ func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
765
+ return true
766
+ }
758
767
  }
759
768
 
760
769
  private enum MaskingType {
@@ -0,0 +1,55 @@
1
+ import Foundation
2
+ import React
3
+
4
+ @objc(SessionRecorderNativeSpec)
5
+ class SessionRecorderNativeSpec: NSObject, RCTBridgeModule {
6
+
7
+ static func moduleName() -> String! {
8
+ return "SessionRecorderNative"
9
+ }
10
+
11
+ static func requiresMainQueueSetup() -> Bool {
12
+ return true
13
+ }
14
+
15
+ @objc func captureAndMask(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
16
+ // Implementation will be provided by the actual module
17
+ reject("NOT_IMPLEMENTED", "Method not implemented", nil)
18
+ }
19
+
20
+ @objc func captureAndMaskWithOptions(_ options: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
21
+ // Implementation will be provided by the actual module
22
+ reject("NOT_IMPLEMENTED", "Method not implemented", nil)
23
+ }
24
+
25
+ @objc func startGestureRecording(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
26
+ // Implementation will be provided by the actual module
27
+ reject("NOT_IMPLEMENTED", "Method not implemented", nil)
28
+ }
29
+
30
+ @objc func stopGestureRecording(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
31
+ // Implementation will be provided by the actual module
32
+ reject("NOT_IMPLEMENTED", "Method not implemented", nil)
33
+ }
34
+
35
+ @objc func isGestureRecordingActive(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
36
+ // Implementation will be provided by the actual module
37
+ reject("NOT_IMPLEMENTED", "Method not implemented", nil)
38
+ }
39
+
40
+ @objc func setGestureCallback(_ callback: @escaping RCTResponseSenderBlock) {
41
+ // Implementation will be provided by the actual module
42
+ }
43
+
44
+ @objc func recordGesture(_ gestureType: String, x: NSNumber, y: NSNumber, target: String?, metadata: NSDictionary?) {
45
+ // Implementation will be provided by the actual module
46
+ }
47
+
48
+ @objc func addListener(_ eventName: String) {
49
+ // Required for RN event emitter contracts
50
+ }
51
+
52
+ @objc func removeListeners(_ count: Int) {
53
+ // Required for RN event emitter contracts
54
+ }
55
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplayer-app/session-recorder-react-native",
3
- "version": "1.0.1-beta.2",
3
+ "version": "1.0.1-beta.3",
4
4
  "description": "Multiplayer Fullstack Session Recorder for React Native",
5
5
  "author": {
6
6
  "name": "Multiplayer Software, Inc.",
@@ -35,7 +35,10 @@
35
35
  "otlp",
36
36
  "fullstack session recorder",
37
37
  "react-native",
38
- "expo"
38
+ "expo",
39
+ "native-module",
40
+ "screen-capture",
41
+ "gesture-recording"
39
42
  ],
40
43
  "scripts": {
41
44
  "clean": "rimraf dist",
@@ -93,5 +96,14 @@
93
96
  "expo-constants": {
94
97
  "optional": true
95
98
  }
99
+ },
100
+ "react-native": {
101
+ "android": {
102
+ "sourceDir": "./android",
103
+ "packageImportPath": "import com.multiplayer.sessionrecordernative.SessionRecorderNativePackage;"
104
+ },
105
+ "ios": {
106
+ "project": "./ios/SessionRecorderNative.xcodeproj"
107
+ }
96
108
  }
97
109
  }
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ android: {
5
+ sourceDir: '../android',
6
+ packageImportPath: 'import com.multiplayer.sessionrecordernative.SessionRecorderNativePackage;'
7
+ },
8
+ ios: {
9
+ project: './ios/SessionRecorderNative.xcodeproj'
10
+ }
11
+ }
12
+ }
13
+ }