@datadog/mobile-react-native-session-replay 2.1.0-alpha.0 → 2.1.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DatadogSDKReactNativeSessionReplay.podspec +2 -1
- package/android/build.gradle +1 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt +3 -2
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt +7 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplaySDKWrapper.kt +3 -0
- package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplayWrapper.kt +2 -0
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementationTest.kt +2 -2
- package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolverTest.kt +24 -1
- package/ios/Sources/DdSessionReplayImplementation.swift +14 -6
- package/package.json +1 -1
|
@@ -20,7 +20,8 @@ Pod::Spec.new do |s|
|
|
|
20
20
|
|
|
21
21
|
# /!\ Remember to keep the version in sync with DatadogSDKReactNative.podspec
|
|
22
22
|
s.dependency 'DatadogSessionReplay', '~> 2.6.0'
|
|
23
|
-
|
|
23
|
+
s.dependency 'DatadogSDKReactNative'
|
|
24
|
+
|
|
24
25
|
s.test_spec 'Tests' do |test_spec|
|
|
25
26
|
test_spec.dependency "React-RCTText"
|
|
26
27
|
test_spec.source_files = 'ios/Tests/*.swift'
|
package/android/build.gradle
CHANGED
|
@@ -189,6 +189,7 @@ dependencies {
|
|
|
189
189
|
}
|
|
190
190
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
191
191
|
implementation "com.datadoghq:dd-sdk-android-session-replay:2.5.0"
|
|
192
|
+
implementation project(path: ':datadog_mobile-react-native')
|
|
192
193
|
|
|
193
194
|
testImplementation "org.junit.platform:junit-platform-launcher:1.6.2"
|
|
194
195
|
testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
|
|
@@ -10,6 +10,7 @@ import com.datadog.android.Datadog
|
|
|
10
10
|
import com.datadog.android.api.feature.FeatureSdkCore
|
|
11
11
|
import com.datadog.android.sessionreplay.SessionReplayConfiguration
|
|
12
12
|
import com.datadog.android.sessionreplay.SessionReplayPrivacy
|
|
13
|
+
import com.datadog.reactnative.DatadogSDKWrapperStorage
|
|
13
14
|
import com.facebook.react.bridge.Promise
|
|
14
15
|
import com.facebook.react.bridge.ReactContext
|
|
15
16
|
import java.util.Locale
|
|
@@ -30,7 +31,7 @@ class DdSessionReplayImplementation(
|
|
|
30
31
|
* @param customEndpoint Custom server url for sending replay data.
|
|
31
32
|
*/
|
|
32
33
|
fun enable(replaySampleRate: Double, defaultPrivacyLevel: String, customEndpoint: String, promise: Promise) {
|
|
33
|
-
val sdkCore =
|
|
34
|
+
val sdkCore = DatadogSDKWrapperStorage.getSdkCore() as FeatureSdkCore
|
|
34
35
|
val logger = sdkCore.internalLogger
|
|
35
36
|
val configuration = SessionReplayConfiguration.Builder(replaySampleRate.toFloat())
|
|
36
37
|
.setPrivacy(buildPrivacy(defaultPrivacyLevel))
|
|
@@ -40,7 +41,7 @@ class DdSessionReplayImplementation(
|
|
|
40
41
|
configuration.useCustomEndpoint(customEndpoint)
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
sessionReplayProvider().enable(configuration.build())
|
|
44
|
+
sessionReplayProvider().enable(configuration.build(), sdkCore)
|
|
44
45
|
promise.resolve(null)
|
|
45
46
|
}
|
|
46
47
|
|
package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
CHANGED
|
@@ -144,6 +144,12 @@ internal class ReactTextPropertiesResolver(
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
private fun getTextColor(shadowNodeWrapper: ShadowNodeWrapper): String? {
|
|
147
|
+
val isColorSet = shadowNodeWrapper
|
|
148
|
+
.getDeclaredShadowNodeField(IS_COLOR_SET_FIELD_NAME) as Boolean?
|
|
149
|
+
if (isColorSet != true) {
|
|
150
|
+
// Improvement: get default text color if different from black
|
|
151
|
+
return "#000000FF"
|
|
152
|
+
}
|
|
147
153
|
val resolvedColor = shadowNodeWrapper
|
|
148
154
|
.getDeclaredShadowNodeField(COLOR_FIELD_NAME) as Int?
|
|
149
155
|
if (resolvedColor != null) {
|
|
@@ -187,6 +193,7 @@ internal class ReactTextPropertiesResolver(
|
|
|
187
193
|
internal const val TEXT_ATTRIBUTES_FIELD_NAME = "mTextAttributes"
|
|
188
194
|
internal const val FONT_FAMILY_FIELD_NAME = "mFontFamily"
|
|
189
195
|
internal const val COLOR_FIELD_NAME = "mColor"
|
|
196
|
+
internal const val IS_COLOR_SET_FIELD_NAME = "mIsColorSet"
|
|
190
197
|
|
|
191
198
|
private const val ROBOTO_TYPEFACE_NAME = "roboto"
|
|
192
199
|
private const val SERIF_FAMILY_NAME = "serif"
|
package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplaySDKWrapper.kt
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
package com.datadog.reactnative.sessionreplay
|
|
8
8
|
|
|
9
|
+
import com.datadog.android.api.SdkCore
|
|
9
10
|
import com.datadog.android.sessionreplay.SessionReplay
|
|
10
11
|
import com.datadog.android.sessionreplay.SessionReplayConfiguration
|
|
11
12
|
|
|
@@ -16,9 +17,11 @@ internal class SessionReplaySDKWrapper : SessionReplayWrapper {
|
|
|
16
17
|
*/
|
|
17
18
|
override fun enable(
|
|
18
19
|
sessionReplayConfiguration: SessionReplayConfiguration,
|
|
20
|
+
sdkCore: SdkCore
|
|
19
21
|
) {
|
|
20
22
|
SessionReplay.enable(
|
|
21
23
|
sessionReplayConfiguration,
|
|
24
|
+
sdkCore,
|
|
22
25
|
)
|
|
23
26
|
}
|
|
24
27
|
}
|
package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/SessionReplayWrapper.kt
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
package com.datadog.reactnative.sessionreplay
|
|
8
8
|
|
|
9
|
+
import com.datadog.android.api.SdkCore
|
|
9
10
|
import com.datadog.android.sessionreplay.SessionReplayConfiguration
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -18,5 +19,6 @@ interface SessionReplayWrapper {
|
|
|
18
19
|
*/
|
|
19
20
|
fun enable(
|
|
20
21
|
sessionReplayConfiguration: SessionReplayConfiguration,
|
|
22
|
+
sdkCore: SdkCore
|
|
21
23
|
)
|
|
22
24
|
}
|
|
@@ -84,7 +84,7 @@ internal class DdSessionReplayImplementationTest {
|
|
|
84
84
|
)
|
|
85
85
|
|
|
86
86
|
// Then
|
|
87
|
-
verify(mockSessionReplay).enable(sessionReplayConfigCaptor.capture())
|
|
87
|
+
verify(mockSessionReplay).enable(sessionReplayConfigCaptor.capture(), any())
|
|
88
88
|
assertThat(sessionReplayConfigCaptor.firstValue)
|
|
89
89
|
.hasFieldEqualTo("sampleRate", replaySampleRate.toFloat())
|
|
90
90
|
.hasFieldEqualTo("privacy", privacy)
|
|
@@ -104,7 +104,7 @@ internal class DdSessionReplayImplementationTest {
|
|
|
104
104
|
testedSessionReplay.enable(replaySampleRate, privacy, "", mockPromise)
|
|
105
105
|
|
|
106
106
|
// Then
|
|
107
|
-
verify(mockSessionReplay).enable(sessionReplayConfigCaptor.capture())
|
|
107
|
+
verify(mockSessionReplay).enable(sessionReplayConfigCaptor.capture(), any())
|
|
108
108
|
assertThat(sessionReplayConfigCaptor.firstValue)
|
|
109
109
|
.hasFieldEqualTo("sampleRate", replaySampleRate.toFloat())
|
|
110
110
|
.hasFieldEqualTo("privacy", SessionReplayPrivacy.MASK)
|
|
@@ -10,6 +10,7 @@ import android.widget.TextView
|
|
|
10
10
|
import com.datadog.android.sessionreplay.model.MobileSegment
|
|
11
11
|
import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver.Companion.COLOR_FIELD_NAME
|
|
12
12
|
import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver.Companion.FONT_FAMILY_FIELD_NAME
|
|
13
|
+
import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver.Companion.IS_COLOR_SET_FIELD_NAME
|
|
13
14
|
import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver.Companion.MONOSPACE_FAMILY_NAME
|
|
14
15
|
import com.datadog.reactnative.sessionreplay.ReactTextPropertiesResolver.Companion.TEXT_ATTRIBUTES_FIELD_NAME
|
|
15
16
|
import com.datadog.reactnative.sessionreplay.ShadowNodeWrapper.Companion.UI_IMPLEMENTATION_FIELD_NAME
|
|
@@ -238,11 +239,13 @@ internal class ReactTextPropertiesResolverTest {
|
|
|
238
239
|
}
|
|
239
240
|
|
|
240
241
|
@Test
|
|
241
|
-
fun `M resolve font color W addReactNativeProperties()`(
|
|
242
|
+
fun `M resolve font color W addReactNativeProperties() { color is defined by developer }`(
|
|
242
243
|
@IntForgery fakeTextColor: Int
|
|
243
244
|
) {
|
|
244
245
|
// Given
|
|
245
246
|
whenever(mockTextView.background).thenReturn(null)
|
|
247
|
+
whenever(mockReflectionUtils.getDeclaredField(mockShadowNode, IS_COLOR_SET_FIELD_NAME))
|
|
248
|
+
.thenReturn(true)
|
|
246
249
|
whenever(mockReflectionUtils.getDeclaredField(mockShadowNode, COLOR_FIELD_NAME))
|
|
247
250
|
.thenReturn(fakeTextColor)
|
|
248
251
|
|
|
@@ -253,10 +256,30 @@ internal class ReactTextPropertiesResolverTest {
|
|
|
253
256
|
assertThat(result.textStyle.color).isEqualTo(formatAsRgba(fakeTextColor))
|
|
254
257
|
}
|
|
255
258
|
|
|
259
|
+
@Test
|
|
260
|
+
fun `M resolve font color W addReactNativeProperties() { color is not defined by developer }`(
|
|
261
|
+
@IntForgery fakeTextColor: Int
|
|
262
|
+
) {
|
|
263
|
+
// Given
|
|
264
|
+
whenever(mockTextView.background).thenReturn(null)
|
|
265
|
+
whenever(mockReflectionUtils.getDeclaredField(mockShadowNode, IS_COLOR_SET_FIELD_NAME))
|
|
266
|
+
.thenReturn(false)
|
|
267
|
+
whenever(mockReflectionUtils.getDeclaredField(mockShadowNode, COLOR_FIELD_NAME))
|
|
268
|
+
.thenReturn(fakeTextColor)
|
|
269
|
+
|
|
270
|
+
// When
|
|
271
|
+
val result = testedResolver.addReactNativeProperties(fakeWireframe, mockTextView, 0f)
|
|
272
|
+
|
|
273
|
+
// Then
|
|
274
|
+
assertThat(result.textStyle.color).isEqualTo("#000000FF")
|
|
275
|
+
}
|
|
276
|
+
|
|
256
277
|
@Test
|
|
257
278
|
fun `M fallback W addReactNativeProperties() { cannot resolve fontColor }`() {
|
|
258
279
|
// Given
|
|
259
280
|
whenever(mockTextView.background).thenReturn(null)
|
|
281
|
+
whenever(mockReflectionUtils.getDeclaredField(mockShadowNode, IS_COLOR_SET_FIELD_NAME))
|
|
282
|
+
.thenReturn(true)
|
|
260
283
|
whenever(mockShadowNodeWrapper.getDeclaredShadowNodeField(COLOR_FIELD_NAME))
|
|
261
284
|
.thenReturn(null)
|
|
262
285
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import Foundation
|
|
8
8
|
@_spi(Internal) import DatadogSessionReplay
|
|
9
9
|
import DatadogInternal
|
|
10
|
+
import DatadogSDKReactNative
|
|
10
11
|
import React
|
|
11
12
|
|
|
12
13
|
@objc
|
|
@@ -42,9 +43,15 @@ public class DdSessionReplayImplementation: NSObject {
|
|
|
42
43
|
|
|
43
44
|
sessionReplayConfiguration.setAdditionalNodeRecorders([RCTTextViewRecorder(uiManager: self.uiManager)])
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
if let core = DatadogSDKWrapper.shared.getCoreInstance() {
|
|
47
|
+
sessionReplay.enable(
|
|
48
|
+
with: sessionReplayConfiguration,
|
|
49
|
+
in: core
|
|
50
|
+
)
|
|
51
|
+
} else {
|
|
52
|
+
consolePrint("Core instance was not found when initializing Session Replay.")
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
resolve(nil)
|
|
49
56
|
}
|
|
50
57
|
|
|
@@ -64,12 +71,13 @@ public class DdSessionReplayImplementation: NSObject {
|
|
|
64
71
|
|
|
65
72
|
internal protocol SessionReplayProtocol {
|
|
66
73
|
func enable(
|
|
67
|
-
with configuration: SessionReplay.Configuration
|
|
74
|
+
with configuration: SessionReplay.Configuration,
|
|
75
|
+
in core: DatadogCoreProtocol
|
|
68
76
|
)
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
internal class NativeSessionReplay: SessionReplayProtocol {
|
|
72
|
-
func enable(with configuration: DatadogSessionReplay.SessionReplay.Configuration) {
|
|
73
|
-
SessionReplay.enable(with: configuration)
|
|
80
|
+
func enable(with configuration: DatadogSessionReplay.SessionReplay.Configuration, in core: DatadogCoreProtocol) {
|
|
81
|
+
SessionReplay.enable(with: configuration, in: core)
|
|
74
82
|
}
|
|
75
83
|
}
|
package/package.json
CHANGED