@datadog/mobile-react-native-session-replay 2.6.1 → 2.6.3

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 (29) hide show
  1. package/README.md +3 -3
  2. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt +5 -5
  3. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt +5 -29
  4. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt +2 -2
  5. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactEditTextMapper.kt +3 -26
  6. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt +3 -25
  7. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/text/FabricTextViewUtils.kt +74 -0
  8. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/text/LegacyTextViewUtils.kt +118 -0
  9. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/{ReactTextPropertiesResolver.kt → utils/text/TextViewUtils.kt} +60 -96
  10. package/android/src/rn75/kotlin/com/datadog/reactnative/sessionreplay/extensions/LengthPercentageExt.kt +1 -2
  11. package/android/src/rn75/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt +1 -3
  12. package/android/src/rn76/kotlin/com/datadog/reactnative/sessionreplay/extensions/LengthPercentageExt.kt +1 -1
  13. package/android/src/rn76/kotlin/com/datadog/reactnative/sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt +1 -3
  14. package/android/src/rnlegacy/kotlin/com.datadog.reactnative.sessionreplay/utils/ReactViewBackgroundDrawableUtils.kt +2 -7
  15. package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt +3 -17
  16. package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/{ReactTextPropertiesResolverTest.kt → utils/text/TextViewUtilsTest.kt} +171 -38
  17. package/ios/Sources/DdSessionReplay.mm +4 -4
  18. package/ios/Sources/DdSessionReplayImplementation.swift +13 -3
  19. package/ios/Sources/RCTFabricWrapper.h +13 -0
  20. package/ios/Sources/RCTFabricWrapper.mm +120 -0
  21. package/ios/Sources/RCTTextPropertiesWrapper.h +23 -0
  22. package/ios/Sources/RCTTextPropertiesWrapper.mm +28 -0
  23. package/ios/Sources/RCTTextViewRecorder.swift +69 -49
  24. package/ios/Sources/RCTVersion.h +8 -0
  25. package/package.json +5 -3
  26. package/scripts/set-ios-rn-version.js +47 -0
  27. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/NoopTextPropertiesResolver.kt +0 -22
  28. package/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtils.kt +0 -40
  29. package/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/TextViewUtilsTest.kt +0 -109
