Skip to content

Commit

Permalink
Support loading placeholders in compose previews
Browse files Browse the repository at this point in the history
Composable placeholders already worked, but resource and drawable
placeholders did not. Presumably some part of the production codepath
isn't supported by the Android Studio renderer. The actual display of
the resources seems to work fine, we just never get to that point in
Glide's code. Debugging exactly what's happening seems mostly
impossible. I don't see a way to view logs or debug code running in the
Android Studio preview renderer.

For now we can work around whatever the issue is by rendering resources
and drawables when in preview mode earlier than normal.
  • Loading branch information
sjudd committed Dec 24, 2022
1 parent 2aed37c commit 01ed966
Showing 1 changed file with 38 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.semantics.SemanticsPropertyKey
import androidx.compose.ui.semantics.SemanticsPropertyReceiver
import androidx.compose.ui.semantics.semantics
Expand All @@ -28,6 +29,7 @@ import com.bumptech.glide.integration.ktx.InternalGlideApi
import com.bumptech.glide.integration.ktx.ResolvableGlideSize
import com.bumptech.glide.integration.ktx.Size
import com.bumptech.glide.integration.ktx.Status
import com.google.accompanist.drawablepainter.rememberDrawablePainter

/** Mutates and returns the given [RequestBuilder] to apply relevant options. */
public typealias RequestBuilderTransform<T> = (RequestBuilder<T>) -> RequestBuilder<T>
Expand Down Expand Up @@ -111,6 +113,14 @@ public fun GlideImage(
val overrideSize: Size? = requestBuilder.overrideSize()
val (size, finalModifier) = rememberSizeAndModifier(overrideSize, modifier)

// TODO(judds): It seems like we should be able to use the production paths for
// resource / drawables as well as Composables. It's not totally clear what part of the prod code
// isn't supported.
if (LocalInspectionMode.current && loading?.isResourceOrDrawable() == true) {
PreviewResourceOrDrawable(loading, contentDescription, modifier)
return
}

SizedGlideImage(
requestBuilder = requestBuilder,
size = size,
Expand All @@ -125,6 +135,27 @@ public fun GlideImage(
)
}

@OptIn(ExperimentalGlideComposeApi::class)
@Composable
private fun PreviewResourceOrDrawable(
loading: Placeholder,
contentDescription: String?,
modifier: Modifier,
) {
val drawable =
when(loading) {
is Placeholder.OfDrawable -> loading.drawable
is Placeholder.OfResourceId -> LocalContext.current.getDrawable(loading.resourceId)
is Placeholder.OfComposable ->
throw IllegalArgumentException("Composables should go through the production codepath")
}
Image(
painter = rememberDrawablePainter(drawable),
modifier = modifier,
contentDescription = contentDescription,
)
}

/**
* Used to specify a [Drawable] to use in conjunction with [GlideImage]'s `loading` or `failure`
* parameters.
Expand Down Expand Up @@ -177,6 +208,13 @@ public sealed class Placeholder {
internal class OfResourceId(@DrawableRes internal val resourceId: Int) : Placeholder()
internal class OfComposable(internal val composable: @Composable () -> Unit) : Placeholder()

internal fun isResourceOrDrawable() =
when (this) {
is OfDrawable -> true
is OfResourceId -> true
is OfComposable -> false
}

internal fun maybeComposable(): (@Composable () -> Unit)? =
when (this) {
is OfComposable -> this.composable
Expand Down

0 comments on commit 01ed966

Please sign in to comment.