@truewatchtech/react-native-mobile 0.3.15-alpha.1 → 0.4.0-alpha.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 (78) hide show
  1. package/FTMobileReactNativeSDK.podspec +2 -1
  2. package/android/build.gradle +21 -3
  3. package/android/src/main/java/com/ft/sdk/reactnative/FTSessionReplayImpl.java +60 -0
  4. package/android/src/main/java/com/ft/sdk/reactnative/FTTraceImpl.java +1 -1
  5. package/android/src/main/java/com/ft/sdk/reactnative/extensions/ReactDrawablesExt.java +155 -0
  6. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/NoopTextPropertiesResolver.java +23 -0
  7. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.java +57 -0
  8. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/ShadowNodeWrapper.java +84 -0
  9. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/TextPropertiesResolver.java +20 -0
  10. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/DefaultMapper.java +78 -0
  11. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/Pair.java +11 -0
  12. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactEditTextMapper.java +136 -0
  13. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactNativeImageViewMapper.java +117 -0
  14. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactTextMapper.java +57 -0
  15. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactViewGroupMapper.java +22 -0
  16. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactViewModalMapper.java +21 -0
  17. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/resources/ReactDrawableCopier.java +35 -0
  18. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/DrawableUtils.java +34 -0
  19. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/ReflectionUtils.java +43 -0
  20. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/FabricTextViewUtils.java +69 -0
  21. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/LegacyTextViewUtils.java +97 -0
  22. package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/TextViewUtils.java +184 -0
  23. package/android/src/main/java/com/ft/sdk/reactnative/utils/ColorUtils.java +24 -0
  24. package/android/src/newarch/java/com/ft/sdk/reactnative/FTSessionReplayModule.java +30 -0
  25. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTSessionReplayModule.java +25 -0
  26. package/android/src/rn69/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +100 -0
  27. package/android/src/rn75/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +27 -0
  28. package/android/src/rn75/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +116 -0
  29. package/android/src/rn76/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +38 -0
  30. package/android/src/rn76/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +117 -0
  31. package/android/src/rn79/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +38 -0
  32. package/android/src/rn79/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +132 -0
  33. package/android/src/rn80/java/com/ft/sdk/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.java +58 -0
  34. package/android/src/rn80/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +190 -0
  35. package/android/src/rnlegacy/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +120 -0
  36. package/android/src/rnpost74/java/com/ft/sdk/reactnative/FTMobilePackage.java +3 -4
  37. package/android/src/rnpre74/java/com/ft/sdk/reactnative/FTMobilePackage.java +1 -0
  38. package/ios/FTMobileReactNative.m +3 -2
  39. package/ios/FTRCTTextViewRecorder.h +33 -0
  40. package/ios/FTRCTTextViewRecorder.m +120 -0
  41. package/ios/FTReactNativeLog.m +1 -1
  42. package/ios/FTReactNativeRUM.h +0 -1
  43. package/ios/FTReactNativeSessionReplay.h +6 -0
  44. package/ios/FTReactNativeSessionReplay.mm +44 -0
  45. package/ios/FTReactNativeTrace.h +0 -2
  46. package/ios/FTReactNativeTrace.m +0 -2
  47. package/ios/FtMobileAgent.xcodeproj/project.pbxproj +6 -0
  48. package/lib/commonjs/ft_logger.js.map +1 -1
  49. package/lib/commonjs/ft_mobile_agent.js.map +1 -1
  50. package/lib/commonjs/ft_rum.js.map +1 -1
  51. package/lib/commonjs/ft_session_replay.js +34 -0
  52. package/lib/commonjs/ft_session_replay.js.map +1 -0
  53. package/lib/commonjs/ft_tracing.js.map +1 -1
  54. package/lib/commonjs/index.js +19 -0
  55. package/lib/commonjs/index.js.map +1 -1
  56. package/lib/commonjs/version.js +1 -1
  57. package/lib/commonjs/version.js.map +1 -1
  58. package/lib/module/ft_logger.js.map +1 -1
  59. package/lib/module/ft_mobile_agent.js.map +1 -1
  60. package/lib/module/ft_rum.js.map +1 -1
  61. package/lib/module/ft_session_replay.js +29 -0
  62. package/lib/module/ft_session_replay.js.map +1 -0
  63. package/lib/module/ft_tracing.js.map +1 -1
  64. package/lib/module/index.js +2 -1
  65. package/lib/module/index.js.map +1 -1
  66. package/lib/module/version.js +1 -1
  67. package/lib/module/version.js.map +1 -1
  68. package/lib/typescript/ft_session_replay.d.ts +27 -0
  69. package/lib/typescript/index.d.ts +2 -1
  70. package/lib/typescript/version.d.ts +1 -1
  71. package/package.json +1 -1
  72. package/src/ft_logger.tsx +0 -1
  73. package/src/ft_mobile_agent.tsx +0 -1
  74. package/src/ft_rum.tsx +1 -3
  75. package/src/ft_session_replay.tsx +34 -0
  76. package/src/ft_tracing.tsx +0 -1
  77. package/src/index.tsx +3 -1
  78. package/src/version.ts +1 -1
