@multiplayer-app/session-recorder-react-native 0.0.1-beta.3 → 0.0.1-beta.5
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/android/build.gradle +32 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/multiplayer/sessionrecorder/ScreenMaskingModule.kt +202 -0
- package/android/src/main/java/com/multiplayer/sessionrecorder/ScreenMaskingPackage.kt +16 -0
- package/android/src/main/java/com/multiplayer/sessionrecorder/SessionRecorderModule.kt +202 -0
- package/android/src/main/java/com/multiplayer/sessionrecorder/SessionRecorderPackage.kt +16 -0
- package/dist/components/MaskableComponent.d.ts +22 -0
- package/dist/components/MaskableComponent.js +1 -0
- package/dist/components/MaskableComponent.js.map +1 -0
- package/dist/components/MaskableTextInput.d.ts +14 -0
- package/dist/components/MaskableTextInput.js +1 -0
- package/dist/components/MaskableTextInput.js.map +1 -0
- package/dist/components/SessionRecorderWidget/FinalPopover.d.ts +11 -0
- package/dist/components/SessionRecorderWidget/FinalPopover.js +1 -0
- package/dist/components/SessionRecorderWidget/FinalPopover.js.map +1 -0
- package/dist/components/SessionRecorderWidget/FloatingButton.d.ts +8 -0
- package/dist/components/SessionRecorderWidget/FloatingButton.js +1 -0
- package/dist/components/SessionRecorderWidget/FloatingButton.js.map +1 -0
- package/dist/components/SessionRecorderWidget/InitialPopover.d.ts +13 -0
- package/dist/components/SessionRecorderWidget/InitialPopover.js +1 -0
- package/dist/components/SessionRecorderWidget/InitialPopover.js.map +1 -0
- package/dist/components/SessionRecorderWidget/ModalContainer.d.ts +8 -0
- package/dist/components/SessionRecorderWidget/ModalContainer.js +1 -0
- package/dist/components/SessionRecorderWidget/ModalContainer.js.map +1 -0
- package/dist/components/SessionRecorderWidget/ModalHeader.d.ts +6 -0
- package/dist/components/SessionRecorderWidget/ModalHeader.js +1 -0
- package/dist/components/SessionRecorderWidget/ModalHeader.js.map +1 -0
- package/dist/components/SessionRecorderWidget/SessionRecorderWidget.d.ts +5 -0
- package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js +1 -0
- package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -0
- package/dist/components/SessionRecorderWidget/icons.d.ts +11 -0
- package/dist/components/SessionRecorderWidget/icons.js +1 -0
- package/dist/components/SessionRecorderWidget/icons.js.map +1 -0
- package/dist/components/SessionRecorderWidget/index.d.ts +2 -0
- package/dist/components/SessionRecorderWidget/index.js +1 -0
- package/dist/components/SessionRecorderWidget/index.js.map +1 -0
- package/dist/components/SessionRecorderWidget/styles.d.ts +145 -0
- package/dist/components/SessionRecorderWidget/styles.js +1 -0
- package/dist/components/SessionRecorderWidget/styles.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/config/defaults.js +1 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/masking.js +1 -1
- package/dist/config/masking.js.map +1 -1
- package/dist/context/SessionRecorderContext.d.ts +5 -3
- package/dist/context/SessionRecorderContext.js +1 -1
- package/dist/context/SessionRecorderContext.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/native/ScreenMasking.d.ts +21 -0
- package/dist/native/ScreenMasking.js +1 -0
- package/dist/native/ScreenMasking.js.map +1 -0
- package/dist/native/SessionRecorderNative.d.ts +21 -0
- package/dist/native/SessionRecorderNative.js +1 -0
- package/dist/native/SessionRecorderNative.js.map +1 -0
- package/dist/patch/xhr.d.ts +1 -1
- package/dist/patch/xhr.js +1 -1
- package/dist/patch/xhr.js.map +1 -1
- package/dist/recorder/screenRecorder.d.ts +1 -0
- package/dist/recorder/screenRecorder.js +1 -1
- package/dist/recorder/screenRecorder.js.map +1 -1
- package/dist/recorder/screenshotManager.d.ts +10 -0
- package/dist/recorder/screenshotManager.js +1 -0
- package/dist/recorder/screenshotManager.js.map +1 -0
- package/dist/services/screenMaskingService.d.ts +39 -0
- package/dist/services/screenMaskingService.js +1 -0
- package/dist/services/screenMaskingService.js.map +1 -0
- package/dist/services/storage.service.d.ts +18 -2
- package/dist/services/storage.service.js +1 -1
- package/dist/services/storage.service.js.map +1 -1
- package/dist/session-recorder.d.ts +2 -1
- package/dist/session-recorder.js +1 -1
- package/dist/session-recorder.js.map +1 -1
- package/dist/types/session-recorder.d.ts +6 -0
- package/dist/types/session-recorder.js.map +1 -1
- package/dist/utils/componentRegistry.d.ts +64 -0
- package/dist/utils/componentRegistry.js +1 -0
- package/dist/utils/componentRegistry.js.map +1 -0
- package/dist/utils/platform.d.ts +3 -0
- package/dist/utils/reactNativeHierarchyExtractor.d.ts +38 -0
- package/dist/utils/reactNativeHierarchyExtractor.js +1 -0
- package/dist/utils/reactNativeHierarchyExtractor.js.map +1 -0
- package/dist/utils/screenshotMasker.d.ts +96 -0
- package/dist/utils/screenshotMasker.js +1 -0
- package/dist/utils/screenshotMasker.js.map +1 -0
- package/dist/utils/viewHierarchyTracker.d.ts +89 -0
- package/dist/utils/viewHierarchyTracker.js +1 -0
- package/dist/utils/viewHierarchyTracker.js.map +1 -0
- package/ios/ScreenMasking.m +12 -0
- package/ios/ScreenMasking.podspec +21 -0
- package/ios/ScreenMasking.swift +205 -0
- package/ios/SessionRecorder.m +12 -0
- package/ios/SessionRecorder.podspec +21 -0
- package/ios/SessionRecorder.swift +205 -0
- package/package.json +12 -2
- package/react-native.config.js +15 -0
- package/src/components/SessionRecorderWidget/FinalPopover.tsx +62 -0
- package/src/components/SessionRecorderWidget/FloatingButton.tsx +136 -0
- package/src/components/SessionRecorderWidget/InitialPopover.tsx +89 -0
- package/src/components/SessionRecorderWidget/ModalContainer.tsx +128 -0
- package/src/components/SessionRecorderWidget/ModalHeader.tsx +24 -0
- package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +109 -0
- package/src/components/SessionRecorderWidget/icons.tsx +52 -0
- package/src/components/SessionRecorderWidget/index.ts +3 -0
- package/src/components/SessionRecorderWidget/styles.ts +150 -0
- package/src/components/index.ts +3 -1
- package/src/config/defaults.ts +1 -0
- package/src/config/masking.ts +1 -0
- package/src/context/SessionRecorderContext.tsx +12 -34
- package/src/index.ts +1 -9
- package/src/native/ScreenMasking.ts +34 -0
- package/src/native/SessionRecorderNative.ts +34 -0
- package/src/patch/xhr.ts +7 -7
- package/src/recorder/screenRecorder.ts +31 -2
- package/src/services/screenMaskingService.ts +114 -0
- package/src/services/storage.service.ts +45 -4
- package/src/session-recorder.ts +9 -3
- package/src/types/session-recorder.ts +7 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
2
|
+
|
|
3
|
+
def safeExtGet(prop, fallback) {
|
|
4
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
android {
|
|
8
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 33)
|
|
9
|
+
|
|
10
|
+
defaultConfig {
|
|
11
|
+
minSdkVersion safeExtGet('minSdkVersion', 21)
|
|
12
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 33)
|
|
13
|
+
versionCode 1
|
|
14
|
+
versionName "1.0"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
buildTypes {
|
|
18
|
+
release {
|
|
19
|
+
minifyEnabled false
|
|
20
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
compileOptions {
|
|
25
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
26
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
dependencies {
|
|
31
|
+
implementation 'com.facebook.react:react-native:+'
|
|
32
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
package com.multiplayer.sessionrecorder
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.graphics.*
|
|
5
|
+
import android.util.Base64
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.widget.EditText
|
|
8
|
+
import android.widget.TextView
|
|
9
|
+
import com.facebook.react.bridge.*
|
|
10
|
+
import java.io.ByteArrayOutputStream
|
|
11
|
+
|
|
12
|
+
class SessionRecorderModule(reactContext: ReactApplicationContext) :
|
|
13
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
14
|
+
|
|
15
|
+
override fun getName() = "SessionRecorder"
|
|
16
|
+
|
|
17
|
+
@ReactMethod
|
|
18
|
+
fun captureAndMask(promise: Promise) {
|
|
19
|
+
val activity = currentActivity ?: return promise.reject("NO_ACTIVITY", "No activity found")
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
val maskedImage = captureAndMaskScreen(activity, null)
|
|
23
|
+
promise.resolve(maskedImage)
|
|
24
|
+
} catch (e: Exception) {
|
|
25
|
+
promise.reject("CAPTURE_FAILED", "Failed to capture and mask screen", e)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactMethod
|
|
30
|
+
fun captureAndMaskWithOptions(options: ReadableMap, promise: Promise) {
|
|
31
|
+
val activity = currentActivity ?: return promise.reject("NO_ACTIVITY", "No activity found")
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
val maskedImage = captureAndMaskScreen(activity, options)
|
|
35
|
+
promise.resolve(maskedImage)
|
|
36
|
+
} catch (e: Exception) {
|
|
37
|
+
promise.reject("CAPTURE_FAILED", "Failed to capture and mask screen", e)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private fun captureAndMaskScreen(activity: Activity, options: ReadableMap?): String {
|
|
42
|
+
val rootView = activity.window.decorView.rootView
|
|
43
|
+
|
|
44
|
+
// Enable drawing cache
|
|
45
|
+
rootView.isDrawingCacheEnabled = true
|
|
46
|
+
rootView.buildDrawingCache()
|
|
47
|
+
|
|
48
|
+
val bitmap = Bitmap.createBitmap(rootView.drawingCache)
|
|
49
|
+
rootView.isDrawingCacheEnabled = false
|
|
50
|
+
|
|
51
|
+
// Apply masking
|
|
52
|
+
val maskedBitmap = applyMasking(bitmap, rootView, options)
|
|
53
|
+
|
|
54
|
+
// Convert to base64
|
|
55
|
+
val output = ByteArrayOutputStream()
|
|
56
|
+
maskedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, output)
|
|
57
|
+
val base64 = Base64.encodeToString(output.toByteArray(), Base64.DEFAULT)
|
|
58
|
+
|
|
59
|
+
return base64
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun applyMasking(bitmap: Bitmap, rootView: View, options: ReadableMap?): Bitmap {
|
|
63
|
+
val maskedBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
|
|
64
|
+
val canvas = Canvas(maskedBitmap)
|
|
65
|
+
|
|
66
|
+
// Find sensitive elements
|
|
67
|
+
val sensitiveElements = findSensitiveElements(rootView)
|
|
68
|
+
|
|
69
|
+
for (element in sensitiveElements) {
|
|
70
|
+
val location = IntArray(2)
|
|
71
|
+
element.getLocationOnScreen(location)
|
|
72
|
+
|
|
73
|
+
val frame = Rect(
|
|
74
|
+
location[0],
|
|
75
|
+
location[1],
|
|
76
|
+
location[0] + element.width,
|
|
77
|
+
location[1] + element.height
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
val maskingType = getMaskingType(element)
|
|
81
|
+
|
|
82
|
+
when (maskingType) {
|
|
83
|
+
MaskingType.BLUR -> applyBlurMask(canvas, frame)
|
|
84
|
+
MaskingType.RECTANGLE -> applyRectangleMask(canvas, frame)
|
|
85
|
+
MaskingType.PIXELATE -> applyPixelateMask(canvas, frame)
|
|
86
|
+
MaskingType.NONE -> { /* No masking */ }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return maskedBitmap
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private fun findSensitiveElements(view: View): List<View> {
|
|
94
|
+
val sensitiveElements = mutableListOf<View>()
|
|
95
|
+
|
|
96
|
+
fun traverseView(currentView: View) {
|
|
97
|
+
if (shouldMaskView(currentView)) {
|
|
98
|
+
sensitiveElements.add(currentView)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (currentView is ViewGroup) {
|
|
102
|
+
for (i in 0 until currentView.childCount) {
|
|
103
|
+
traverseView(currentView.getChildAt(i))
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
traverseView(view)
|
|
109
|
+
return sensitiveElements
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun shouldMaskView(view: View): Boolean {
|
|
113
|
+
// Check for EditText - mask all text fields when inputMasking is enabled
|
|
114
|
+
if (view is EditText) {
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check for TextView - mask all text views when inputMasking is enabled
|
|
119
|
+
if (view is TextView) {
|
|
120
|
+
return true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private fun getMaskingType(view: View): MaskingType {
|
|
127
|
+
// Default masking type for all text inputs
|
|
128
|
+
return MaskingType.RECTANGLE
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private fun applyBlurMask(canvas: Canvas, frame: Rect) {
|
|
132
|
+
val paint = Paint().apply {
|
|
133
|
+
color = Color.BLACK
|
|
134
|
+
alpha = 200 // Semi-transparent
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
canvas.drawRect(frame, paint)
|
|
138
|
+
|
|
139
|
+
// Add some noise to make it look blurred
|
|
140
|
+
paint.color = Color.WHITE
|
|
141
|
+
paint.alpha = 80
|
|
142
|
+
|
|
143
|
+
for (i in 0..20) {
|
|
144
|
+
val randomX = frame.left + (Math.random() * frame.width()).toFloat()
|
|
145
|
+
val randomY = frame.top + (Math.random() * frame.height()).toFloat()
|
|
146
|
+
val randomSize = (Math.random() * 6 + 2).toFloat()
|
|
147
|
+
canvas.drawCircle(randomX, randomY, randomSize, paint)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private fun applyRectangleMask(canvas: Canvas, frame: Rect) {
|
|
152
|
+
val paint = Paint().apply {
|
|
153
|
+
color = Color.GRAY
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
canvas.drawRect(frame, paint)
|
|
157
|
+
|
|
158
|
+
// Add some text-like pattern
|
|
159
|
+
paint.color = Color.DKGRAY
|
|
160
|
+
val lineHeight = 4f
|
|
161
|
+
val spacing = 8f
|
|
162
|
+
|
|
163
|
+
var y = frame.top + spacing
|
|
164
|
+
while (y < frame.bottom - spacing) {
|
|
165
|
+
val lineWidth = (Math.random() * frame.width() * 0.5 + frame.width() * 0.3).toFloat()
|
|
166
|
+
val x = frame.left + (Math.random() * (frame.width() - lineWidth)).toFloat()
|
|
167
|
+
canvas.drawRect(x, y, x + lineWidth, y + lineHeight, paint)
|
|
168
|
+
y += lineHeight + spacing
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun applyPixelateMask(canvas: Canvas, frame: Rect) {
|
|
173
|
+
val pixelSize = 8f
|
|
174
|
+
val pixelCountX = (frame.width() / pixelSize).toInt()
|
|
175
|
+
val pixelCountY = (frame.height() / pixelSize).toInt()
|
|
176
|
+
|
|
177
|
+
val paint = Paint()
|
|
178
|
+
|
|
179
|
+
for (x in 0 until pixelCountX) {
|
|
180
|
+
for (y in 0 until pixelCountY) {
|
|
181
|
+
val pixelFrame = RectF(
|
|
182
|
+
frame.left + x * pixelSize,
|
|
183
|
+
frame.top + y * pixelSize,
|
|
184
|
+
frame.left + (x + 1) * pixelSize,
|
|
185
|
+
frame.top + (y + 1) * pixelSize
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
// Use a random color for each pixel
|
|
189
|
+
paint.color = Color.rgb(
|
|
190
|
+
(Math.random() * 255).toInt(),
|
|
191
|
+
(Math.random() * 255).toInt(),
|
|
192
|
+
(Math.random() * 255).toInt()
|
|
193
|
+
)
|
|
194
|
+
canvas.drawRect(pixelFrame, paint)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private enum class MaskingType {
|
|
200
|
+
BLUR, RECTANGLE, PIXELATE, NONE
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.multiplayer.sessionrecorder
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class SessionRecorderPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(SessionRecorderModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
+
return emptyList()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
package com.multiplayer.sessionrecorder
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.graphics.*
|
|
5
|
+
import android.util.Base64
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.widget.EditText
|
|
8
|
+
import android.widget.TextView
|
|
9
|
+
import com.facebook.react.bridge.*
|
|
10
|
+
import java.io.ByteArrayOutputStream
|
|
11
|
+
|
|
12
|
+
class SessionRecorderModule(reactContext: ReactApplicationContext) :
|
|
13
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
14
|
+
|
|
15
|
+
override fun getName() = "SessionRecorder"
|
|
16
|
+
|
|
17
|
+
@ReactMethod
|
|
18
|
+
fun captureAndMask(promise: Promise) {
|
|
19
|
+
val activity = currentActivity ?: return promise.reject("NO_ACTIVITY", "No activity found")
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
val maskedImage = captureAndMaskScreen(activity, null)
|
|
23
|
+
promise.resolve(maskedImage)
|
|
24
|
+
} catch (e: Exception) {
|
|
25
|
+
promise.reject("CAPTURE_FAILED", "Failed to capture and mask screen", e)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactMethod
|
|
30
|
+
fun captureAndMaskWithOptions(options: ReadableMap, promise: Promise) {
|
|
31
|
+
val activity = currentActivity ?: return promise.reject("NO_ACTIVITY", "No activity found")
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
val maskedImage = captureAndMaskScreen(activity, options)
|
|
35
|
+
promise.resolve(maskedImage)
|
|
36
|
+
} catch (e: Exception) {
|
|
37
|
+
promise.reject("CAPTURE_FAILED", "Failed to capture and mask screen", e)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private fun captureAndMaskScreen(activity: Activity, options: ReadableMap?): String {
|
|
42
|
+
val rootView = activity.window.decorView.rootView
|
|
43
|
+
|
|
44
|
+
// Enable drawing cache
|
|
45
|
+
rootView.isDrawingCacheEnabled = true
|
|
46
|
+
rootView.buildDrawingCache()
|
|
47
|
+
|
|
48
|
+
val bitmap = Bitmap.createBitmap(rootView.drawingCache)
|
|
49
|
+
rootView.isDrawingCacheEnabled = false
|
|
50
|
+
|
|
51
|
+
// Apply masking
|
|
52
|
+
val maskedBitmap = applyMasking(bitmap, rootView, options)
|
|
53
|
+
|
|
54
|
+
// Convert to base64
|
|
55
|
+
val output = ByteArrayOutputStream()
|
|
56
|
+
maskedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, output)
|
|
57
|
+
val base64 = Base64.encodeToString(output.toByteArray(), Base64.DEFAULT)
|
|
58
|
+
|
|
59
|
+
return base64
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun applyMasking(bitmap: Bitmap, rootView: View, options: ReadableMap?): Bitmap {
|
|
63
|
+
val maskedBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
|
|
64
|
+
val canvas = Canvas(maskedBitmap)
|
|
65
|
+
|
|
66
|
+
// Find sensitive elements
|
|
67
|
+
val sensitiveElements = findSensitiveElements(rootView)
|
|
68
|
+
|
|
69
|
+
for (element in sensitiveElements) {
|
|
70
|
+
val location = IntArray(2)
|
|
71
|
+
element.getLocationOnScreen(location)
|
|
72
|
+
|
|
73
|
+
val frame = Rect(
|
|
74
|
+
location[0],
|
|
75
|
+
location[1],
|
|
76
|
+
location[0] + element.width,
|
|
77
|
+
location[1] + element.height
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
val maskingType = getMaskingType(element)
|
|
81
|
+
|
|
82
|
+
when (maskingType) {
|
|
83
|
+
MaskingType.BLUR -> applyBlurMask(canvas, frame)
|
|
84
|
+
MaskingType.RECTANGLE -> applyRectangleMask(canvas, frame)
|
|
85
|
+
MaskingType.PIXELATE -> applyPixelateMask(canvas, frame)
|
|
86
|
+
MaskingType.NONE -> { /* No masking */ }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return maskedBitmap
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private fun findSensitiveElements(view: View): List<View> {
|
|
94
|
+
val sensitiveElements = mutableListOf<View>()
|
|
95
|
+
|
|
96
|
+
fun traverseView(currentView: View) {
|
|
97
|
+
if (shouldMaskView(currentView)) {
|
|
98
|
+
sensitiveElements.add(currentView)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (currentView is ViewGroup) {
|
|
102
|
+
for (i in 0 until currentView.childCount) {
|
|
103
|
+
traverseView(currentView.getChildAt(i))
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
traverseView(view)
|
|
109
|
+
return sensitiveElements
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun shouldMaskView(view: View): Boolean {
|
|
113
|
+
// Check for EditText - mask all text fields when inputMasking is enabled
|
|
114
|
+
if (view is EditText) {
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check for TextView - mask all text views when inputMasking is enabled
|
|
119
|
+
if (view is TextView) {
|
|
120
|
+
return true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private fun getMaskingType(view: View): MaskingType {
|
|
127
|
+
// Default masking type for all text inputs
|
|
128
|
+
return MaskingType.RECTANGLE
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private fun applyBlurMask(canvas: Canvas, frame: Rect) {
|
|
132
|
+
val paint = Paint().apply {
|
|
133
|
+
color = Color.BLACK
|
|
134
|
+
alpha = 200 // Semi-transparent
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
canvas.drawRect(frame, paint)
|
|
138
|
+
|
|
139
|
+
// Add some noise to make it look blurred
|
|
140
|
+
paint.color = Color.WHITE
|
|
141
|
+
paint.alpha = 80
|
|
142
|
+
|
|
143
|
+
for (i in 0..20) {
|
|
144
|
+
val randomX = frame.left + (Math.random() * frame.width()).toFloat()
|
|
145
|
+
val randomY = frame.top + (Math.random() * frame.height()).toFloat()
|
|
146
|
+
val randomSize = (Math.random() * 6 + 2).toFloat()
|
|
147
|
+
canvas.drawCircle(randomX, randomY, randomSize, paint)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private fun applyRectangleMask(canvas: Canvas, frame: Rect) {
|
|
152
|
+
val paint = Paint().apply {
|
|
153
|
+
color = Color.GRAY
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
canvas.drawRect(frame, paint)
|
|
157
|
+
|
|
158
|
+
// Add some text-like pattern
|
|
159
|
+
paint.color = Color.DKGRAY
|
|
160
|
+
val lineHeight = 4f
|
|
161
|
+
val spacing = 8f
|
|
162
|
+
|
|
163
|
+
var y = frame.top + spacing
|
|
164
|
+
while (y < frame.bottom - spacing) {
|
|
165
|
+
val lineWidth = (Math.random() * frame.width() * 0.5 + frame.width() * 0.3).toFloat()
|
|
166
|
+
val x = frame.left + (Math.random() * (frame.width() - lineWidth)).toFloat()
|
|
167
|
+
canvas.drawRect(x, y, x + lineWidth, y + lineHeight, paint)
|
|
168
|
+
y += lineHeight + spacing
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun applyPixelateMask(canvas: Canvas, frame: Rect) {
|
|
173
|
+
val pixelSize = 8f
|
|
174
|
+
val pixelCountX = (frame.width() / pixelSize).toInt()
|
|
175
|
+
val pixelCountY = (frame.height() / pixelSize).toInt()
|
|
176
|
+
|
|
177
|
+
val paint = Paint()
|
|
178
|
+
|
|
179
|
+
for (x in 0 until pixelCountX) {
|
|
180
|
+
for (y in 0 until pixelCountY) {
|
|
181
|
+
val pixelFrame = RectF(
|
|
182
|
+
frame.left + x * pixelSize,
|
|
183
|
+
frame.top + y * pixelSize,
|
|
184
|
+
frame.left + (x + 1) * pixelSize,
|
|
185
|
+
frame.top + (y + 1) * pixelSize
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
// Use a random color for each pixel
|
|
189
|
+
paint.color = Color.rgb(
|
|
190
|
+
(Math.random() * 255).toInt(),
|
|
191
|
+
(Math.random() * 255).toInt(),
|
|
192
|
+
(Math.random() * 255).toInt()
|
|
193
|
+
)
|
|
194
|
+
canvas.drawRect(pixelFrame, paint)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private enum class MaskingType {
|
|
200
|
+
BLUR, RECTANGLE, PIXELATE, NONE
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.multiplayer.sessionrecorder
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
class SessionRecorderPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(SessionRecorderModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
+
return emptyList()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ViewProps } from 'react-native';
|
|
3
|
+
interface MaskableComponentProps extends ViewProps {
|
|
4
|
+
/** Whether this component should be masked in screenshots */
|
|
5
|
+
maskInScreenshots?: boolean;
|
|
6
|
+
/** Custom mask type for this component */
|
|
7
|
+
maskType?: 'blur' | 'blackout' | 'pixelate';
|
|
8
|
+
/** Element identifier for hierarchy tracking */
|
|
9
|
+
elementId?: string;
|
|
10
|
+
/** Whether this is a sensitive input field */
|
|
11
|
+
isSensitive?: boolean;
|
|
12
|
+
/** Accessibility label for masking detection */
|
|
13
|
+
accessibilityLabel?: string;
|
|
14
|
+
/** Children components */
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A wrapper component that provides masking control for its children
|
|
19
|
+
* Similar to PostHog's ph-no-capture functionality
|
|
20
|
+
*/
|
|
21
|
+
export declare const MaskableComponent: React.FC<MaskableComponentProps>;
|
|
22
|
+
export default MaskableComponent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof=require("@babel/runtime/helpers/typeof");Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=exports.MaskableComponent=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _jsxRuntime=require("react/jsx-runtime");var _excluded=["maskInScreenshots","maskType","elementId","isSensitive","accessibilityLabel","children"];var _this=void 0,_jsxFileName="/Users/gegham/www/multiplayer-debugger-javascript/packages/session-recorder-react-native/dist/components/MaskableComponent.js";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,"default":e};if(null===e||"object"!=_typeof(e)&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t2 in e)"default"!==_t2&&{}.hasOwnProperty.call(e,_t2)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t2))&&(i.get||i.set)?o(f,_t2,i):f[_t2]=e[_t2]);return f;})(e,t);}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var MaskableComponent=exports.MaskableComponent=function MaskableComponent(_ref){var _ref$maskInScreenshot=_ref.maskInScreenshots,maskInScreenshots=_ref$maskInScreenshot===void 0?false:_ref$maskInScreenshot,_ref$maskType=_ref.maskType,maskType=_ref$maskType===void 0?'blackout':_ref$maskType,elementId=_ref.elementId,_ref$isSensitive=_ref.isSensitive,isSensitive=_ref$isSensitive===void 0?false:_ref$isSensitive,accessibilityLabel=_ref.accessibilityLabel,children=_ref.children,viewProps=(0,_objectWithoutProperties2["default"])(_ref,_excluded);var viewRef=(0,_react.useRef)(null);(0,_react.useEffect)(function(){if(maskInScreenshots||isSensitive){registerMaskableComponent({elementId:elementId,maskType:maskType,isSensitive:isSensitive,bounds:getElementBounds(viewRef.current)});}return function(){if(elementId){unregisterMaskableComponent(elementId);}};},[maskInScreenshots,maskType,elementId,isSensitive]);var finalAccessibilityLabel=accessibilityLabel||(maskInScreenshots?'ph-no-capture':undefined)||(isSensitive?'mask-input':undefined);return(0,_jsxRuntime.jsx)(_reactNative.View,_objectSpread(_objectSpread({ref:viewRef,accessibilityLabel:finalAccessibilityLabel},viewProps),{},{children:children}));};function registerMaskableComponent(component){console.log('Registering maskable component:',component);}function unregisterMaskableComponent(elementId){console.log('Unregistering maskable component:',elementId);}function getElementBounds(view){if(!view)return undefined;return undefined;}var _default=exports["default"]=MaskableComponent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaskableComponent.js","sourceRoot":"","sources":["../../src/components/MaskableComponent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,EAAE,IAAI,EAAa,MAAM,cAAc,CAAA;AAiB9C;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,CAAC,EAClE,iBAAiB,GAAG,KAAK,EACzB,QAAQ,GAAG,UAAU,EACrB,SAAS,EACT,WAAW,GAAG,KAAK,EACnB,kBAAkB,EAClB,QAAQ,EACR,GAAG,SAAS,EACb,EAAE,EAAE;IACH,MAAM,OAAO,GAAG,MAAM,CAAO,IAAI,CAAC,CAAA;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,6DAA6D;QAC7D,IAAI,iBAAiB,IAAI,WAAW,EAAE,CAAC;YACrC,yEAAyE;YACzE,wCAAwC;YACxC,yBAAyB,CAAC;gBACxB,SAAS;gBACT,QAAQ;gBACR,WAAW;gBACX,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC;aAC1C,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,GAAG,EAAE;YACV,kCAAkC;YAClC,IAAI,SAAS,EAAE,CAAC;gBACd,2BAA2B,CAAC,SAAS,CAAC,CAAA;YACxC,CAAC;QACH,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAA;IAEzD,oCAAoC;IACpC,MAAM,uBAAuB,GAC3B,kBAAkB,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAErH,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,uBAAuB,CAAC,CAAC,IAAI,SAAS,CAAC,CAC7E;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAAC,SAKlC;IACC,wDAAwD;IACxD,gDAAgD;IAChD,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,SAAS,CAAC,CAAA;AAC3D,CAAC;AAED;;GAEG;AACH,SAAS,2BAA2B,CAAC,SAAiB;IACpD,wDAAwD;IACxD,gDAAgD;IAChD,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAA;AAC7D,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,IAAiB;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAE3B,oDAAoD;IACpD,6CAA6C;IAC7C,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,eAAe,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TextInputProps } from 'react-native';
|
|
3
|
+
interface MaskableTextInputProps extends TextInputProps {
|
|
4
|
+
/** Unique identifier for this input */
|
|
5
|
+
maskId: string;
|
|
6
|
+
/** Whether this input should be masked (default: true) */
|
|
7
|
+
shouldMask?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A TextInput component that automatically registers itself for masking
|
|
11
|
+
* This is the practical solution for React Native input masking
|
|
12
|
+
*/
|
|
13
|
+
export declare const MaskableTextInput: React.FC<MaskableTextInputProps>;
|
|
14
|
+
export default MaskableTextInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof=require("@babel/runtime/helpers/typeof");Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=exports.MaskableTextInput=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _componentRegistry=require("../utils/componentRegistry");var _jsxRuntime=require("react/jsx-runtime");var _excluded=["maskId","shouldMask"];var _this=void 0,_jsxFileName="/Users/gegham/www/multiplayer-debugger-javascript/packages/session-recorder-react-native/dist/components/MaskableTextInput.js";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,"default":e};if(null===e||"object"!=_typeof(e)&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t2 in e)"default"!==_t2&&{}.hasOwnProperty.call(e,_t2)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t2))&&(i.get||i.set)?o(f,_t2,i):f[_t2]=e[_t2]);return f;})(e,t);}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var MaskableTextInput=exports.MaskableTextInput=function MaskableTextInput(_ref){var maskId=_ref.maskId,_ref$shouldMask=_ref.shouldMask,shouldMask=_ref$shouldMask===void 0?true:_ref$shouldMask,textInputProps=(0,_objectWithoutProperties2["default"])(_ref,_excluded);var textInputRef=(0,_react.useRef)(null);(0,_react.useEffect)(function(){if(shouldMask&&textInputRef.current){(0,_componentRegistry.registerTextInput)(maskId,textInputRef.current,textInputProps);}return function(){(0,_componentRegistry.unregisterComponent)(maskId);};},[maskId,shouldMask,textInputProps]);return(0,_jsxRuntime.jsx)(_reactNative.TextInput,_objectSpread({ref:textInputRef},textInputProps));};var _default=exports["default"]=MaskableTextInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaskableTextInput.js","sourceRoot":"","sources":["../../src/components/MaskableTextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,EAAE,SAAS,EAAkB,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AASnF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,cAAc,EAAE,EAAE,EAAE;IACtH,MAAM,YAAY,GAAG,MAAM,CAAY,IAAI,CAAC,CAAA;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACvC,sCAAsC;YACtC,iBAAiB,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;QACjE,CAAC;QAED,qBAAqB;QACrB,OAAO,GAAG,EAAE;YACV,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC,CAAA;IAExC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,cAAc,CAAC,EAAG,CAAA;AAC7D,CAAC,CAAA;AAED,eAAe,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WidgetTextOverridesConfig } from '../../types';
|
|
3
|
+
interface FinalPopoverProps {
|
|
4
|
+
textOverrides: WidgetTextOverridesConfig;
|
|
5
|
+
onStopRecording: (comment: string) => void;
|
|
6
|
+
onCancelSession: () => void;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
isSubmitting: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const FinalPopover: React.FC<FinalPopoverProps>;
|
|
11
|
+
export default FinalPopover;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof=require("@babel/runtime/helpers/typeof");Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=void 0;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _styles=require("./styles");var _ModalHeader=_interopRequireDefault(require("./ModalHeader"));var _jsxRuntime=require("react/jsx-runtime");var _this=void 0,_jsxFileName="/Users/gegham/www/multiplayer-debugger-javascript/packages/session-recorder-react-native/dist/components/SessionRecorderWidget/FinalPopover.js";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,"default":e};if(null===e||"object"!=_typeof(e)&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t3 in e)"default"!==_t3&&{}.hasOwnProperty.call(e,_t3)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t3))&&(i.get||i.set)?o(f,_t3,i):f[_t3]=e[_t3]);return f;})(e,t);}var FinalPopover=function FinalPopover(_ref){var textOverrides=_ref.textOverrides,onStopRecording=_ref.onStopRecording,onCancelSession=_ref.onCancelSession,isSubmitting=_ref.isSubmitting;var _useState=(0,_react.useState)(''),_useState2=(0,_slicedToArray2["default"])(_useState,2),comment=_useState2[0],setComment=_useState2[1];var handleStopRecording=function(){var _ref2=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee(){var _t;return _regenerator["default"].wrap(function(_context){while(1)switch(_context.prev=_context.next){case 0:_context.prev=0;_context.next=1;return onStopRecording(comment);case 1:_context.next=3;break;case 2:_context.prev=2;_t=_context["catch"](0);_reactNative.Alert.alert('Error','Failed to save session');case 3:case"end":return _context.stop();}},_callee,null,[[0,2]]);}));return function handleStopRecording(){return _ref2.apply(this,arguments);};}();return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.popoverContent,children:[(0,_jsxRuntime.jsx)(_ModalHeader["default"],{children:(0,_jsxRuntime.jsx)(_reactNative.Pressable,{onPress:onCancelSession,style:_styles.sharedStyles.cancelButton,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.cancelButtonText,children:textOverrides.cancelButtonText})})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.popoverBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.title,children:textOverrides.finalTitle}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.description,children:textOverrides.finalDescription}),(0,_jsxRuntime.jsx)(_reactNative.TextInput,{style:_styles.sharedStyles.commentInput,placeholder:textOverrides.commentPlaceholder,value:comment,onChangeText:setComment,multiline:true,numberOfLines:3,textAlignVertical:"top"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_styles.sharedStyles.popoverFooter,children:(0,_jsxRuntime.jsx)(_reactNative.Pressable,{style:[_styles.sharedStyles.actionButton,_styles.sharedStyles.stopButton],onPress:handleStopRecording,disabled:isSubmitting,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.actionButtonText,children:isSubmitting?'Saving...':textOverrides.saveButtonText})})})]})]});};var _default=exports["default"]=FinalPopover;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FinalPopover.js","sourceRoot":"","sources":["../../../src/components/SessionRecorderWidget/FinalPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,WAAW,MAAM,eAAe,CAAA;AAUvC,MAAM,YAAY,GAAgC,CAAC,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,EAAE,EAAE;IACtH,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAE1C,MAAM,mBAAmB,GAAG,KAAK,IAAI,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,OAAO,CAAC,CAAA;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAA;QAChD,CAAC;IACH,CAAC,CAAA;IAED,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,CACvC;MAAA,CAAC,WAAW,CACV;QAAA,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,CACpE;UAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,EAAE,IAAI,CACpF;QAAA,EAAE,SAAS,CACb;MAAA,EAAE,WAAW,CAEb;;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,CACpC;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,IAAI,CACjE;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAE7E;;QAAA,CAAC,SAAS,CACR,KAAK,CAAC,CAAC,YAAY,CAAC,YAAY,CAAC,CACjC,WAAW,CAAC,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAC9C,KAAK,CAAC,CAAC,OAAO,CAAC,CACf,YAAY,CAAC,CAAC,UAAU,CAAC,CACzB,SAAS,CACT,aAAa,CAAC,CAAC,CAAC,CAAC,CACjB,iBAAiB,CAAC,KAAK,EAGzB;;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CACtC;UAAA,CAAC,SAAS,CACR,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC,CAC5D,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAC7B,QAAQ,CAAC,CAAC,YAAY,CAAC,CAEvB;YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,IAAI,CAC/G;UAAA,EAAE,SAAS,CACb;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SessionState } from '../../types';
|
|
3
|
+
interface FloatingButtonProps {
|
|
4
|
+
sessionState: SessionState | null;
|
|
5
|
+
onPress: () => void;
|
|
6
|
+
}
|
|
7
|
+
declare const FloatingButton: React.FC<FloatingButtonProps>;
|
|
8
|
+
export default FloatingButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof=require("@babel/runtime/helpers/typeof");Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _types=require("../../types");var _storage=require("../../services/storage.service");var _icons=require("./icons");var _jsxRuntime=require("react/jsx-runtime");var _this=void 0,_jsxFileName="/Users/gegham/www/multiplayer-debugger-javascript/packages/session-recorder-react-native/dist/components/SessionRecorderWidget/FloatingButton.js";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,"default":e};if(null===e||"object"!=_typeof(e)&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t2 in e)"default"!==_t2&&{}.hasOwnProperty.call(e,_t2)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t2))&&(i.get||i.set)?o(f,_t2,i):f[_t2]=e[_t2]);return f;})(e,t);}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){(0,_defineProperty2["default"])(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}var buttonSize=52;var rightOffset=20;var topOffset=_reactNative.Platform.OS==='ios'?60:40;var FloatingButton=function FloatingButton(_ref){var sessionState=_ref.sessionState,onPress=_ref.onPress;var position=(0,_react.useRef)(new _reactNative.Animated.ValueXY({x:0,y:0})).current;var lastPosition=(0,_react.useRef)({top:topOffset,right:rightOffset});var storageService=(0,_react.useRef)(_storage.StorageService.getInstance()).current;var screenBounds=(0,_react.useMemo)(function(){var _Dimensions$get=_reactNative.Dimensions.get('window'),width=_Dimensions$get.width,height=_Dimensions$get.height;return{minTop:topOffset,maxTop:height-buttonSize,minRight:0,maxRight:width-buttonSize};},[]);(0,_react.useEffect)(function(){var savedPosition=storageService.getFloatingButtonPosition();if(savedPosition){var _Dimensions$get2=_reactNative.Dimensions.get('window'),width=_Dimensions$get2.width;var top=savedPosition.y;var right=width-savedPosition.x-buttonSize;lastPosition.current={top:top,right:right};position.setValue({x:right,y:top});}else{position.setValue({x:lastPosition.current.right,y:lastPosition.current.top});}},[]);var panResponder=(0,_react.useRef)(_reactNative.PanResponder.create({onStartShouldSetPanResponder:function onStartShouldSetPanResponder(){return true;},onMoveShouldSetPanResponder:function onMoveShouldSetPanResponder(evt,gestureState){var distance=Math.sqrt(gestureState.dx*gestureState.dx+gestureState.dy*gestureState.dy);return distance>5;},onPanResponderGrant:function onPanResponderGrant(){position.setValue({x:lastPosition.current.right,y:lastPosition.current.top});},onPanResponderMove:function onPanResponderMove(evt,gestureState){var newTop=lastPosition.current.top+gestureState.dy;var newRight=lastPosition.current.right-gestureState.dx;position.setValue({x:newRight,y:newTop});},onPanResponderRelease:function onPanResponderRelease(e,gestureState){var distance=Math.sqrt(gestureState.dx*gestureState.dx+gestureState.dy*gestureState.dy);if(distance<=5){onPress();}else{var newTop=lastPosition.current.top+gestureState.dy;var newRight=lastPosition.current.right-gestureState.dx;var clampedTop=Math.max(screenBounds.minTop,Math.min(screenBounds.maxTop,newTop));var clampedRight=Math.max(screenBounds.minRight,Math.min(screenBounds.maxRight,newRight));lastPosition.current={top:clampedTop,right:clampedRight};position.setValue({x:clampedRight,y:clampedTop});var _Dimensions$get3=_reactNative.Dimensions.get('window'),width=_Dimensions$get3.width;var storagePosition={x:width-clampedRight-buttonSize,y:clampedTop};storageService.saveFloatingButtonPosition(storagePosition);}}})).current;var content=(0,_react.useMemo)(function(){switch(sessionState){case _types.SessionState.started:return{icon:(0,_jsxRuntime.jsx)(_icons.CapturingIcon,{size:28,color:"white"}),color:'#FF4444'};case _types.SessionState.paused:return{icon:(0,_jsxRuntime.jsx)(_icons.PausedIcon,{size:28,color:"white"}),color:'#FFA500'};default:return{icon:(0,_jsxRuntime.jsx)(_icons.RecordIcon,{size:28,color:"#718096"}),color:'#ffffff'};}},[sessionState]);return(0,_jsxRuntime.jsx)(_reactNative.Animated.View,_objectSpread(_objectSpread({style:[styles.draggableButton,{top:position.y,right:position.x}]},panResponder.panHandlers),{},{children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.floatingButton,{backgroundColor:content.color}],children:content.icon})}));};var styles=_reactNative.StyleSheet.create({draggableButton:{position:'absolute'},floatingButton:{elevation:8,shadowRadius:4,width:buttonSize,shadowColor:'#000',height:buttonSize,shadowOpacity:0.25,alignItems:'center',justifyContent:'center',borderRadius:buttonSize/2,shadowOffset:{width:0,height:2}}});var _default=exports["default"]=FloatingButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingButton.js","sourceRoot":"","sources":["../../../src/components/SessionRecorderWidget/FloatingButton.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SessionType } from '@multiplayer-app/session-recorder-common';
|
|
3
|
+
import { WidgetTextOverridesConfig } from '../../types';
|
|
4
|
+
interface InitialPopoverProps {
|
|
5
|
+
textOverrides: WidgetTextOverridesConfig;
|
|
6
|
+
showContinuousRecording: boolean;
|
|
7
|
+
onStartRecording: (sessionType: SessionType) => void;
|
|
8
|
+
onSaveContinuousSession: () => void;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
isSubmitting: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare const InitialPopover: React.FC<InitialPopoverProps>;
|
|
13
|
+
export default InitialPopover;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof=require("@babel/runtime/helpers/typeof");Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=void 0;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sessionRecorderCommon=require("@multiplayer-app/session-recorder-common");var _styles=require("./styles");var _ModalHeader=_interopRequireDefault(require("./ModalHeader"));var _jsxRuntime=require("react/jsx-runtime");var _this=void 0,_jsxFileName="/Users/gegham/www/multiplayer-debugger-javascript/packages/session-recorder-react-native/dist/components/SessionRecorderWidget/InitialPopover.js";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,"default":e};if(null===e||"object"!=_typeof(e)&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t2 in e)"default"!==_t2&&{}.hasOwnProperty.call(e,_t2)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t2))&&(i.get||i.set)?o(f,_t2,i):f[_t2]=e[_t2]);return f;})(e,t);}var InitialPopover=function InitialPopover(_ref){var textOverrides=_ref.textOverrides,showContinuousRecording=_ref.showContinuousRecording,onStartRecording=_ref.onStartRecording,onSaveContinuousSession=_ref.onSaveContinuousSession,onClose=_ref.onClose,isSubmitting=_ref.isSubmitting;var _useState=(0,_react.useState)(false),_useState2=(0,_slicedToArray2["default"])(_useState,2),continuousRecording=_useState2[0],setContinuousRecording=_useState2[1];var handleStartRecording=function(){var _ref2=(0,_asyncToGenerator2["default"])(_regenerator["default"].mark(function _callee(){var sessionType;return _regenerator["default"].wrap(function(_context){while(1)switch(_context.prev=_context.next){case 0:try{sessionType=continuousRecording?_sessionRecorderCommon.SessionType.CONTINUOUS:_sessionRecorderCommon.SessionType.PLAIN;onStartRecording(sessionType);}catch(error){_reactNative.Alert.alert('Error','Failed to start recording');}case 1:case"end":return _context.stop();}},_callee);}));return function handleStartRecording(){return _ref2.apply(this,arguments);};}();return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.popoverContent,children:[(0,_jsxRuntime.jsx)(_ModalHeader["default"],{}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.popoverBody,children:[showContinuousRecording&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.continuousRecordingSection,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.continuousRecordingLabel,children:textOverrides.continuousRecordingLabel}),(0,_jsxRuntime.jsx)(_reactNative.Switch,{value:continuousRecording,onValueChange:setContinuousRecording,trackColor:{"false":'#767577',"true":'#81b0ff'},thumbColor:continuousRecording?'#007AFF':'#f4f3f4'})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.title,children:showContinuousRecording?textOverrides.initialTitleWithContinuous:textOverrides.initialTitleWithoutContinuous}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.description,children:showContinuousRecording?textOverrides.initialDescriptionWithContinuous:textOverrides.initialDescriptionWithoutContinuous}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:_styles.sharedStyles.popoverFooter,children:(0,_jsxRuntime.jsx)(_reactNative.Pressable,{style:[_styles.sharedStyles.actionButton,_styles.sharedStyles.startButton],onPress:handleStartRecording,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.actionButtonText,children:textOverrides.startRecordingButtonText})})}),showContinuousRecording&&continuousRecording&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.continuousOverlay,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:_styles.sharedStyles.continuousOverlayContent,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:_styles.sharedStyles.continuousOverlayTitle,children:["\uD83D\uDD34 ",textOverrides.continuousOverlayTitle]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.continuousOverlayDescription,children:textOverrides.continuousOverlayDescription})]}),(0,_jsxRuntime.jsx)(_reactNative.Pressable,{style:[_styles.sharedStyles.actionButton,_styles.sharedStyles.saveButton],onPress:onSaveContinuousSession,disabled:isSubmitting,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:_styles.sharedStyles.actionButtonText,children:textOverrides.saveLastSnapshotButtonText})})]})]})]});};var _default=exports["default"]=InitialPopover;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitialPopover.js","sourceRoot":"","sources":["../../../src/components/SessionRecorderWidget/InitialPopover.tsx"],"names":[],"mappings":"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"}
|