From 5e4afc8d4af478776998c40ec4fc68dcb7393f0c Mon Sep 17 00:00:00 2001 From: luyi Date: Thu, 31 Oct 2024 13:34:18 +0100 Subject: [PATCH] Fix CompoundButton mapper drawable clone issue --- .../mapper/CheckableCompoundButtonMapper.kt | 4 +-- .../mapper/CheckableTextViewMapper.kt | 10 ++++++ .../recorder/mapper/CheckedTextViewMapper.kt | 6 +++- .../mapper/BaseCheckableTextViewMapperTest.kt | 33 +++++++------------ 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt index 9efff700b5..6afcca9873 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableCompoundButtonMapper.kt @@ -103,10 +103,10 @@ internal abstract class CheckableCompoundButtonMapper( null } } - return originCheckableDrawable?.let { cloneCheckableDrawable(view, it) } + return originCheckableDrawable } - private fun cloneCheckableDrawable(view: T, drawable: Drawable): Drawable? { + override fun cloneCheckableDrawable(view: T, drawable: Drawable): Drawable? { return drawable.constantState?.newDrawable(view.resources)?.apply { // Set state to make the drawable have correct tint. setState(view.drawableState) diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt index e7968644aa..0398ae7924 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckableTextViewMapper.kt @@ -6,11 +6,13 @@ package com.datadog.android.sessionreplay.internal.recorder.mapper +import android.content.res.Resources import android.graphics.drawable.Drawable import android.widget.Checkable import android.widget.TextView import androidx.annotation.UiThread import com.datadog.android.api.InternalLogger +import com.datadog.android.sessionreplay.internal.recorder.resources.DrawableCopier import com.datadog.android.sessionreplay.model.MobileSegment import com.datadog.android.sessionreplay.recorder.MappingContext import com.datadog.android.sessionreplay.recorder.mapper.TextViewMapper @@ -109,6 +111,11 @@ internal abstract class CheckableTextViewMapper( view, mappingContext.systemInformation.screenDensity ) + val drawableCopier = object : DrawableCopier { + override fun copy(originalDrawable: Drawable, resources: Resources): Drawable? { + return cloneCheckableDrawable(view, it) + } + } mappingContext.imageWireframeHelper.createImageWireframe( view = view, imagePrivacy = mapInputPrivacyToImagePrivacy(mappingContext.textAndInputPrivacy), @@ -117,6 +124,7 @@ internal abstract class CheckableTextViewMapper( y = checkBoxBounds.y, width = it.intrinsicWidth, height = it.intrinsicHeight, + drawableCopier = drawableCopier, drawable = it, shapeStyle = null, border = null, @@ -127,6 +135,8 @@ internal abstract class CheckableTextViewMapper( } } + abstract fun cloneCheckableDrawable(view: T, drawable: Drawable): Drawable? + @UiThread abstract fun getCheckableDrawable(view: T): Drawable? diff --git a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt index 97a5faf820..05222776c7 100644 --- a/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt +++ b/features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/CheckedTextViewMapper.kt @@ -75,7 +75,11 @@ internal open class CheckedTextViewMapper( return (view.checkMarkDrawable?.constantState as? DrawableContainer.DrawableContainerState)?.getChild( checkableDrawableIndex - )?.constantState?.newDrawable(view.resources)?.apply { + ) + } + + override fun cloneCheckableDrawable(view: CheckedTextView, drawable: Drawable): Drawable? { + return drawable.constantState?.newDrawable(view.resources)?.apply { // Set state to make the drawable have correct tint according to the state. setState(view.drawableState) // Set tint list to drawable if the button has declared `checkMarkTint` attribute. diff --git a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt index 4b58f4ec35..a588b28c51 100644 --- a/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt +++ b/features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/internal/recorder/mapper/BaseCheckableTextViewMapperTest.kt @@ -87,9 +87,6 @@ internal abstract class BaseCheckableTextViewMapperTest : @Mock lateinit var mockConstantState: DrawableContainer.DrawableContainerState - @Mock - lateinit var mockCheckedConstantState: DrawableContainer.DrawableContainerState - @IntForgery(min = 0, max = 0xffffff) var fakeCurrentTextColor: Int = 0 @@ -108,35 +105,27 @@ internal abstract class BaseCheckableTextViewMapperTest : @Mock lateinit var mockNotCheckedDrawable: Drawable - @Mock - lateinit var mockClonedDrawable: Drawable - @Mock lateinit var mockDrawableCopier: DrawableCopier @IntForgery - var mockCloneDrawableIntrinsicHeight: Int = 0 + var fakeDrawableIntrinsicHeight: Int = 0 @IntForgery - var mockCloneDrawableIntrinsicWidth: Int = 0 + var fakeDrawableIntrinsicWidth: Int = 0 @Forgery lateinit var fakeImagePrivacy: ImagePrivacy @BeforeEach fun `set up`() { - mockClonedDrawable = mock { - whenever(it.intrinsicHeight) doReturn mockCloneDrawableIntrinsicHeight - whenever(it.intrinsicWidth) doReturn mockCloneDrawableIntrinsicWidth - } - mockCheckedConstantState = mock { - whenever(it.newDrawable(mockResources)) doReturn mockClonedDrawable - } mockCheckedDrawable = mock { - whenever(it.constantState) doReturn mockCheckedConstantState + whenever(it.intrinsicHeight) doReturn fakeDrawableIntrinsicHeight + whenever(it.intrinsicWidth) doReturn fakeDrawableIntrinsicWidth } mockNotCheckedDrawable = mock { - whenever(it.constantState) doReturn mockCheckedConstantState + whenever(it.intrinsicHeight) doReturn fakeDrawableIntrinsicHeight + whenever(it.intrinsicWidth) doReturn fakeDrawableIntrinsicWidth } mockConstantState = mock { whenever(it.getChild(CHECK_BOX_CHECKED_DRAWABLE_INDEX)) doReturn mockCheckedDrawable @@ -226,8 +215,8 @@ internal abstract class BaseCheckableTextViewMapperTest : currentWireframeIndex = anyInt(), x = eq(expectedX), y = eq(expectedY), - width = eq(mockCloneDrawableIntrinsicWidth), - height = eq(mockCloneDrawableIntrinsicHeight), + width = eq(fakeDrawableIntrinsicWidth), + height = eq(fakeDrawableIntrinsicHeight), usePIIPlaceholder = anyBoolean(), drawable = any(), drawableCopier = any(), @@ -270,10 +259,10 @@ internal abstract class BaseCheckableTextViewMapperTest : currentWireframeIndex = anyInt(), x = eq(expectedX), y = eq(expectedY), - width = eq(mockCloneDrawableIntrinsicWidth), - height = eq(mockCloneDrawableIntrinsicHeight), + width = eq(fakeDrawableIntrinsicWidth), + height = eq(fakeDrawableIntrinsicHeight), usePIIPlaceholder = anyBoolean(), - drawable = eq(mockClonedDrawable), + drawable = eq(mockNotCheckedDrawable), drawableCopier = any(), asyncJobStatusCallback = eq(mockAsyncJobStatusCallback), clipping = eq(MobileSegment.WireframeClip()),