@@ -0,0 +1,38 @@
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.ft.sdk.reactnative.sessionreplay.extensions;
7
+
8
+ import com.facebook.react.uimanager.LengthPercentage;
9
+ import com.facebook.react.uimanager.style.CornerRadii;
10
+
11
+ public final class LengthPercentageExt {
12
+
13
+ private LengthPercentageExt() {
14
+ // Utility class, prevent instantiation
15
+ }
16
+
17
+ /**
18
+ * Gets the average radius value from a LengthPercentage, or returns 0f if the LengthPercentage is null.
19
+ * The radius is calculated as the average of horizontal and vertical values.
20
+ *
21
+ * @param lengthPercentage the LengthPercentage to resolve, can be null
22
+ * @param width the width to resolve against
23
+ * @param height the height to resolve against
24
+ * @return the average radius value, or 0f if lengthPercentage is null
25
+ */
26
+ public static float getRadius(LengthPercentage lengthPercentage, float width, float height) {
27
+ if (lengthPercentage == null) {
28
+ return 0f;
29
+ }
30
+
31
+ CornerRadii value = lengthPercentage.resolve(width, height);
32
+ if (value == null) {
33
+ return 0f;
34
+ }
35
+
36
+ return (value.getHorizontal() + value.getVertical()) / 2f;
37
+ }
38
+ }
@@ -0,0 +1,132 @@
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.ft.sdk.reactnative.sessionreplay.utils;
7
+
8
+ import android.graphics.drawable.Drawable;
9
+ import android.graphics.drawable.InsetDrawable;
10
+ import android.graphics.drawable.LayerDrawable;
11
+
12
+ import com.ft.sdk.reactnative.sessionreplay.extensions.LengthPercentageExt;
13
+ import com.ft.sdk.reactnative.sessionreplay.mappers.Pair;
14
+ import com.ft.sdk.reactnative.utils.ColorUtils;
15
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI;
16
+ import com.facebook.react.uimanager.LengthPercentage;
17
+ import com.facebook.react.uimanager.Spacing;
18
+ import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable;
19
+ import com.ft.sdk.sessionreplay.model.ShapeBorder;
20
+ import com.ft.sdk.sessionreplay.model.ShapeStyle;
21
+
22
+ public class ReactViewBackgroundDrawableUtils extends DrawableUtils {
23
+ private static final String COLOR_FIELD_NAME = "mColor";
24
+ private static final String UNIFORM_FIELD_NAME = "uniform";
25
+ private final ReflectionUtils reflectionUtils;
26
+
27
+ public ReactViewBackgroundDrawableUtils() {
28
+ this(new ReflectionUtils());
29
+ }
30
+
31
+ public ReactViewBackgroundDrawableUtils(ReflectionUtils reflectionUtils) {
32
+ this.reflectionUtils = reflectionUtils;
33
+ }
34
+
35
+ @UnstableReactNativeAPI
36
+ @Override
37
+ public Pair<ShapeStyle, ShapeBorder> resolveShapeAndBorder(
38
+ Drawable drawable,
39
+ float opacity,
40
+ float pixelDensity
41
+ ) {
42
+ if (!(drawable instanceof CSSBackgroundDrawable)) {
43
+ return new Pair<>(null, null);
44
+ }
45
+ CSSBackgroundDrawable cssDrawable = (CSSBackgroundDrawable) drawable;
46
+ ShapeBorder borderProps = resolveBorder(cssDrawable, pixelDensity);
47
+ Integer backgroundColor = getBackgroundColor(cssDrawable);
48
+ String colorHexString;
49
+ if (backgroundColor != null) {
50
+ colorHexString = ColorUtils.formatAsRgba(backgroundColor);
51
+ } else {
52
+ return new Pair<>(null, borderProps);
53
+ }
54
+ return new Pair<>(
55
+ new ShapeStyle(
56
+ colorHexString,
57
+ opacity,
58
+ getBorderRadius(cssDrawable)
59
+ ),
60
+ borderProps
61
+ );
62
+ }
63
+
64
+ @UnstableReactNativeAPI
65
+ @Override
66
+ public Drawable getReactBackgroundFromDrawable(Drawable drawable) {
67
+ if (drawable instanceof CSSBackgroundDrawable) {
68
+ return drawable;
69
+ } else if (drawable instanceof InsetDrawable) {
70
+ return getReactBackgroundFromDrawable(((InsetDrawable) drawable).getDrawable());
71
+ } else if (drawable instanceof LayerDrawable) {
72
+ return getDrawableFromLayerDrawable((LayerDrawable) drawable);
73
+ } else {
74
+ return null;
75
+ }
76
+ }
77
+
78
+ @UnstableReactNativeAPI
79
+ private Drawable getDrawableFromLayerDrawable(LayerDrawable layerDrawable) {
80
+ for (int layerNumber = 0; layerNumber < layerDrawable.getNumberOfLayers(); layerNumber++) {
81
+ Drawable layer = layerDrawable.getDrawable(layerNumber);
82
+ if (layer instanceof CSSBackgroundDrawable) {
83
+ return layer;
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+
89
+ @UnstableReactNativeAPI
90
+ private float getBorderRadius(CSSBackgroundDrawable drawable) {
91
+ float width = (float) drawable.getIntrinsicWidth();
92
+ float height = (float) drawable.getIntrinsicHeight();
93
+ LengthPercentage uniform = getBorderRadiusUniform(drawable);
94
+ if (uniform != null) {
95
+ return LengthPercentageExt.getRadius(uniform, width, height);
96
+ } else {
97
+ return 0f;
98
+ }
99
+ }
100
+
101
+ @UnstableReactNativeAPI
102
+ private LengthPercentage getBorderRadiusUniform(CSSBackgroundDrawable drawable) {
103
+ Object value = reflectionUtils.getDeclaredField(
104
+ drawable.getBorderRadius(),
105
+ UNIFORM_FIELD_NAME
106
+ );
107
+ return value instanceof LengthPercentage ? (LengthPercentage) value : null;
108
+ }
109
+
110
+ @UnstableReactNativeAPI
111
+ private Integer getBackgroundColor(CSSBackgroundDrawable backgroundDrawable) {
112
+ Object value = reflectionUtils.getDeclaredField(
113
+ backgroundDrawable,
114
+ COLOR_FIELD_NAME
115
+ );
116
+ return value instanceof Integer ? (Integer) value : null;
117
+ }
118
+
119
+ @UnstableReactNativeAPI
120
+ private ShapeBorder resolveBorder(
121
+ CSSBackgroundDrawable backgroundDrawable,
122
+ float pixelDensity
123
+ ) {
124
+ long borderWidth = (long) (backgroundDrawable.getFullBorderWidth() / pixelDensity);
125
+ String borderColor = ColorUtils.formatAsRgba(backgroundDrawable.getBorderColor(Spacing.ALL));
126
+ return new ShapeBorder(
127
+ borderColor,
128
+ borderWidth
129
+ );
130
+ }
131
+
132
+ }
@@ -0,0 +1,58 @@
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.ft.sdk.reactnative.sessionreplay.extensions;
7
+
8
+ import com.facebook.react.uimanager.style.ComputedBorderRadius;
9
+ import com.facebook.react.uimanager.style.ComputedBorderRadiusProp;
10
+ import com.facebook.react.uimanager.style.CornerRadii;
11
+
12
+ public final class ComputedBorderRadiusExt {
13
+
14
+ private ComputedBorderRadiusExt() {
15
+ // Utility class, prevent instantiation
16
+ }
17
+
18
+ /**
19
+ * Gets the average border radius from all four corners of a ComputedBorderRadius.
20
+ *
21
+ * @param computedBorderRadius the ComputedBorderRadius to calculate average from, can be null
22
+ * @return the average border radius value, or 0f if computedBorderRadius is null
23
+ */
24
+ public static float getAverage(ComputedBorderRadius computedBorderRadius) {
25
+ if (computedBorderRadius == null) {
26
+ return 0f;
27
+ }
28
+
29
+ float topRightRadius = getAverageForProp(computedBorderRadius, ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS);
30
+ float topLeftRadius = getAverageForProp(computedBorderRadius, ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS);
31
+ float bottomRightRadius = getAverageForProp(computedBorderRadius, ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS);
32
+ float bottomLeftRadius = getAverageForProp(computedBorderRadius, ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS);
33
+
34
+ return (topRightRadius + topLeftRadius + bottomRightRadius + bottomLeftRadius) / 4f;
35
+ }
36
+
37
+ /**
38
+ * Gets the average border radius for a specific property of ComputedBorderRadius.
39
+ *
40
+ * @param computedBorderRadius the ComputedBorderRadius to get value from, can be null
41
+ * @param prop the ComputedBorderRadiusProp to get the average for
42
+ * @return the average border radius value for the specified property, or 0f if computedBorderRadius is null
43
+ */
44
+ public static float getAverageForProp(ComputedBorderRadius computedBorderRadius, ComputedBorderRadiusProp prop) {
45
+ if (computedBorderRadius == null) {
46
+ return 0f;
47
+ }
48
+
49
+ CornerRadii borderRadius = computedBorderRadius.get(prop);
50
+ if (borderRadius == null) {
51
+ return 0f;
52
+ }
53
+
54
+ float vertical = borderRadius.getVertical();
55
+ float horizontal = borderRadius.getHorizontal();
56
+ return (vertical + horizontal) / 2f;
57
+ }
58
+ }
@@ -0,0 +1,190 @@
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.ft.sdk.reactnative.sessionreplay.utils;
7
+
8
+ import android.graphics.Canvas;
9
+ import android.graphics.Color;
10
+ import android.graphics.ColorFilter;
11
+ import android.graphics.PixelFormat;
12
+ import android.graphics.drawable.Drawable;
13
+ import android.graphics.drawable.InsetDrawable;
14
+ import android.graphics.drawable.LayerDrawable;
15
+
16
+ import com.ft.sdk.reactnative.sessionreplay.extensions.ComputedBorderRadiusExt;
17
+ import com.ft.sdk.reactnative.sessionreplay.mappers.Pair;
18
+ import com.ft.sdk.reactnative.utils.ColorUtils;
19
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI;
20
+ import com.facebook.react.uimanager.Spacing;
21
+ import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable;
22
+ import com.facebook.react.uimanager.style.ComputedBorderRadius;
23
+ import com.ft.sdk.sessionreplay.model.ShapeBorder;
24
+ import com.ft.sdk.sessionreplay.model.ShapeStyle;
25
+
26
+ public class ReactViewBackgroundDrawableUtils extends DrawableUtils {
27
+ private static final String CSS_BACKGROUND_COLOR_FIELD_NAME = "mColor";
28
+ private static final String CSS_COMPUTED_BORDER_RADIUS_FIELD_NAME = "mComputedBorderRadius";
29
+ private static final String COMPUTED_BORDER_RADIUS_FIELD_NAME = "computedBorderRadius";
30
+ private static final String BACKGROUND_COLOR_FIELD_NAME = "backgroundColor";
31
+ private final ReflectionUtils reflectionUtils;
32
+
33
+
34
+ public ReactViewBackgroundDrawableUtils() {
35
+ this(new ReflectionUtils());
36
+ }
37
+
38
+ public ReactViewBackgroundDrawableUtils(ReflectionUtils reflectionUtils) {
39
+ this.reflectionUtils = reflectionUtils;
40
+ }
41
+
42
+ public static class BackgroundDrawableWrapper extends Drawable {
43
+ public final String backgroundColor;
44
+ public final float cornerRadius;
45
+
46
+ public BackgroundDrawableWrapper(String backgroundColor, float cornerRadius) {
47
+ this.backgroundColor = backgroundColor;
48
+ this.cornerRadius = cornerRadius;
49
+ }
50
+
51
+ @Override
52
+ public void draw(Canvas canvas) {
53
+ }
54
+
55
+ @Override
56
+ public void setAlpha(int alpha) {
57
+ }
58
+
59
+ @Override
60
+ public void setColorFilter(ColorFilter colorFilter) {
61
+ }
62
+
63
+ @Override
64
+ public int getOpacity() {
65
+ return PixelFormat.OPAQUE;
66
+ }
67
+ }
68
+
69
+ @UnstableReactNativeAPI
70
+ @Override
71
+ public Pair<ShapeStyle, ShapeBorder> resolveShapeAndBorder(
72
+ Drawable drawable,
73
+ float opacity,
74
+ float pixelDensity
75
+ ) {
76
+ if (drawable instanceof BackgroundDrawableWrapper) {
77
+ BackgroundDrawableWrapper wrapper = (BackgroundDrawableWrapper) drawable;
78
+ return new Pair<>(
79
+ new ShapeStyle(
80
+ wrapper.backgroundColor,
81
+ opacity,
82
+ wrapper.cornerRadius
83
+ ),
84
+ null
85
+ );
86
+ } else if (drawable instanceof CSSBackgroundDrawable) {
87
+ CSSBackgroundDrawable cssDrawable = (CSSBackgroundDrawable) drawable;
88
+ ShapeBorder borderProps = resolveBorder(cssDrawable, pixelDensity);
89
+ Integer backgroundColor = getCSSBackgroundColor(cssDrawable);
90
+ String colorHexString;
91
+ if (backgroundColor != null) {
92
+ colorHexString = ColorUtils.formatAsRgba(backgroundColor);
93
+ } else {
94
+ return new Pair<>(null, borderProps);
95
+ }
96
+ return new Pair<>(
97
+ new ShapeStyle(
98
+ colorHexString,
99
+ opacity,
100
+ getCSSComputedBorderRadius(cssDrawable) != null ? ComputedBorderRadiusExt.getAverage(getCSSComputedBorderRadius(cssDrawable)) : 0f
101
+ ),
102
+ borderProps
103
+ );
104
+ }
105
+ return new Pair<>(null, null);
106
+ }
107
+
108
+ @UnstableReactNativeAPI
109
+ @Override
110
+ public Drawable getReactBackgroundFromDrawable(Drawable drawable) {
111
+ if (drawable instanceof CSSBackgroundDrawable) {
112
+ return drawable;
113
+ } else if (drawable instanceof InsetDrawable) {
114
+ return getReactBackgroundFromDrawable(((InsetDrawable) drawable).getDrawable());
115
+ } else if (drawable instanceof LayerDrawable) {
116
+ return getDrawableFromLayerDrawable((LayerDrawable) drawable);
117
+ } else {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ @UnstableReactNativeAPI
123
+ private Drawable getDrawableFromLayerDrawable(LayerDrawable layerDrawable) {
124
+ for (int layerNumber = 0; layerNumber < layerDrawable.getNumberOfLayers(); layerNumber++) {
125
+ Drawable layer = layerDrawable.getDrawable(layerNumber);
126
+ if (layer instanceof CSSBackgroundDrawable) {
127
+ return layer;
128
+ } else if (layer != null) {
129
+ if (layer.getClass().getName().equals("com.facebook.react.uimanager.drawable.BackgroundDrawable")) {
130
+ Integer backgroundColor = getBackgroundColor(layer);
131
+ if (backgroundColor == null) backgroundColor = Color.TRANSPARENT;
132
+ ComputedBorderRadius borderRadius = getComputedBorderRadius(layer);
133
+ float cornerRadius = borderRadius != null ? ComputedBorderRadiusExt.getAverage(borderRadius) : 0f;
134
+ return new BackgroundDrawableWrapper(
135
+ ColorUtils.formatAsRgba(backgroundColor),
136
+ cornerRadius
137
+ );
138
+ }
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+
144
+ @UnstableReactNativeAPI
145
+ private ComputedBorderRadius getCSSComputedBorderRadius(CSSBackgroundDrawable drawable) {
146
+ Object value = reflectionUtils.getDeclaredField(
147
+ drawable,
148
+ CSS_COMPUTED_BORDER_RADIUS_FIELD_NAME
149
+ );
150
+ return value instanceof ComputedBorderRadius ? (ComputedBorderRadius) value : null;
151
+ }
152
+
153
+ private ComputedBorderRadius getComputedBorderRadius(Object drawable) {
154
+ Object value = reflectionUtils.getDeclaredField(
155
+ drawable,
156
+ COMPUTED_BORDER_RADIUS_FIELD_NAME
157
+ );
158
+ return value instanceof ComputedBorderRadius ? (ComputedBorderRadius) value : null;
159
+ }
160
+
161
+ @UnstableReactNativeAPI
162
+ private Integer getCSSBackgroundColor(CSSBackgroundDrawable backgroundDrawable) {
163
+ Object value = reflectionUtils.getDeclaredField(
164
+ backgroundDrawable,
165
+ CSS_BACKGROUND_COLOR_FIELD_NAME
166
+ );
167
+ return value instanceof Integer ? (Integer) value : null;
168
+ }
169
+
170
+ private Integer getBackgroundColor(Object backgroundDrawable) {
171
+ Object value = reflectionUtils.getDeclaredField(
172
+ backgroundDrawable,
173
+ BACKGROUND_COLOR_FIELD_NAME
174
+ );
175
+ return value instanceof Integer ? (Integer) value : null;
176
+ }
177
+
178
+ @UnstableReactNativeAPI
179
+ private ShapeBorder resolveBorder(
180
+ CSSBackgroundDrawable backgroundDrawable,
181
+ float pixelDensity
182
+ ) {
183
+ long borderWidth = (long) (backgroundDrawable.getFullBorderWidth() / pixelDensity);
184
+ String borderColor = ColorUtils.formatAsRgba(backgroundDrawable.getBorderColor(Spacing.ALL));
185
+ return new ShapeBorder(
186
+ borderColor,
187
+ borderWidth
188
+ );
189
+ }
190
+ }
@@ -0,0 +1,120 @@
1
+ package com.ft.sdk.reactnative.sessionreplay.utils;
2
+
3
+ import android.graphics.Color;
4
+ import android.graphics.drawable.Drawable;
5
+ import android.graphics.drawable.InsetDrawable;
6
+ import android.graphics.drawable.LayerDrawable;
7
+
8
+ import com.ft.sdk.reactnative.sessionreplay.mappers.Pair;
9
+ import com.ft.sdk.reactnative.utils.ColorUtils;
10
+ import com.facebook.react.uimanager.Spacing;
11
+ import com.facebook.react.views.view.ReactViewBackgroundDrawable;
12
+ import com.ft.sdk.sessionreplay.model.ShapeBorder;
13
+ import com.ft.sdk.sessionreplay.model.ShapeStyle;
14
+
15
+ public class ReactViewBackgroundDrawableUtils extends DrawableUtils {
16
+ private static final String COLOR_FIELD_NAME = "mColor";
17
+ private static final String BORDER_RGB_FIELD_NAME = "mBorderRGB";
18
+ private static final String BORDER_ALPHA_FIELD_NAME = "mBorderAlpha";
19
+ private static final int DEFAULT_BORDER_RGB = 0x00FFFFFF & Color.BLACK;
20
+ private static final int DEFAULT_BORDER_ALPHA = -0x1000000 & Color.BLACK;
21
+ private final ReflectionUtils reflectionUtils;
22
+
23
+ public ReactViewBackgroundDrawableUtils() {
24
+ this(new ReflectionUtils());
25
+ }
26
+
27
+ public ReactViewBackgroundDrawableUtils(ReflectionUtils reflectionUtils) {
28
+ this.reflectionUtils = reflectionUtils;
29
+ }
30
+
31
+ @Override
32
+ public Pair<ShapeStyle, ShapeBorder> resolveShapeAndBorder(
33
+ Drawable drawable,
34
+ float opacity,
35
+ float pixelDensity
36
+ ) {
37
+ if (!(drawable instanceof ReactViewBackgroundDrawable)) {
38
+ return new Pair<>(null, null);
39
+ }
40
+ ReactViewBackgroundDrawable bgDrawable = (ReactViewBackgroundDrawable) drawable;
41
+ ShapeBorder borderProps = resolveBorder(bgDrawable, pixelDensity);
42
+ long cornerRadius = (long) (bgDrawable.getFullBorderRadius() / pixelDensity);
43
+ Integer backgroundColor = getBackgroundColor(bgDrawable);
44
+ String colorHexString;
45
+ if (backgroundColor != null) {
46
+ colorHexString = ColorUtils.formatAsRgba(backgroundColor);
47
+ } else {
48
+ return new Pair<>(null, borderProps);
49
+ }
50
+ return new Pair<>(
51
+ new ShapeStyle(
52
+ colorHexString,
53
+ opacity,
54
+ cornerRadius
55
+ ),
56
+ borderProps
57
+ );
58
+ }
59
+
60
+ @Override
61
+ public Drawable getReactBackgroundFromDrawable(Drawable drawable) {
62
+ if (drawable instanceof ReactViewBackgroundDrawable) {
63
+ return drawable;
64
+ } else if (drawable instanceof InsetDrawable) {
65
+ return getReactBackgroundFromDrawable(((InsetDrawable) drawable).getDrawable());
66
+ } else if (drawable instanceof LayerDrawable) {
67
+ return getDrawableFromLayerDrawable((LayerDrawable) drawable);
68
+ } else {
69
+ return null;
70
+ }
71
+ }
72
+
73
+ private Drawable getDrawableFromLayerDrawable(LayerDrawable layerDrawable) {
74
+ for (int layerNumber = 0; layerNumber < layerDrawable.getNumberOfLayers(); layerNumber++) {
75
+ Drawable layer = layerDrawable.getDrawable(layerNumber);
76
+ if (layer instanceof ReactViewBackgroundDrawable) {
77
+ return layer;
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+
83
+ private ShapeBorder resolveBorder(
84
+ ReactViewBackgroundDrawable backgroundDrawable,
85
+ float pixelDensity
86
+ ) {
87
+ long borderWidth = (long) (backgroundDrawable.getFullBorderWidth() / pixelDensity);
88
+ int borderColorInt = getBorderColor(backgroundDrawable);
89
+ String borderColor = ColorUtils.formatAsRgba(borderColorInt);
90
+ return new ShapeBorder(
91
+ borderColor,
92
+ borderWidth
93
+ );
94
+ }
95
+
96
+ private int getBorderColor(ReactViewBackgroundDrawable backgroundDrawable) {
97
+ Spacing borderRgb = (Spacing) reflectionUtils.getDeclaredField(
98
+ backgroundDrawable,
99
+ BORDER_RGB_FIELD_NAME
100
+ );
101
+ Spacing borderAlpha = (Spacing) reflectionUtils.getDeclaredField(
102
+ backgroundDrawable,
103
+ BORDER_ALPHA_FIELD_NAME
104
+ );
105
+ float rgb = borderRgb != null ? borderRgb.get(Spacing.ALL) : DEFAULT_BORDER_RGB;
106
+ float alpha = borderAlpha != null ? borderAlpha.get(Spacing.ALL) : DEFAULT_BORDER_ALPHA;
107
+ int rgbComponent = 0x00FFFFFF & (int) rgb;
108
+ int alphaComponent = -0x1000000 & ((int) alpha << 24);
109
+ return rgbComponent | alphaComponent;
110
+ }
111
+
112
+ private Integer getBackgroundColor(ReactViewBackgroundDrawable backgroundDrawable) {
113
+ Object value = reflectionUtils.getDeclaredField(
114
+ backgroundDrawable,
115
+ COLOR_FIELD_NAME
116
+ );
117
+ return value instanceof Integer ? (Integer) value : null;
118
+ }
119
+
120
+ }
@@ -3,7 +3,6 @@ package com.ft.sdk.reactnative;
3
3
  import androidx.annotation.NonNull;
4
4
  import androidx.annotation.Nullable;
5
5
 
6
- import com.ft.sdk.reactnative.BuildConfig;
7
6
  import com.facebook.react.BaseReactPackage;
8
7
  import com.facebook.react.bridge.NativeModule;
9
8
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -28,8 +27,8 @@ public class FTMobilePackage extends BaseReactPackage {
28
27
  return new FTTraceModule(reactApplicationContext);
29
28
  case FTRUMImpl.NAME:
30
29
  return new FTRUMModule(reactApplicationContext);
31
- // case FTSessionReplayImpl.NAME:
32
- // return new FTSessionReplayModule(reactApplicationContext);
30
+ case FTSessionReplayImpl.NAME:
31
+ return new FTSessionReplayModule(reactApplicationContext);
33
32
  default:
34
33
  return null;
35
34
  }
@@ -47,7 +46,7 @@ public class FTMobilePackage extends BaseReactPackage {
47
46
  FTRUMImpl.NAME,
48
47
  FTLogImpl.NAME,
49
48
  FTTraceImpl.NAME,
50
- // FTSessionReplayImpl.NAME,
49
+ FTSessionReplayImpl.NAME,
51
50
  };
52
51
  Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
53
52
 
@@ -20,6 +20,7 @@ public class FTMobilePackage implements ReactPackage {
20
20
  modules.add(new FTLogModule(reactContext));
21
21
  modules.add(new FTTraceModule(reactContext));
22
22
  modules.add(new FTRUMModule(reactContext));
23
+ modules.add(new FTSessionReplayModule(reactContext));
23
24
  return modules;
24
25
  }
25
26
 
@@ -165,7 +165,7 @@ RCT_REMAP_METHOD(trackEventFromExtension,
165
165
  }else{
166
166
  resolve(nil);
167
167
  }
168
-
168
+
169
169
  }];
170
170
  }
171
171
  RCT_REMAP_METHOD(shutDown,
@@ -180,4 +180,5 @@ RCT_REMAP_METHOD(clearAllData,
180
180
  [FTMobileAgent clearAllData];
181
181
  resolve(nil);
182
182
  }
183
- @end
183
+ @end
184
+
@@ -0,0 +1,33 @@
1
+ //
2
+ // FTRCTTextViewRecorder.h
3
+ // FTMobileReactNativeSDK
4
+ //
5
+ // Created by hulilei on 2024/9/25.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+ #import <FTMobileSDK/FTSRWireframesBuilder.h>
10
+ #import <React/RCTUIManager.h>
11
+ @class FTViewAttributes,FTViewTreeRecorder;
12
+ NS_ASSUME_NONNULL_BEGIN
13
+
14
+ @interface FTRCTTextViewBuilder : NSObject<FTSRWireframesBuilder>
15
+ @property (nonatomic, strong) FTViewAttributes *attributes;
16
+ @property (nonatomic, assign) CGRect wireframeRect;
17
+ @property (nonatomic, assign) int wireframeID;
18
+ @property (nonatomic, strong) UIColor * backgroundColor;
19
+ @property (nonatomic, assign) NSTextAlignment textAlignment;
20
+ @property (nonatomic, strong) UIColor *textColor;
21
+ @property (nonatomic,assign) CGFloat fontSize;
22
+ @property (nonatomic,assign) CGRect contentRect;
23
+ @property (nonatomic, strong) id<FTSRTextObfuscatingProtocol> textObfuscator;
24
+
25
+ @property (nonatomic, copy) NSString *text;
26
+ @end
27
+
28
+ @interface FTRCTTextViewRecorder : NSObject<FTSRWireframesRecorder>
29
+ @property (nonatomic, copy) NSString *identifier;
30
+ @property (nonatomic,copy) FTTextObfuscator textObfuscator;
31
+ -(instancetype)initWithUIManager:(RCTUIManager *)uiManager;
32
+ @end
33
+ NS_ASSUME_NONNULL_END