@@ -38,12 +38,12 @@ RCT_REMAP_METHOD(enable, withEnableReplaySampleRate:(double)replaySampleRate
38
38
 
39
39
  RCT_EXPORT_METHOD(startRecording:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
40
40
  {
41
- [self startRecordingWithResolver:resolve reject:reject];
41
+ [self startRecording:resolve reject:reject];
42
42
  }
43
43
 
44
44
  RCT_EXPORT_METHOD(stopRecording:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
45
45
  {
46
- [self stopRecordingWithResolver:resolve reject:reject];
46
+ [self stopRecording:resolve reject:reject];
47
47
  }
48
48
 
49
49
  // Thanks to this guard, we won't compile this code when we build for the old architecture.
@@ -85,11 +85,11 @@ RCT_EXPORT_METHOD(stopRecording:(RCTPromiseResolveBlock)resolve withRejecter:(RC
85
85
  reject:reject];
86
86
  }
87
87
 
88
- - (void)startRecordingWithResolver:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
88
+ - (void)startRecording:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
89
89
  [self.ddSessionReplayImplementation startRecordingWithResolve:resolve reject:reject];
90
90
  }
91
91
 
92
- - (void)stopRecordingWithResolver:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
92
+ - (void)stopRecording:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
93
93
  [self.ddSessionReplayImplementation stopRecordingWithResolve:resolve reject:reject];
94
94
  }
95
95
 
@@ -15,17 +15,24 @@ public class DdSessionReplayImplementation: NSObject {
15
15
  private lazy var sessionReplay: SessionReplayProtocol = sessionReplayProvider()
16
16
  private let sessionReplayProvider: () -> SessionReplayProtocol
17
17
  private let uiManager: RCTUIManager
18
+ private let fabricWrapper: RCTFabricWrapper
18
19
 
19
- internal init(sessionReplayProvider: @escaping () -> SessionReplayProtocol, uiManager: RCTUIManager) {
20
+ internal init(
21
+ sessionReplayProvider: @escaping () -> SessionReplayProtocol,
22
+ uiManager: RCTUIManager,
23
+ fabricWrapper: RCTFabricWrapper
24
+ ) {
20
25
  self.sessionReplayProvider = sessionReplayProvider
21
26
  self.uiManager = uiManager
27
+ self.fabricWrapper = fabricWrapper
22
28
  }
23
29
 
24
30
  @objc
25
31
  public convenience init(bridge: RCTBridge) {
26
32
  self.init(
27
33
  sessionReplayProvider: { NativeSessionReplay() },
28
- uiManager: bridge.uiManager
34
+ uiManager: bridge.uiManager,
35
+ fabricWrapper: RCTFabricWrapper()
29
36
  )
30
37
  }
31
38
 
@@ -44,6 +51,7 @@ public class DdSessionReplayImplementation: NSObject {
44
51
  if (customEndpoint != "") {
45
52
  customEndpointURL = URL(string: "\(customEndpoint)/api/v2/replay" as String)
46
53
  }
54
+
47
55
  var sessionReplayConfiguration = SessionReplay.Configuration(
48
56
  replaySampleRate: Float(replaySampleRate),
49
57
  textAndInputPrivacyLevel: convertTextAndInputPrivacy(textAndInputPrivacyLevel),
@@ -53,7 +61,9 @@ public class DdSessionReplayImplementation: NSObject {
53
61
  customEndpoint: customEndpointURL
54
62
  )
55
63
 
56
- sessionReplayConfiguration.setAdditionalNodeRecorders([RCTTextViewRecorder(uiManager: self.uiManager)])
64
+ sessionReplayConfiguration.setAdditionalNodeRecorders([
65
+ RCTTextViewRecorder(uiManager: uiManager, fabricWrapper: fabricWrapper)
66
+ ])
57
67
 
58
68
  if let core = DatadogSDKWrapper.shared.getCoreInstance() {
59
69
  sessionReplay.enable(
@@ -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
+ #import <Foundation/Foundation.h>
7
+ #import "RCTTextPropertiesWrapper.h"
8
+
9
+ @interface RCTFabricWrapper : NSObject
10
+
11
+ - (nullable RCTTextPropertiesWrapper*)tryToExtractTextPropertiesFromView:(UIView* _Nonnull)view;
12
+
13
+ @end
@@ -0,0 +1,120 @@
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
+ #import "RCTFabricWrapper.h"
8
+
9
+ #if RCT_NEW_ARCH_ENABLED
10
+ #import "RCTVersion.h"
11
+
12
+ #import <React-RCTFabric/React/RCTParagraphComponentView.h>
13
+ #import <React-RCTFabric/React/RCTConversions.h>
14
+
15
+ #if RCT_VERSION_MINOR > 74
16
+ #import <React-FabricComponents/react/renderer/components/text/ParagraphProps.h>
17
+ #else
18
+ #import <React-Fabric/react/renderer/components/text/ParagraphProps.h>
19
+ #endif
20
+
21
+
22
+ namespace rct = facebook::react;
23
+ #endif
24
+
25
+ @implementation RCTFabricWrapper
26
+ /**
27
+ * Extracts the text properties from the given UIView when the view is of type RCTParagraphComponentView, returns nil otherwise.
28
+ */
29
+ - (nullable RCTTextPropertiesWrapper*)tryToExtractTextPropertiesFromView:(UIView *)view {
30
+ #if RCT_NEW_ARCH_ENABLED
31
+ if (![view isKindOfClass:[RCTParagraphComponentView class]]) {
32
+ return nil;
33
+ }
34
+
35
+ // Cast view to RCTParagraphComponentView
36
+ RCTParagraphComponentView* paragraphComponentView = (RCTParagraphComponentView *)view;
37
+ if (paragraphComponentView == nil) {
38
+ return nil;
39
+ }
40
+
41
+ // Retrieve ParagraphProps from shared pointer
42
+ const rct::ParagraphProps* props = (rct::ParagraphProps*)paragraphComponentView.props.get();
43
+ if (props == nil) {
44
+ return nil;
45
+ }
46
+
47
+ // Extract Attributes
48
+ RCTTextPropertiesWrapper* textPropertiesWrapper = [[RCTTextPropertiesWrapper alloc] init];
49
+ textPropertiesWrapper.text = [RCTFabricWrapper getTextFromView:paragraphComponentView];
50
+ textPropertiesWrapper.contentRect = paragraphComponentView.bounds;
51
+
52
+ rct::TextAttributes textAttributes = props->textAttributes;
53
+ textPropertiesWrapper.alignment = [RCTFabricWrapper getAlignmentFromAttributes:textAttributes];
54
+ textPropertiesWrapper.foregroundColor = [RCTFabricWrapper getForegroundColorFromAttributes:textAttributes];
55
+ textPropertiesWrapper.fontSize = [RCTFabricWrapper getFontSizeFromAttributes:textAttributes];
56
+
57
+ return textPropertiesWrapper;
58
+ #else
59
+ return nil;
60
+ #endif
61
+ }
62
+
63
+ #if RCT_NEW_ARCH_ENABLED
64
+ + (NSString* _Nonnull)getTextFromView:(RCTParagraphComponentView*)view {
65
+ if (view == nil || view.attributedText == nil) {
66
+ return RCTTextPropertiesDefaultText;
67
+ }
68
+
69
+ return view.attributedText.string;
70
+ }
71
+
72
+ + (NSTextAlignment)getAlignmentFromAttributes:(rct::TextAttributes)textAttributes {
73
+ const rct::TextAlignment alignment = textAttributes.alignment.has_value() ?
74
+ textAttributes.alignment.value() :
75
+ rct::TextAlignment::Natural;
76
+
77
+ switch (alignment) {
78
+ case rct::TextAlignment::Natural:
79
+ return NSTextAlignmentNatural;
80
+
81
+ case rct::TextAlignment::Left:
82
+ return NSTextAlignmentLeft;
83
+
84
+ case rct::TextAlignment::Center:
85
+ return NSTextAlignmentCenter;
86
+
87
+ case rct::TextAlignment::Right:
88
+ return NSTextAlignmentRight;
89
+
90
+ case rct::TextAlignment::Justified:
91
+ return NSTextAlignmentJustified;
92
+
93
+ default:
94
+ return RCTTextPropertiesDefaultAlignment;
95
+ }
96
+ }
97
+
98
+ + (UIColor* _Nonnull)getForegroundColorFromAttributes:(rct::TextAttributes)textAttributes {
99
+ @try {
100
+ #if RCT_VERSION_MINOR > 73
101
+ rct::Color color = *textAttributes.foregroundColor;
102
+ UIColor* uiColor = (__bridge UIColor*)color.getUIColor().get();
103
+ if (uiColor != nil) {
104
+ return uiColor;
105
+ }
106
+ #else
107
+ return RCTUIColorFromSharedColor(textAttributes.foregroundColor);
108
+ #endif
109
+ } @catch (NSException *exception) {}
110
+
111
+ return RCTTextPropertiesDefaultForegroundColor;
112
+ }
113
+
114
+ + (CGFloat)getFontSizeFromAttributes:(rct::TextAttributes)textAttributes {
115
+ // Float is just an alias for CGFloat, but this could change in the future.
116
+ _Static_assert(sizeof(rct::Float) == sizeof(CGFloat), "Float and CGFloat are expected to have the same size.");
117
+ return isnan(textAttributes.fontSize) ? RCTTextPropertiesDefaultFontSize : (CGFloat)textAttributes.fontSize;
118
+ }
119
+ #endif
120
+ @end
@@ -0,0 +1,23 @@
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
+ @interface RCTTextPropertiesWrapper : NSObject
8
+
9
+ extern NSString* const RCTTextPropertiesDefaultText;
10
+ extern NSTextAlignment const RCTTextPropertiesDefaultAlignment;
11
+ extern UIColor* const RCTTextPropertiesDefaultForegroundColor;
12
+ extern CGFloat const RCTTextPropertiesDefaultFontSize;
13
+ extern CGRect const RCTTextPropertiesDefaultContentRect;
14
+
15
+ @property (nonatomic, strong, nonnull) NSString* text;
16
+ @property (nonatomic, assign) NSTextAlignment alignment;
17
+ @property (nonatomic, strong, nonnull) UIColor* foregroundColor;
18
+ @property (nonatomic, assign) CGFloat fontSize;
19
+ @property (nonatomic, assign) CGRect contentRect;
20
+
21
+ - (instancetype _Nonnull) init;
22
+
23
+ @end
@@ -0,0 +1,28 @@
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 "RCTTextPropertiesWrapper.h"
7
+
8
+ @implementation RCTTextPropertiesWrapper
9
+
10
+ NSString* const RCTTextPropertiesDefaultText = @"";
11
+ NSTextAlignment const RCTTextPropertiesDefaultAlignment = NSTextAlignmentNatural;
12
+ UIColor* const RCTTextPropertiesDefaultForegroundColor = [UIColor blackColor];
13
+ CGFloat const RCTTextPropertiesDefaultFontSize = 14.0;
14
+ CGRect const RCTTextPropertiesDefaultContentRect = CGRectZero;
15
+
16
+ - (instancetype)init {
17
+ self = [super init];
18
+ if (self) {
19
+ _text = RCTTextPropertiesDefaultText;
20
+ _alignment = RCTTextPropertiesDefaultAlignment;
21
+ _foregroundColor = RCTTextPropertiesDefaultForegroundColor;
22
+ _fontSize = RCTTextPropertiesDefaultFontSize;
23
+ _contentRect = RCTTextPropertiesDefaultContentRect;
24
+ }
25
+ return self;
26
+ }
27
+
28
+ @end
@@ -17,27 +17,11 @@ internal class RCTTextViewRecorder: SessionReplayNodeRecorder {
17
17
  internal var identifier = UUID()
18
18
 
19
19
  internal let uiManager: RCTUIManager
20
+ internal let fabricWrapper: RCTFabricWrapper
20
21
 
21
- internal init(uiManager: RCTUIManager) {
22
+ internal init(uiManager: RCTUIManager, fabricWrapper: RCTFabricWrapper) {
22
23
  self.uiManager = uiManager
23
- }
24
-
25
- internal func extractTextFromSubViews(
26
- subviews: [RCTShadowView]?
27
- ) -> String? {
28
- if let subviews = subviews {
29
- return subviews.compactMap { subview in
30
- if let sub = subview as? RCTRawTextShadowView {
31
- return sub.text
32
- }
33
- if let sub = subview as? RCTVirtualTextShadowView {
34
- // We recursively get all subviews for nested Text components
35
- return extractTextFromSubViews(subviews: sub.reactSubviews())
36
- }
37
- return nil
38
- }.joined()
39
- }
40
- return nil
24
+ self.fabricWrapper = fabricWrapper
41
25
  }
42
26
 
43
27
  public func semantics(
@@ -45,6 +29,48 @@ internal class RCTTextViewRecorder: SessionReplayNodeRecorder {
45
29
  with attributes: SessionReplayViewAttributes,
46
30
  in context: SessionReplayViewTreeRecordingContext
47
31
  ) -> SessionReplayNodeSemantics? {
32
+ guard
33
+ let textProperties = fabricWrapper.tryToExtractTextProperties(from: view) ?? tryToExtractTextProperties(view: view)
34
+ else {
35
+ return view is RCTTextView ? SessionReplayInvisibleElement.constant : nil
36
+ }
37
+
38
+ let builder = RCTTextViewWireframesBuilder(
39
+ wireframeID: context.ids.nodeID(view: view, nodeRecorder: self),
40
+ attributes: attributes,
41
+ text: textProperties.text,
42
+ textAlignment: textProperties.alignment,
43
+ textColor: textProperties.foregroundColor,
44
+ textObfuscator: textObfuscator(context),
45
+ fontSize: textProperties.fontSize,
46
+ contentRect: textProperties.contentRect
47
+ )
48
+
49
+ return SessionReplaySpecificElement(subtreeStrategy: .ignore, nodes: [
50
+ SessionReplayNode(viewAttributes: attributes, wireframesBuilder: builder)
51
+ ])
52
+ }
53
+
54
+ internal func tryToExtractTextFromSubViews(
55
+ subviews: [RCTShadowView]?
56
+ ) -> String? {
57
+ guard let subviews = subviews else {
58
+ return nil
59
+ }
60
+
61
+ return subviews.compactMap { subview in
62
+ if let sub = subview as? RCTRawTextShadowView {
63
+ return sub.text
64
+ }
65
+ if let sub = subview as? RCTVirtualTextShadowView {
66
+ // We recursively get all subviews for nested Text components
67
+ return tryToExtractTextFromSubViews(subviews: sub.reactSubviews())
68
+ }
69
+ return nil
70
+ }.joined()
71
+ }
72
+
73
+ private func tryToExtractTextProperties(view: UIView) -> RCTTextPropertiesWrapper? {
48
74
  guard let textView = view as? RCTTextView else {
49
75
  return nil
50
76
  }
@@ -56,41 +82,35 @@ internal class RCTTextViewRecorder: SessionReplayNodeRecorder {
56
82
  shadowView = uiManager.shadowView(forReactTag: tag) as? RCTTextShadowView
57
83
  }
58
84
 
59
- if let shadow = shadowView {
60
- // TODO: RUM-2173 check performance is ok
61
- let text = extractTextFromSubViews(
62
- subviews: shadow.reactSubviews()
63
- )
85
+ guard let shadow = shadowView else {
86
+ return nil
87
+ }
64
88
 
65
- let builder = RCTTextViewWireframesBuilder(
66
- wireframeID: context.ids.nodeID(view: textView, nodeRecorder: self),
67
- attributes: attributes,
68
- text: text,
69
- textAlignment: shadow.textAttributes.alignment,
70
- textColor: shadow.textAttributes.foregroundColor?.cgColor,
71
- textObfuscator: textObfuscator(context),
72
- fontSize: shadow.textAttributes.fontSize,
73
- contentRect: shadow.contentFrame
74
- )
75
- let node = SessionReplayNode(viewAttributes: attributes, wireframesBuilder: builder)
76
- return SessionReplaySpecificElement(subtreeStrategy: .ignore, nodes: [node])
89
+ let textProperties = RCTTextPropertiesWrapper()
90
+
91
+ // TODO: RUM-2173 check performance is ok
92
+ if let text = tryToExtractTextFromSubViews(subviews: shadow.reactSubviews()) {
93
+ textProperties.text = text
77
94
  }
78
- return SessionReplayInvisibleElement.constant
79
- }
80
- }
81
95
 
82
- // Black color. This is the default for RN: https://github.com/facebook/react-native/blob/a5ee029cd02a636136058d82919480eeeb700067/packages/react-native/Libraries/Text/RCTTextAttributes.mm#L250
83
- let DEFAULT_COLOR = UIColor.black.cgColor
96
+ if let foregroundColor = shadow.textAttributes.foregroundColor {
97
+ textProperties.foregroundColor = foregroundColor
98
+ }
84
99
 
85
- // Default font size for RN: https://github.com/facebook/react-native/blob/16dff523b0a16d7fa9b651062c386885c2f48a6b/packages/react-native/React/Views/RCTFont.mm#L396
86
- let DEFAULT_FONT_SIZE = CGFloat(14)
100
+ textProperties.alignment = shadow.textAttributes.alignment
101
+ textProperties.fontSize = shadow.textAttributes.fontSize
102
+ textProperties.contentRect = shadow.contentFrame
103
+
104
+ return textProperties
105
+ }
106
+ }
87
107
 
88
108
  internal struct RCTTextViewWireframesBuilder: SessionReplayNodeWireframesBuilder {
89
109
  let wireframeID: WireframeID
90
110
  let attributes: SessionReplayViewAttributes
91
- let text: String?
111
+ let text: String
92
112
  var textAlignment: NSTextAlignment
93
- let textColor: CGColor?
113
+ let textColor: UIColor
94
114
  let textObfuscator: SessionReplayTextObfuscating
95
115
  let fontSize: CGFloat
96
116
  let contentRect: CGRect
@@ -140,12 +160,12 @@ internal struct RCTTextViewWireframesBuilder: SessionReplayNodeWireframesBuilder
140
160
  id: wireframeID,
141
161
  frame: relativeIntersectedRect,
142
162
  clip: attributes.clip,
143
- text: textObfuscator.mask(text: text ?? ""),
163
+ text: textObfuscator.mask(text: text),
144
164
  textFrame: textFrame,
145
- // Text alignment is top for all RCTTextView components.
165
+ // Text alignment is top for all RCTTextView and RCTParagraphComponentView components.
146
166
  textAlignment: .init(systemTextAlignment: textAlignment, vertical: .top),
147
- textColor: textColor ?? DEFAULT_COLOR,
148
- fontOverride: SessionReplayWireframesBuilder.FontOverride(size: fontSize.isNaN ? DEFAULT_FONT_SIZE : fontSize),
167
+ textColor: textColor.cgColor,
168
+ fontOverride: SessionReplayWireframesBuilder.FontOverride(size: fontSize.isNaN ? RCTTextPropertiesDefaultFontSize : fontSize),
149
169
  borderColor: attributes.layerBorderColor,
150
170
  borderWidth: attributes.layerBorderWidth,
151
171
  backgroundColor: attributes.backgroundColor,
@@ -0,0 +1,8 @@
1
+ #ifndef RCTVersion_h
2
+ #define RCTVersion_h
3
+
4
+ #define RCT_VERSION_MAJOR 0
5
+ #define RCT_VERSION_MINOR 73
6
+ #define RCT_VERSION_PATCH 9
7
+
8
+ #endif /* RCTVersion_h */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datadog/mobile-react-native-session-replay",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "description": "A client-side React Native module to enable session replay with Datadog",
5
5
  "keywords": [
6
6
  "datadog",
@@ -19,6 +19,7 @@
19
19
  "files": [
20
20
  "src/**",
21
21
  "lib/**",
22
+ "scripts/**",
22
23
  "android/build.gradle",
23
24
  "android/detekt.yml",
24
25
  "android/gradle.properties",
@@ -40,7 +41,8 @@
40
41
  "scripts": {
41
42
  "test": "jest",
42
43
  "lint": "eslint .",
43
- "prepare": "rm -rf lib && yarn bob build"
44
+ "prepare": "rm -rf lib && yarn bob build",
45
+ "postinstall": "node scripts/set-ios-rn-version.js"
44
46
  },
45
47
  "peerDependencies": {
46
48
  "react": ">=16.13.1",
@@ -88,5 +90,5 @@
88
90
  "javaPackageName": "com.datadog.reactnative.sessionreplay"
89
91
  }
90
92
  },
91
- "gitHead": "4ef34c61e03e30d00bb86f7cd3fa255fdc6eed41"
93
+ "gitHead": "1870ee0f82b7773c107dce3b16766526401e7a56"
92
94
  }
@@ -0,0 +1,47 @@
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
+ /* eslint-disable @typescript-eslint/no-var-requires */
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ function getReactNativeVersion() {
11
+ try {
12
+ // eslint-disable-next-line global-require
13
+ return require('react-native/package.json').version;
14
+ } catch (error) {
15
+ throw new Error(
16
+ 'Failed to find React Native. Ensure it is installed in your project.'
17
+ );
18
+ }
19
+ }
20
+
21
+ const rnVersion = getReactNativeVersion();
22
+
23
+ const outputDir = path.resolve(__dirname, '../ios/Sources');
24
+ const outputFile = path.join(outputDir, 'RCTVersion.h');
25
+
26
+ if (!fs.existsSync(outputDir)) {
27
+ fs.mkdirSync(outputDir, { recursive: true });
28
+ }
29
+
30
+ const [major, minor, patch] = rnVersion.split('.').map(Number);
31
+
32
+ const headerContent = `#ifndef RCTVersion_h
33
+ #define RCTVersion_h
34
+
35
+ #define RCT_VERSION_MAJOR ${major || 0}
36
+ #define RCT_VERSION_MINOR ${minor || 0}
37
+ #define RCT_VERSION_PATCH ${patch || 0}
38
+
39
+ #endif /* RCTVersion_h */
40
+ `;
41
+
42
+ try {
43
+ fs.writeFileSync(outputFile, headerContent, 'utf8');
44
+ } catch (error) {
45
+ console.error(`Failed to write RCTVersion.h: ${error.message}`);
46
+ process.exit(1);
47
+ }
@@ -1,22 +0,0 @@
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
-
9
- package com.datadog.reactnative.sessionreplay
10
-
11
- import android.widget.TextView
12
- import com.datadog.android.sessionreplay.model.MobileSegment
13
-
14
- internal class NoopTextPropertiesResolver: TextPropertiesResolver {
15
- override fun addReactNativeProperties(
16
- originalWireframe: MobileSegment.Wireframe.TextWireframe,
17
- view: TextView,
18
- pixelDensity: Float
19
- ): MobileSegment.Wireframe.TextWireframe {
20
- return originalWireframe
21
- }
22
- }
@@ -1,40 +0,0 @@
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
-
9
- package com.datadog.reactnative.sessionreplay.utils
10
-
11
- import android.widget.TextView
12
- import com.datadog.android.sessionreplay.model.MobileSegment
13
- import com.datadog.android.sessionreplay.recorder.MappingContext
14
- import com.datadog.reactnative.sessionreplay.TextPropertiesResolver
15
-
16
- internal class TextViewUtils {
17
- internal fun mapTextViewToWireframes(
18
- wireframes: List<MobileSegment.Wireframe>,
19
- view: TextView,
20
- mappingContext: MappingContext,
21
- reactTextPropertiesResolver: TextPropertiesResolver
22
- ): List<MobileSegment.Wireframe> {
23
- val result = mutableListOf<MobileSegment.Wireframe>()
24
- val pixelDensity = mappingContext.systemInformation.screenDensity
25
-
26
- for (originalWireframe in wireframes) {
27
- if (originalWireframe !is MobileSegment.Wireframe.TextWireframe) {
28
- result.add(originalWireframe)
29
- } else {
30
- result.add(reactTextPropertiesResolver.addReactNativeProperties(
31
- originalWireframe = originalWireframe,
32
- view = view,
33
- pixelDensity = pixelDensity,
34
- ))
35
- }
36
- }
37
-
38
- return result
39
- }
40
- }