@truewatchtech/react-native-session-replay 0.4.1
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/FTSessionReplayReactNative.podspec +50 -0
- package/README.md +33 -0
- package/android/build.gradle +228 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +4 -0
- package/android/gradlew +185 -0
- package/android/gradlew.bat +89 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/AndroidManifestNew.xml +3 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayImpl.java +119 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/NoopTextPropertiesResolver.java +23 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.java +57 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/ShadowNodeWrapper.java +84 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/TextPropertiesResolver.java +20 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/extensions/ReactDrawablesExt.java +155 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/DefaultMapper.java +78 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/Pair.java +11 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactEditTextMapper.java +136 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactNativeImageViewMapper.java +117 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactTextMapper.java +57 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactViewGroupMapper.java +22 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/mappers/ReactViewModalMapper.java +21 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/resources/ReactDrawableCopier.java +35 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/ColorUtils.java +24 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/DrawableUtils.java +34 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactNativeUtils.java +18 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/ReflectionUtils.java +43 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/FabricTextViewUtils.java +69 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/LegacyTextViewUtils.java +97 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/TextViewUtils.java +184 -0
- package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/views/FTPrivacyView.java +113 -0
- package/android/src/newarch/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayModule.java +20 -0
- package/android/src/newarch/java/com/ft/sdk/reactnative/sessionreplay/views/FTPrivacyViewManager.java +87 -0
- package/android/src/oldarch/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayModule.java +25 -0
- package/android/src/oldarch/java/com/ft/sdk/reactnative/sessionreplay/views/FTPrivacyViewManager.java +70 -0
- package/android/src/rn69/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +100 -0
- package/android/src/rn75/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +27 -0
- package/android/src/rn75/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +116 -0
- package/android/src/rn76/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +38 -0
- package/android/src/rn76/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +117 -0
- package/android/src/rn79/java/com/ft/sdk/reactnative/sessionreplay/extensions/LengthPercentageExt.java +38 -0
- package/android/src/rn79/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +132 -0
- package/android/src/rn80/java/com/ft/sdk/reactnative/sessionreplay/extensions/ComputedBorderRadiusExt.java +58 -0
- package/android/src/rn80/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +190 -0
- package/android/src/rnlegacy/java/com/ft/sdk/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.java +120 -0
- package/android/src/rnpost74/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayPackage.java +58 -0
- package/android/src/rnpre74/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayPackage.java +30 -0
- package/ios/FTPrivacyViewFabric.h +22 -0
- package/ios/FTPrivacyViewFabric.mm +84 -0
- package/ios/FTPrivacyViewPaper.h +17 -0
- package/ios/FTPrivacyViewPaper.mm +85 -0
- package/ios/FTRCTFabricWrapper.h +13 -0
- package/ios/FTRCTFabricWrapper.mm +113 -0
- package/ios/FTRCTTextPropertiesWrapper.h +24 -0
- package/ios/FTRCTTextPropertiesWrapper.mm +28 -0
- package/ios/FTRCTTextViewRecorder.h +33 -0
- package/ios/FTRCTTextViewRecorder.m +172 -0
- package/ios/FTReactNativeSessionReplay.h +13 -0
- package/ios/FTReactNativeSessionReplay.mm +85 -0
- package/ios/FTSessionReplayReactNative.xcodeproj/project.pbxproj +304 -0
- package/lib/commonjs/components/SessionReplayView/HideView.js +19 -0
- package/lib/commonjs/components/SessionReplayView/HideView.js.map +1 -0
- package/lib/commonjs/components/SessionReplayView/MaskAllView.js +25 -0
- package/lib/commonjs/components/SessionReplayView/MaskAllView.js.map +1 -0
- package/lib/commonjs/components/SessionReplayView/MaskNoneView.js +23 -0
- package/lib/commonjs/components/SessionReplayView/MaskNoneView.js.map +1 -0
- package/lib/commonjs/components/SessionReplayView/PrivacyView.js +28 -0
- package/lib/commonjs/components/SessionReplayView/PrivacyView.js.map +1 -0
- package/lib/commonjs/components/SessionReplayView/index.js +29 -0
- package/lib/commonjs/components/SessionReplayView/index.js.map +1 -0
- package/lib/commonjs/ft_session_replay.js +69 -0
- package/lib/commonjs/ft_session_replay.js.map +1 -0
- package/lib/commonjs/index.js +50 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/specs/FTPrivacyViewNative.js +29 -0
- package/lib/commonjs/specs/FTPrivacyViewNative.js.map +1 -0
- package/lib/commonjs/specs/FTPrivacyViewNativeComponent.js +10 -0
- package/lib/commonjs/specs/FTPrivacyViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/NativeFTReactNativeSessionReplay.js +10 -0
- package/lib/commonjs/specs/NativeFTReactNativeSessionReplay.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/components/SessionReplayView/HideView.js +12 -0
- package/lib/module/components/SessionReplayView/HideView.js.map +1 -0
- package/lib/module/components/SessionReplayView/MaskAllView.js +18 -0
- package/lib/module/components/SessionReplayView/MaskAllView.js.map +1 -0
- package/lib/module/components/SessionReplayView/MaskNoneView.js +16 -0
- package/lib/module/components/SessionReplayView/MaskNoneView.js.map +1 -0
- package/lib/module/components/SessionReplayView/PrivacyView.js +21 -0
- package/lib/module/components/SessionReplayView/PrivacyView.js.map +1 -0
- package/lib/module/components/SessionReplayView/index.js +23 -0
- package/lib/module/components/SessionReplayView/index.js.map +1 -0
- package/lib/module/ft_session_replay.js +67 -0
- package/lib/module/ft_session_replay.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/specs/FTPrivacyViewNative.js +24 -0
- package/lib/module/specs/FTPrivacyViewNative.js.map +1 -0
- package/lib/module/specs/FTPrivacyViewNativeComponent.js +3 -0
- package/lib/module/specs/FTPrivacyViewNativeComponent.js.map +1 -0
- package/lib/module/specs/NativeFTReactNativeSessionReplay.js +5 -0
- package/lib/module/specs/NativeFTReactNativeSessionReplay.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/components/SessionReplayView/HideView.d.ts +7 -0
- package/lib/typescript/components/SessionReplayView/MaskAllView.d.ts +8 -0
- package/lib/typescript/components/SessionReplayView/MaskNoneView.d.ts +7 -0
- package/lib/typescript/components/SessionReplayView/PrivacyView.d.ts +12 -0
- package/lib/typescript/components/SessionReplayView/index.d.ts +22 -0
- package/lib/typescript/ft_session_replay.d.ts +61 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/specs/FTPrivacyViewNative.d.ts +2 -0
- package/lib/typescript/specs/FTPrivacyViewNativeComponent.d.ts +10 -0
- package/lib/typescript/specs/NativeFTReactNativeSessionReplay.d.ts +11 -0
- package/lib/typescript/types.d.ts +8 -0
- package/package.json +97 -0
- package/scripts/set-ios-rn-version.js +47 -0
- package/src/components/SessionReplayView/HideView.tsx +15 -0
- package/src/components/SessionReplayView/MaskAllView.tsx +35 -0
- package/src/components/SessionReplayView/MaskNoneView.tsx +26 -0
- package/src/components/SessionReplayView/PrivacyView.tsx +40 -0
- package/src/components/SessionReplayView/index.ts +26 -0
- package/src/ft_session_replay.tsx +78 -0
- package/src/index.tsx +19 -0
- package/src/specs/FTPrivacyViewNative.ts +32 -0
- package/src/specs/FTPrivacyViewNativeComponent.ts +14 -0
- package/src/specs/NativeFTReactNativeSessionReplay.ts +13 -0
- package/src/types.ts +9 -0
package/android/src/main/java/com/ft/sdk/reactnative/sessionreplay/utils/text/TextViewUtils.java
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
package com.ft.sdk.reactnative.sessionreplay.utils.text;
|
|
2
|
+
|
|
3
|
+
import android.view.Gravity;
|
|
4
|
+
import android.widget.TextView;
|
|
5
|
+
|
|
6
|
+
import com.ft.sdk.reactnative.sessionreplay.BuildConfig;
|
|
7
|
+
import com.ft.sdk.reactnative.sessionreplay.mappers.Pair;
|
|
8
|
+
import com.ft.sdk.reactnative.sessionreplay.utils.DrawableUtils;
|
|
9
|
+
import com.ft.sdk.reactnative.sessionreplay.utils.ReactViewBackgroundDrawableUtils;
|
|
10
|
+
import com.ft.sdk.reactnative.sessionreplay.utils.ReflectionUtils;
|
|
11
|
+
import com.facebook.react.bridge.ReactContext;
|
|
12
|
+
import com.ft.sdk.sessionreplay.model.Alignment;
|
|
13
|
+
import com.ft.sdk.sessionreplay.model.ShapeBorder;
|
|
14
|
+
import com.ft.sdk.sessionreplay.model.ShapeStyle;
|
|
15
|
+
import com.ft.sdk.sessionreplay.model.TextPosition;
|
|
16
|
+
import com.ft.sdk.sessionreplay.model.TextStyle;
|
|
17
|
+
import com.ft.sdk.sessionreplay.model.TextWireframe;
|
|
18
|
+
import com.ft.sdk.sessionreplay.model.Vertical;
|
|
19
|
+
import com.ft.sdk.sessionreplay.model.Wireframe;
|
|
20
|
+
import com.ft.sdk.sessionreplay.recorder.MappingContext;
|
|
21
|
+
import com.ft.sdk.sessionreplay.utils.InternalLogger;
|
|
22
|
+
|
|
23
|
+
import java.util.ArrayList;
|
|
24
|
+
import java.util.List;
|
|
25
|
+
|
|
26
|
+
public abstract class TextViewUtils {
|
|
27
|
+
protected final ReactContext reactContext;
|
|
28
|
+
protected final DrawableUtils drawableUtils;
|
|
29
|
+
|
|
30
|
+
public TextViewUtils(ReactContext reactContext, DrawableUtils drawableUtils) {
|
|
31
|
+
this.reactContext = reactContext;
|
|
32
|
+
this.drawableUtils = drawableUtils;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public List<Wireframe> mapTextViewToWireframes(
|
|
36
|
+
List<Wireframe> wireframes,
|
|
37
|
+
TextView view,
|
|
38
|
+
MappingContext mappingContext
|
|
39
|
+
) {
|
|
40
|
+
List<Wireframe> result = new ArrayList<>();
|
|
41
|
+
float pixelDensity = mappingContext.getSystemInformation().getScreenDensity();
|
|
42
|
+
for (Wireframe originalWireframe : wireframes) {
|
|
43
|
+
if (!(originalWireframe instanceof TextWireframe)) {
|
|
44
|
+
result.add(originalWireframe);
|
|
45
|
+
} else {
|
|
46
|
+
result.add(addReactNativeProperties(
|
|
47
|
+
(TextWireframe) originalWireframe,
|
|
48
|
+
view,
|
|
49
|
+
pixelDensity
|
|
50
|
+
));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public TextWireframe addReactNativeProperties(
|
|
57
|
+
TextWireframe originalWireframe,
|
|
58
|
+
TextView view,
|
|
59
|
+
float pixelDensity
|
|
60
|
+
) {
|
|
61
|
+
Pair<ShapeStyle, ShapeBorder> shapeAndBorder = resolveShapeStyleAndBorder(view, pixelDensity);
|
|
62
|
+
ShapeStyle shapeStyle = shapeAndBorder != null ? shapeAndBorder.first : originalWireframe.getShapeStyle();
|
|
63
|
+
ShapeBorder border = shapeAndBorder != null ? shapeAndBorder.second : originalWireframe.getBorder();
|
|
64
|
+
|
|
65
|
+
Pair<TextStyle, TextPosition> textStyleAndPosition = resolveTextStyleAndPosition(originalWireframe, view, pixelDensity);
|
|
66
|
+
TextStyle textStyle = textStyleAndPosition != null ? textStyleAndPosition.first : originalWireframe.getTextStyle();
|
|
67
|
+
TextPosition textPosition = textStyleAndPosition != null ? textStyleAndPosition.second : originalWireframe.getTextPosition();
|
|
68
|
+
|
|
69
|
+
// nothing changed, return the original wireframe
|
|
70
|
+
if (shapeStyle == originalWireframe.getShapeStyle()
|
|
71
|
+
&& border == originalWireframe.getBorder()
|
|
72
|
+
&& textStyle == originalWireframe.getTextStyle()
|
|
73
|
+
&& textPosition == originalWireframe.getTextPosition()) {
|
|
74
|
+
return originalWireframe;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return new TextWireframe(
|
|
78
|
+
originalWireframe.getId(),
|
|
79
|
+
originalWireframe.getX(),
|
|
80
|
+
originalWireframe.getY(),
|
|
81
|
+
originalWireframe.getWidth(),
|
|
82
|
+
originalWireframe.getHeight(),
|
|
83
|
+
originalWireframe.getClip(),
|
|
84
|
+
shapeStyle,
|
|
85
|
+
border,
|
|
86
|
+
originalWireframe.getText(),
|
|
87
|
+
textStyle,
|
|
88
|
+
textPosition
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
protected Pair<TextStyle, TextPosition> resolveTextStyleAndPosition(
|
|
93
|
+
TextWireframe originalWireframe,
|
|
94
|
+
TextView view,
|
|
95
|
+
float pixelDensity
|
|
96
|
+
) {
|
|
97
|
+
if (!reactContext.hasActiveReactInstance()) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
TextStyle textStyle = resolveTextStyle(originalWireframe, pixelDensity, view);
|
|
101
|
+
if (textStyle == null) return null;
|
|
102
|
+
Alignment alignment = resolveTextAlignment(view, originalWireframe);
|
|
103
|
+
TextPosition textPosition = new TextPosition(
|
|
104
|
+
originalWireframe.getTextPosition() != null ? originalWireframe.getTextPosition().getPadding()
|
|
105
|
+
: null, alignment
|
|
106
|
+
);
|
|
107
|
+
return new Pair<>(textStyle, textPosition);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected Pair<ShapeStyle, ShapeBorder> resolveShapeStyleAndBorder(
|
|
111
|
+
TextView view,
|
|
112
|
+
float pixelDensity
|
|
113
|
+
) {
|
|
114
|
+
android.graphics.drawable.Drawable backgroundDrawable = drawableUtils.getReactBackgroundFromDrawable(view.getBackground());
|
|
115
|
+
if (backgroundDrawable == null) return null;
|
|
116
|
+
float opacity = view.getAlpha();
|
|
117
|
+
return drawableUtils.resolveShapeAndBorder(backgroundDrawable, opacity, pixelDensity);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected Alignment resolveTextAlignment(
|
|
121
|
+
TextView view,
|
|
122
|
+
TextWireframe textWireframe
|
|
123
|
+
) {
|
|
124
|
+
int gravity = view.getGravity();
|
|
125
|
+
com.ft.sdk.sessionreplay.model.Horizontal horizontal = textWireframe.getTextPosition() != null && textWireframe.getTextPosition().getAlignment() != null ? textWireframe.getTextPosition().getAlignment().getHorizontal() : null;
|
|
126
|
+
Vertical vertical;
|
|
127
|
+
switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
|
|
128
|
+
case Gravity.TOP:
|
|
129
|
+
vertical = Vertical.TOP;
|
|
130
|
+
break;
|
|
131
|
+
case Gravity.CENTER_VERTICAL:
|
|
132
|
+
case Gravity.CENTER:
|
|
133
|
+
vertical = Vertical.CENTER;
|
|
134
|
+
break;
|
|
135
|
+
case Gravity.BOTTOM:
|
|
136
|
+
vertical = Vertical.BOTTOM;
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
vertical = Vertical.TOP;
|
|
140
|
+
}
|
|
141
|
+
return new Alignment(horizontal, vertical);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
protected String resolveFontFamily(String typefaceName) {
|
|
145
|
+
switch (typefaceName) {
|
|
146
|
+
case ROBOTO_TYPEFACE_NAME:
|
|
147
|
+
return SANS_SERIF_FAMILY_NAME;
|
|
148
|
+
case MONOSPACE_FAMILY_NAME:
|
|
149
|
+
return MONOSPACE_FAMILY_NAME;
|
|
150
|
+
case SERIF_FAMILY_NAME:
|
|
151
|
+
return SERIF_FAMILY_NAME;
|
|
152
|
+
default:
|
|
153
|
+
return SANS_SERIF_FAMILY_NAME;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
protected abstract TextStyle resolveTextStyle(
|
|
158
|
+
TextWireframe textWireframe,
|
|
159
|
+
float pixelsDensity,
|
|
160
|
+
TextView view
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
public static final String TEXT_ATTRIBUTES_FIELD_NAME = "mTextAttributes";
|
|
164
|
+
public static final String FONT_FAMILY_FIELD_NAME = "mFontFamily";
|
|
165
|
+
public static final String COLOR_FIELD_NAME = "mColor";
|
|
166
|
+
public static final String IS_COLOR_SET_FIELD_NAME = "mIsColorSet";
|
|
167
|
+
public static final String SPANNED_FIELD_NAME = "mSpanned";
|
|
168
|
+
private static final String ROBOTO_TYPEFACE_NAME = "roboto";
|
|
169
|
+
private static final String SERIF_FAMILY_NAME = "serif";
|
|
170
|
+
private static final String SANS_SERIF_FAMILY_NAME = "roboto, sans-serif";
|
|
171
|
+
public static final String MONOSPACE_FAMILY_NAME = "monospace";
|
|
172
|
+
public static final String RESOLVE_UIMANAGERMODULE_ERROR = "Unable to resolve UIManagerModule";
|
|
173
|
+
public static final String RESOLVE_FABRICFIELD_ERROR = "Unable to resolve field from fabric view";
|
|
174
|
+
public static final String NULL_FABRICFIELD_ERROR = "Null value found when trying to resolve field from fabric view";
|
|
175
|
+
|
|
176
|
+
public static TextViewUtils create(ReactContext reactContext, InternalLogger logger) {
|
|
177
|
+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
178
|
+
return new FabricTextViewUtils(reactContext, logger, new ReactViewBackgroundDrawableUtils());
|
|
179
|
+
} else {
|
|
180
|
+
return new LegacyTextViewUtils(reactContext, logger, new ReflectionUtils(), new ReactViewBackgroundDrawableUtils());
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
4
|
+
* * This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
5
|
+
* * Copyright 2016-Present Datadog, Inc.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
package com.ft.sdk.reactnative.sessionreplay.views;
|
|
9
|
+
|
|
10
|
+
import android.content.Context;
|
|
11
|
+
import com.facebook.react.views.view.ReactViewGroup;
|
|
12
|
+
import com.ft.sdk.sessionreplay.ImagePrivacy;
|
|
13
|
+
import com.ft.sdk.sessionreplay.PrivacyOverrideExtensions;
|
|
14
|
+
import com.ft.sdk.sessionreplay.TextAndInputPrivacy;
|
|
15
|
+
import com.ft.sdk.sessionreplay.TouchPrivacy;
|
|
16
|
+
|
|
17
|
+
public class FTPrivacyView extends ReactViewGroup {
|
|
18
|
+
private TextAndInputPrivacy textAndInputPrivacy;
|
|
19
|
+
private ImagePrivacy imagePrivacy;
|
|
20
|
+
private TouchPrivacy touchPrivacy;
|
|
21
|
+
private boolean hide;
|
|
22
|
+
private String nativeID;
|
|
23
|
+
|
|
24
|
+
public FTPrivacyView(Context context) {
|
|
25
|
+
super(context);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public void setTextAndInputPrivacy(String value) {
|
|
29
|
+
if (value == null || value.isEmpty()) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
switch (value) {
|
|
33
|
+
case "MASK_SENSITIVE_INPUTS":
|
|
34
|
+
this.textAndInputPrivacy = TextAndInputPrivacy.MASK_SENSITIVE_INPUTS;
|
|
35
|
+
break;
|
|
36
|
+
case "MASK_ALL_INPUTS":
|
|
37
|
+
this.textAndInputPrivacy = TextAndInputPrivacy.MASK_ALL_INPUTS;
|
|
38
|
+
break;
|
|
39
|
+
case "MASK_ALL":
|
|
40
|
+
this.textAndInputPrivacy = TextAndInputPrivacy.MASK_ALL;
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
PrivacyOverrideExtensions.setSessionReplayTextAndInputPrivacy(this, this.textAndInputPrivacy);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public void setImagePrivacy(String value) {
|
|
49
|
+
if (value == null || value.isEmpty()) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
switch (value) {
|
|
53
|
+
case "MASK_NON_BUNDLED_ONLY":
|
|
54
|
+
this.imagePrivacy = ImagePrivacy.MASK_LARGE_ONLY;
|
|
55
|
+
break;
|
|
56
|
+
case "MASK_ALL":
|
|
57
|
+
this.imagePrivacy = ImagePrivacy.MASK_ALL;
|
|
58
|
+
break;
|
|
59
|
+
case "MASK_NONE":
|
|
60
|
+
this.imagePrivacy = ImagePrivacy.MASK_NONE;
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
PrivacyOverrideExtensions.setSessionReplayImagePrivacy(this, this.imagePrivacy);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public void setTouchPrivacy(String value) {
|
|
69
|
+
if (value == null || value.isEmpty()) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
switch (value) {
|
|
73
|
+
case "SHOW":
|
|
74
|
+
this.touchPrivacy = TouchPrivacy.SHOW;
|
|
75
|
+
break;
|
|
76
|
+
case "HIDE":
|
|
77
|
+
this.touchPrivacy = TouchPrivacy.HIDE;
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
PrivacyOverrideExtensions.setSessionReplayTouchPrivacy(this, this.touchPrivacy);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public void setHide(boolean value) {
|
|
86
|
+
this.hide = value;
|
|
87
|
+
PrivacyOverrideExtensions.setSessionReplayHidden(this, this.hide);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void setNativeID(String nativeID) {
|
|
91
|
+
this.nativeID = nativeID;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public TextAndInputPrivacy getTextAndInputPrivacy() {
|
|
95
|
+
return textAndInputPrivacy;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public ImagePrivacy getImagePrivacy() {
|
|
99
|
+
return imagePrivacy;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public TouchPrivacy getTouchPrivacy() {
|
|
103
|
+
return touchPrivacy;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public boolean getHide() {
|
|
107
|
+
return hide;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public String getNativeID() {
|
|
111
|
+
return nativeID;
|
|
112
|
+
}
|
|
113
|
+
}
|
package/android/src/newarch/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayModule.java
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.ft.sdk.reactnative.sessionreplay;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise;
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
5
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
7
|
+
|
|
8
|
+
public class FTSessionReplayModule extends NativeFTReactNativeSessionReplaySpec {
|
|
9
|
+
private final FTSessionReplayImpl impl = new FTSessionReplayImpl();
|
|
10
|
+
|
|
11
|
+
public FTSessionReplayModule(ReactApplicationContext reactContext) {
|
|
12
|
+
super(reactContext);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Override
|
|
16
|
+
@ReactMethod
|
|
17
|
+
public void sessionReplayConfig(ReadableMap context, Promise promise) {
|
|
18
|
+
impl.sessionReplayConfig(context, promise, getReactApplicationContext());
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
|
|
4
|
+
* * This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
5
|
+
* * Copyright 2016-Present Datadog, Inc.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
package com.ft.sdk.reactnative.sessionreplay.views;
|
|
9
|
+
|
|
10
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
11
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
12
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
|
13
|
+
import com.facebook.react.uimanager.ViewGroupManager;
|
|
14
|
+
import com.facebook.react.uimanager.ViewManagerDelegate;
|
|
15
|
+
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
16
|
+
import com.facebook.react.viewmanagers.FTPrivacyViewManagerDelegate;
|
|
17
|
+
import com.facebook.react.viewmanagers.FTPrivacyViewManagerInterface;
|
|
18
|
+
|
|
19
|
+
import java.util.HashMap;
|
|
20
|
+
import java.util.Map;
|
|
21
|
+
|
|
22
|
+
public class FTPrivacyViewManager extends ViewGroupManager<FTPrivacyView>
|
|
23
|
+
implements FTPrivacyViewManagerInterface<FTPrivacyView> {
|
|
24
|
+
public static final String REACT_CLASS = "FTPrivacyView";
|
|
25
|
+
|
|
26
|
+
private final FTPrivacyViewManagerDelegate<FTPrivacyView, FTPrivacyViewManager> delegate =
|
|
27
|
+
new FTPrivacyViewManagerDelegate<>(this);
|
|
28
|
+
|
|
29
|
+
public FTPrivacyViewManager(ReactApplicationContext context) {
|
|
30
|
+
super();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Override
|
|
34
|
+
public ViewManagerDelegate<FTPrivacyView> getDelegate() {
|
|
35
|
+
return delegate;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Override
|
|
39
|
+
public String getName() {
|
|
40
|
+
return REACT_CLASS;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Override
|
|
44
|
+
protected FTPrivacyView createViewInstance(ThemedReactContext themedReactContext) {
|
|
45
|
+
return new FTPrivacyView(themedReactContext);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "hide", defaultBoolean = false)
|
|
49
|
+
@Override
|
|
50
|
+
public void setHide(FTPrivacyView view, boolean value) {
|
|
51
|
+
if (view != null) {
|
|
52
|
+
view.setHide(value);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@ReactProp(name = "textAndInputPrivacy")
|
|
57
|
+
@Override
|
|
58
|
+
public void setTextAndInputPrivacy(FTPrivacyView view, String value) {
|
|
59
|
+
if (view != null) {
|
|
60
|
+
view.setTextAndInputPrivacy(value);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@ReactProp(name = "imagePrivacy")
|
|
65
|
+
@Override
|
|
66
|
+
public void setImagePrivacy(FTPrivacyView view, String value) {
|
|
67
|
+
if (view != null) {
|
|
68
|
+
view.setImagePrivacy(value);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@ReactProp(name = "touchPrivacy")
|
|
73
|
+
@Override
|
|
74
|
+
public void setTouchPrivacy(FTPrivacyView view, String value) {
|
|
75
|
+
if (view != null) {
|
|
76
|
+
view.setTouchPrivacy(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@ReactProp(name = "nativeID")
|
|
81
|
+
@Override
|
|
82
|
+
public void setNativeID(FTPrivacyView view, String value) {
|
|
83
|
+
if (view != null) {
|
|
84
|
+
view.setNativeID(value != null ? value : "");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
package/android/src/oldarch/java/com/ft/sdk/reactnative/sessionreplay/FTSessionReplayModule.java
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package com.ft.sdk.reactnative.sessionreplay;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise;
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
5
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
6
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
8
|
+
|
|
9
|
+
public class FTSessionReplayModule extends ReactContextBaseJavaModule {
|
|
10
|
+
private final FTSessionReplayImpl impl = new FTSessionReplayImpl();
|
|
11
|
+
|
|
12
|
+
public FTSessionReplayModule(ReactApplicationContext reactContext) {
|
|
13
|
+
super(reactContext);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Override
|
|
17
|
+
public String getName() {
|
|
18
|
+
return FTSessionReplayImpl.NAME;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@ReactMethod
|
|
22
|
+
public void sessionReplayConfig(ReadableMap context, Promise promise) {
|
|
23
|
+
impl.sessionReplayConfig(context, promise, getReactApplicationContext());
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
|
|
7
|
+
package com.ft.sdk.reactnative.sessionreplay.views;
|
|
8
|
+
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
12
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
|
13
|
+
import com.facebook.react.uimanager.ViewGroupManager;
|
|
14
|
+
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
public class FTPrivacyViewManager extends ViewGroupManager<FTPrivacyView> {
|
|
18
|
+
public static final String REACT_CLASS = "FTPrivacyView";
|
|
19
|
+
|
|
20
|
+
public FTPrivacyViewManager(ReactApplicationContext context) {
|
|
21
|
+
super();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@NonNull
|
|
25
|
+
@Override
|
|
26
|
+
public String getName() {
|
|
27
|
+
return REACT_CLASS;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@NonNull
|
|
31
|
+
@Override
|
|
32
|
+
protected FTPrivacyView createViewInstance(@NonNull ThemedReactContext context) {
|
|
33
|
+
return new FTPrivacyView(context);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@ReactProp(name = "hide", defaultBoolean = false)
|
|
37
|
+
public void setHide(FTPrivacyView view, boolean value) {
|
|
38
|
+
if (view != null) {
|
|
39
|
+
view.setHide(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@ReactProp(name = "textAndInputPrivacy")
|
|
44
|
+
public void setTextAndInputPrivacy(FTPrivacyView view, String value) {
|
|
45
|
+
if (view != null) {
|
|
46
|
+
view.setTextAndInputPrivacy(value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactProp(name = "imagePrivacy")
|
|
51
|
+
public void setImagePrivacy(FTPrivacyView view, String value) {
|
|
52
|
+
if (view != null) {
|
|
53
|
+
view.setImagePrivacy(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@ReactProp(name = "touchPrivacy")
|
|
58
|
+
public void setTouchPrivacy(FTPrivacyView view, String value) {
|
|
59
|
+
if (view != null) {
|
|
60
|
+
view.setTouchPrivacy(value);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@ReactProp(name = "nativeID")
|
|
65
|
+
public void setNativeID(FTPrivacyView view, String value) {
|
|
66
|
+
if (view != null) {
|
|
67
|
+
view.setNativeID(value != null ? value : "");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
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.mappers.Pair;
|
|
13
|
+
import com.ft.sdk.reactnative.sessionreplay.utils.ColorUtils;
|
|
14
|
+
import com.facebook.react.uimanager.Spacing;
|
|
15
|
+
import com.facebook.react.views.view.ReactViewBackgroundDrawable;
|
|
16
|
+
import com.ft.sdk.sessionreplay.model.ShapeBorder;
|
|
17
|
+
import com.ft.sdk.sessionreplay.model.ShapeStyle;
|
|
18
|
+
|
|
19
|
+
public class ReactViewBackgroundDrawableUtils extends DrawableUtils {
|
|
20
|
+
|
|
21
|
+
private static final String COLOR_FIELD_NAME = "mColor";
|
|
22
|
+
|
|
23
|
+
public ReactViewBackgroundDrawableUtils() {
|
|
24
|
+
super();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Override
|
|
28
|
+
public Pair<ShapeStyle, ShapeBorder> resolveShapeAndBorder(
|
|
29
|
+
Drawable drawable,
|
|
30
|
+
float opacity,
|
|
31
|
+
float pixelDensity) {
|
|
32
|
+
if (!(drawable instanceof ReactViewBackgroundDrawable)) {
|
|
33
|
+
return new Pair<>(null, null);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ReactViewBackgroundDrawable backgroundDrawable = (ReactViewBackgroundDrawable) drawable;
|
|
37
|
+
ShapeBorder borderProps = resolveBorder(backgroundDrawable, pixelDensity);
|
|
38
|
+
long cornerRadius = (long) (backgroundDrawable.getFullBorderWidth() / pixelDensity);
|
|
39
|
+
|
|
40
|
+
Integer backgroundColor = getBackgroundColor(backgroundDrawable);
|
|
41
|
+
String colorHexString = null;
|
|
42
|
+
if (backgroundColor != null) {
|
|
43
|
+
colorHexString = ColorUtils.formatAsRgba(backgroundColor);
|
|
44
|
+
} else {
|
|
45
|
+
return new Pair<>(null, borderProps);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ShapeStyle shapeStyle = new ShapeStyle(
|
|
49
|
+
colorHexString,
|
|
50
|
+
opacity,
|
|
51
|
+
cornerRadius
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return new Pair<>(shapeStyle, borderProps);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Override
|
|
58
|
+
public Drawable getReactBackgroundFromDrawable(Drawable drawable) {
|
|
59
|
+
if (drawable instanceof ReactViewBackgroundDrawable) {
|
|
60
|
+
return drawable;
|
|
61
|
+
} else if (drawable instanceof InsetDrawable) {
|
|
62
|
+
return getReactBackgroundFromDrawable(((InsetDrawable) drawable).getDrawable());
|
|
63
|
+
} else if (drawable instanceof LayerDrawable) {
|
|
64
|
+
return getDrawableFromLayerDrawable((LayerDrawable) drawable);
|
|
65
|
+
} else {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private Drawable getDrawableFromLayerDrawable(LayerDrawable layerDrawable) {
|
|
71
|
+
for (int layerNumber = 0; layerNumber < layerDrawable.getNumberOfLayers(); layerNumber++) {
|
|
72
|
+
Drawable layer = layerDrawable.getDrawable(layerNumber);
|
|
73
|
+
if (layer instanceof ReactViewBackgroundDrawable) {
|
|
74
|
+
return layer;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private ShapeBorder resolveBorder(
|
|
81
|
+
ReactViewBackgroundDrawable backgroundDrawable,
|
|
82
|
+
float pixelDensity) {
|
|
83
|
+
long borderWidth = (long) (backgroundDrawable.getFullBorderWidth() / pixelDensity);
|
|
84
|
+
String borderColor = ColorUtils.formatAsRgba(backgroundDrawable.getBorderColor(Spacing.ALL));
|
|
85
|
+
|
|
86
|
+
return new ShapeBorder(
|
|
87
|
+
borderColor,
|
|
88
|
+
borderWidth
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private Integer getBackgroundColor(ReactViewBackgroundDrawable backgroundDrawable) {
|
|
93
|
+
Object result = reflectionUtils.getDeclaredField(backgroundDrawable, COLOR_FIELD_NAME);
|
|
94
|
+
if (result instanceof Integer) {
|
|
95
|
+
return (Integer) result;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
|
|
10
|
+
public final class LengthPercentageExt {
|
|
11
|
+
|
|
12
|
+
private LengthPercentageExt() {
|
|
13
|
+
// Utility class, prevent instantiation
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Gets the radius value from a LengthPercentage, or returns 0f if the LengthPercentage is null.
|
|
18
|
+
*
|
|
19
|
+
* @param lengthPercentage the LengthPercentage to resolve, can be null
|
|
20
|
+
* @param width the width to resolve against
|
|
21
|
+
* @param height the height to resolve against
|
|
22
|
+
* @return the resolved radius value, or 0f if lengthPercentage is null
|
|
23
|
+
*/
|
|
24
|
+
public static float getRadius(LengthPercentage lengthPercentage, float width, float height) {
|
|
25
|
+
return lengthPercentage != null ? lengthPercentage.resolve(width, height) : 0f;
|
|
26
|
+
}
|
|
27
|
+
}
|