Skip to content

Commit

Permalink
Merge pull request #2432 from DataDog/yl/compose/fix-image-regression
Browse files Browse the repository at this point in the history
RUM-6535: Add backwards compatibility for Coil AsyncImage
  • Loading branch information
ambushwork authored Dec 5, 2024
2 parents b204077 + 1f84948 commit 53e3a46
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
-keep class coil.compose.ContentPainterElement {
<fields>;
}
-keep class coil.compose.ContentPainterModifier {
<fields>;
}
-keep class coil.compose.AsyncImagePainter {
<fields>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.datadog.android.api.feature.FeatureSdkCore
import java.lang.reflect.Field
import java.lang.reflect.Method

@Suppress("StringLiteralDuplication")
internal object ComposeReflection {
val WrappedCompositionClass = getClassSafe("androidx.compose.ui.platform.WrappedComposition")

Expand Down Expand Up @@ -64,8 +65,13 @@ internal object ComposeReflection {
val AndroidImageBitmapClass = getClassSafe("androidx.compose.ui.graphics.AndroidImageBitmap")
val BitmapField = AndroidImageBitmapClass?.getDeclaredFieldSafe("bitmap")

val ContentPainterModifierClass = getClassSafe("coil.compose.ContentPainterModifier")
val PainterFieldOfContentPainterModifier =
ContentPainterModifierClass?.getDeclaredFieldSafe("painter")

val ContentPainterElementClass = getClassSafe("coil.compose.ContentPainterElement")
val PainterFieldOfContentPainter = ContentPainterElementClass?.getDeclaredFieldSafe("painter")
val PainterFieldOfContentPainterElement =
ContentPainterElementClass?.getDeclaredFieldSafe("painter")

val AsyncImagePainterClass = getClassSafe("coil.compose.AsyncImagePainter")
val PainterFieldOfAsyncImagePainter = AsyncImagePainterClass?.getDeclaredFieldSafe("_painter")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeRefl
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.BitmapField
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.CompositionField
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.ContentPainterElementClass
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.ContentPainterModifierClass
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.GetInnerLayerCoordinatorMethod
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.ImageField
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.LayoutNodeField
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterElementClass
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterField
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterFieldOfAsyncImagePainter
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterFieldOfContentPainter
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterFieldOfContentPainterElement
import com.datadog.android.sessionreplay.compose.internal.reflection.ComposeReflection.PainterFieldOfContentPainterModifier
import com.datadog.android.sessionreplay.compose.internal.reflection.getSafe

@Suppress("TooManyFunctions")
Expand Down Expand Up @@ -136,12 +138,16 @@ internal class ReflectionUtils {
}

fun getAsyncImagePainter(semanticsNode: SemanticsNode): Painter? {
val modifier = semanticsNode.layoutInfo.getModifierInfo().firstOrNull {
ContentPainterElementClass?.isInstance(it.modifier) == true
}?.modifier
val asyncPainter = PainterFieldOfContentPainter?.getSafe(modifier)
val painter = PainterFieldOfAsyncImagePainter?.getSafe(asyncPainter) as? Painter
return painter
val asyncPainter = semanticsNode.layoutInfo.getModifierInfo().firstNotNullOfOrNull {
if (ContentPainterModifierClass?.isInstance(it.modifier) == true) {
PainterFieldOfContentPainterModifier?.getSafe(it.modifier)
} else if (ContentPainterElementClass?.isInstance(it.modifier) == true) {
PainterFieldOfContentPainterElement?.getSafe(it.modifier)
} else {
null
}
}
return PainterFieldOfAsyncImagePainter?.getSafe(asyncPainter) as? Painter
}

fun getNestedPainter(painter: Painter): Painter? {
Expand Down

0 comments on commit 53e3a46

Please sign in to comment.