Skip to content

Commit 4095c48

Browse files
Merge pull request #851 from DataDog/marcosaia/RUM-9424/support-rn-79
[RUM-9424] Session Replay support for RN 0.79
2 parents c704763 + bdf3d0d commit 4095c48

File tree

3 files changed

+127
-1
lines changed

3 files changed

+127
-1
lines changed

packages/react-native-session-replay/android/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ android {
135135
java.srcDirs += ['src/oldarch/kotlin']
136136
}
137137

138-
if (reactNativeMinorVersion >= 76) {
138+
if (reactNativeMinorVersion >= 79) {
139+
java.srcDirs += ['src/rn79/kotlin']
140+
} else if (reactNativeMinorVersion >= 76) {
139141
java.srcDirs += ['src/rn76/kotlin']
140142
} else if (reactNativeMinorVersion >= 75) {
141143
java.srcDirs += ['src/rn75/kotlin']
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
package com.datadog.reactnative.sessionreplay.extensions
7+
8+
import com.facebook.react.uimanager.LengthPercentage
9+
10+
internal fun LengthPercentage?.getRadius(width: Float, height: Float) = this
11+
?.resolve(width, height)
12+
?.let { (it.horizontal + it.vertical) / 2f }
13+
?: 0f
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
import android.graphics.drawable.Drawable
7+
import android.graphics.drawable.InsetDrawable
8+
import android.graphics.drawable.LayerDrawable
9+
import com.datadog.android.sessionreplay.model.MobileSegment
10+
import com.datadog.reactnative.sessionreplay.extensions.getRadius
11+
import com.datadog.reactnative.sessionreplay.utils.DrawableUtils
12+
import com.datadog.reactnative.sessionreplay.utils.formatAsRgba
13+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
14+
import com.facebook.react.uimanager.LengthPercentage
15+
import com.facebook.react.uimanager.Spacing
16+
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
17+
18+
internal class ReactViewBackgroundDrawableUtils : DrawableUtils() {
19+
@OptIn(UnstableReactNativeAPI::class)
20+
override fun resolveShapeAndBorder(
21+
drawable: Drawable,
22+
opacity: Float,
23+
pixelDensity: Float
24+
): Pair<MobileSegment.ShapeStyle?, MobileSegment.ShapeBorder?> {
25+
if (drawable !is CSSBackgroundDrawable) {
26+
return null to null
27+
}
28+
29+
val borderProps = resolveBorder(drawable, pixelDensity)
30+
val backgroundColor = getBackgroundColor(drawable)
31+
val colorHexString = if (backgroundColor != null) {
32+
formatAsRgba(backgroundColor)
33+
} else {
34+
return null to borderProps
35+
}
36+
37+
return MobileSegment.ShapeStyle(
38+
colorHexString,
39+
opacity,
40+
getBorderRadius(drawable)
41+
) to borderProps
42+
}
43+
44+
@OptIn(UnstableReactNativeAPI::class)
45+
override fun getReactBackgroundFromDrawable(drawable: Drawable?): Drawable? {
46+
return when(drawable) {
47+
is CSSBackgroundDrawable -> drawable
48+
is InsetDrawable -> getReactBackgroundFromDrawable(drawable.drawable)
49+
is LayerDrawable -> getDrawableFromLayerDrawable(drawable)
50+
else -> null
51+
}
52+
}
53+
54+
@OptIn(UnstableReactNativeAPI::class)
55+
private fun getDrawableFromLayerDrawable(layerDrawable: LayerDrawable): Drawable? {
56+
for (layerNumber in 0 until layerDrawable.numberOfLayers) {
57+
val layer = layerDrawable.getDrawable(layerNumber)
58+
if (layer is CSSBackgroundDrawable) {
59+
return layer
60+
}
61+
}
62+
return null
63+
}
64+
65+
@OptIn(UnstableReactNativeAPI::class)
66+
private fun getBorderRadius(drawable: CSSBackgroundDrawable): Float {
67+
val width = drawable.intrinsicWidth.toFloat()
68+
val height = drawable.intrinsicHeight.toFloat()
69+
val uniform = getBorderRadiusUniform(drawable)
70+
return uniform?.getRadius(width, height) ?: 0f
71+
}
72+
73+
@OptIn(UnstableReactNativeAPI::class)
74+
private fun getBorderRadiusUniform(
75+
drawable: CSSBackgroundDrawable
76+
): LengthPercentage? {
77+
return reflectionUtils.getDeclaredField(
78+
drawable.borderRadius,
79+
UNIFORM_FIELD_NAME
80+
) as? LengthPercentage
81+
}
82+
83+
@OptIn(UnstableReactNativeAPI::class)
84+
private fun getBackgroundColor(
85+
backgroundDrawable: CSSBackgroundDrawable
86+
): Int? {
87+
return reflectionUtils.getDeclaredField(
88+
backgroundDrawable,
89+
COLOR_FIELD_NAME
90+
) as? Int
91+
}
92+
93+
@OptIn(UnstableReactNativeAPI::class)
94+
private fun resolveBorder(
95+
backgroundDrawable: CSSBackgroundDrawable,
96+
pixelDensity: Float
97+
): MobileSegment.ShapeBorder {
98+
val borderWidth = (backgroundDrawable.fullBorderWidth / pixelDensity).toLong()
99+
val borderColor = formatAsRgba(backgroundDrawable.getBorderColor(Spacing.ALL))
100+
101+
return MobileSegment.ShapeBorder(
102+
color = borderColor,
103+
width = borderWidth
104+
)
105+
}
106+
107+
private companion object {
108+
private const val COLOR_FIELD_NAME = "mColor"
109+
private const val UNIFORM_FIELD_NAME = "uniform"
110+
}
111+
}

0 commit comments

Comments
 (0)