-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Android SR for ReactTextView and ReactEditText #569
Conversation
b27e59a
to
a87b2e8
Compare
...ay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextShadowNodeUtils.kt
Outdated
Show resolved
Hide resolved
68aa3f2
to
aef3116
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it's hard to put extensive testing in place here, I believe we should rely on comments to make sure that if we want to revisit this code later we understand exactly what it does.
I've also suggested a few improvements.
Your screenshot also seems to be missing a few use cases, can you add all the examples on the screen?
...ay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextShadowNodeUtils.kt
Outdated
Show resolved
Hide resolved
...ay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextShadowNodeUtils.kt
Outdated
Show resolved
Hide resolved
...lay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt
Outdated
Show resolved
Hide resolved
...lay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt
Outdated
Show resolved
Hide resolved
...lay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt
Outdated
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Outdated
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Outdated
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Outdated
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Outdated
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
...on-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DrawableUtilsTest.kt
Outdated
Show resolved
Hide resolved
...on-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/DrawableUtilsTest.kt
Outdated
Show resolved
Hide resolved
...kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt
Outdated
Show resolved
Hide resolved
...oid/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolverTest.kt
Outdated
Show resolved
Hide resolved
MobileSegment.TextStyle( | ||
family = "Serif", | ||
size = forge.aPositiveLong(), | ||
"#000000" | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's extract this to the ForgeryFactory
, maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll extract this, but I'm a bit concerned that it duplicates logic in the native sdk. I'm wondering if we shouldn't change the visibility of the forgery factories there
4f1fd12
to
8f2601e
Compare
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
...droid/src/main/kotlin/com/datadog/reactnative/sessionreplay/DdSessionReplayImplementation.kt
Show resolved
Hide resolved
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
...android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolver.kt
Outdated
Show resolved
Hide resolved
...lay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt
Outdated
Show resolved
Hide resolved
...lay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/mappers/ReactTextMapper.kt
Outdated
Show resolved
Hide resolved
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Outdated
Show resolved
Hide resolved
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Outdated
Show resolved
Hide resolved
...kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt
Outdated
Show resolved
Hide resolved
...oid/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolverTest.kt
Outdated
Show resolved
Hide resolved
...oid/src/test/kotlin/com/datadog/reactnative/sessionreplay/ReactTextPropertiesResolverTest.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me if @0xnm approves as well.
val padding = textPosition?.padding | ||
val alignment = resolveTextAlignment(view, textWireframe) | ||
|
||
return textWireframe.copy( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you create a copy here ? Couldn't we just resolve all the properties first and then after create the instance ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change to remove the copy in the drawable method and return pairs of values so we only copy the wireframe once. Copying the wireframe at least once is necessary (unless nothing changed in terms of properties), because the initial wireframe comes from the superclass map so it's either to do this or to duplicate the logic.
import java.lang.reflect.Field | ||
|
||
internal class ReflectionUtils { | ||
internal fun getDeclaredField(instance: Any, fieldName: String): Any? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wow...are we going to use reflection ? How many times is this code going to be called ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately yes, since we need the values from the React shadownode. It would be called multiple times for every view
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would test the performances of these methods and see how they could affect the frame rate. These methods are being called on the UIThread and it will be problematic. I would rather have less quality of the replays than affected performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mariusc83 performance benchmark is scheduled after this PR is merged. I agree that performance is more important than quality of replays.
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left some final suggestions and then I think it is good to be merged.
...ain/kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupport.kt
Outdated
Show resolved
Hide resolved
|
||
internal companion object { | ||
internal fun getLogger(): InternalLogger? { | ||
return (Datadog.getInstance() as? FeatureSdkCore)?.internalLogger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is a best way to get a logger, because it has 2 problems:
- it introduces nullability (it can be avoided if we get logger only once when feature is initialized, because it is guaranteed that core will be there at this point and its type is
FeatureSdkCore
) - each call to
Datadog.getInstance
introduces synchronization lock (not a big penalty, but still).
Normally in other features we are passing down the logger instance we got only once (or passing down SDK core instance), and anyway in the code of this module you have InternalLogger
as constructor argument.
But it is not a blocker for me, if it works fine for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this one is on me, I suggested this change.
I wasn't aware of the sync lock, let's watch how much of an impact this has in the perf benchmark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably just peanuts and we shouldn't care about this penalty. But if we have some tracing data, it will be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it back to passing the logger instance
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Show resolved
Hide resolved
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Show resolved
Hide resolved
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Outdated
Show resolved
Hide resolved
...on-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt
Show resolved
Hide resolved
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
...eplay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/ReflectionUtils.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
...kotlin/com/datadog/reactnative/sessionreplay/ReactNativeSessionReplayExtensionSupportTest.kt
Outdated
Show resolved
Hide resolved
1d1850d
to
bdce711
Compare
bdce711
to
7cc8400
Compare
What does this PR do?
Implementation of Android Session Replay for ReactTextView and ReactEditText - "allow" only (masking requires a change on the Android sdk side before it can be implemented here)
Device
Replay
Motivation
Necessary for Session Replay support for Android
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)