Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,11 @@ class AsyncImagePainter internal constructor(

return request.newBuilder()
.target(
onStart = { placeholder ->
val painter = placeholder?.asPainter(request.context, filterQuality)
onStart = { placeholder, crossfadeBetweenImages ->
var painter = placeholder?.asPainter(request.context, filterQuality)
if (crossfadeBetweenImages && painter == null && this.painter != null) {
painter = this.painter
}
updateState(State.Loading(painter))
},
)
Expand Down
16 changes: 11 additions & 5 deletions coil-core/api/android/coil-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -692,8 +692,8 @@ public final class coil3/request/ImageRequest$Builder {
public final fun size (Lcoil3/size/Size;)Lcoil3/request/ImageRequest$Builder;
public final fun size (Lcoil3/size/SizeResolver;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lcoil3/target/Target;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcoil3/request/ImageRequest$Builder;
public static synthetic fun target$default (Lcoil3/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcoil3/request/ImageRequest$Builder;
public static synthetic fun target$default (Lcoil3/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcoil3/request/ImageRequest$Builder;
}

public final class coil3/request/ImageRequest$Defaults {
Expand Down Expand Up @@ -764,12 +764,16 @@ public final class coil3/request/ImageRequestsKt {
public static final fun allowConversionToBitmap (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun crossfade (Lcoil3/ImageLoader$Builder;Z)Lcoil3/ImageLoader$Builder;
public static final fun crossfade (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun crossfadeBetweenImages (Lcoil3/ImageLoader$Builder;Z)Lcoil3/ImageLoader$Builder;
public static final fun crossfadeBetweenImages (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/request/ImageRequest;)Z
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/request/Options;)Z
public static final fun getAllowConversionToBitmap (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getAllowConversionToBitmap (Lcoil3/request/ImageRequest;)Z
public static final fun getAllowConversionToBitmap (Lcoil3/request/Options;)Z
public static final fun getCrossfadeBetweenImages (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getCrossfadeBetweenImages (Lcoil3/request/ImageRequest;)Z
public static final fun getMaxBitmapSize (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getMaxBitmapSize (Lcoil3/request/ImageRequest;)Lcoil3/size/Size;
public static final fun getMaxBitmapSize (Lcoil3/request/Options;)Lcoil3/size/Size;
Expand Down Expand Up @@ -1019,12 +1023,13 @@ public abstract class coil3/target/GenericViewTarget : androidx/lifecycle/Defaul
public abstract fun getDrawable ()Landroid/graphics/drawable/Drawable;
public fun onError (Lcoil3/Image;)V
public fun onStart (Landroidx/lifecycle/LifecycleOwner;)V
public fun onStart (Lcoil3/Image;)V
public fun onStart (Lcoil3/Image;Z)V
public fun onStop (Landroidx/lifecycle/LifecycleOwner;)V
public fun onSuccess (Lcoil3/Image;)V
public abstract fun setDrawable (Landroid/graphics/drawable/Drawable;)V
protected final fun updateAnimation ()V
protected final fun updateImage (Lcoil3/Image;)V
protected final fun updateImage (Lcoil3/Image;Z)V
public static synthetic fun updateImage$default (Lcoil3/target/GenericViewTarget;Lcoil3/Image;ZILjava/lang/Object;)V
}

public class coil3/target/ImageViewTarget : coil3/target/GenericViewTarget {
Expand All @@ -1040,7 +1045,8 @@ public class coil3/target/ImageViewTarget : coil3/target/GenericViewTarget {

public abstract interface class coil3/target/Target {
public fun onError (Lcoil3/Image;)V
public fun onStart (Lcoil3/Image;)V
public fun onStart (Lcoil3/Image;Z)V
public static synthetic fun onStart$default (Lcoil3/target/Target;Lcoil3/Image;ZILjava/lang/Object;)V
public fun onSuccess (Lcoil3/Image;)V
}

Expand Down
10 changes: 8 additions & 2 deletions coil-core/api/coil-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ abstract interface coil3.request/Disposable { // coil3.request/Disposable|null[0

abstract interface coil3.target/Target { // coil3.target/Target|null[0]
open fun onError(coil3/Image?) // coil3.target/Target.onError|onError(coil3.Image?){}[0]
open fun onStart(coil3/Image?) // coil3.target/Target.onStart|onStart(coil3.Image?){}[0]
open fun onStart(coil3/Image?, kotlin/Boolean = ...) // coil3.target/Target.onStart|onStart(coil3.Image?;kotlin.Boolean){}[0]
open fun onSuccess(coil3/Image) // coil3.target/Target.onSuccess|onSuccess(coil3.Image){}[0]
}

Expand Down Expand Up @@ -644,7 +644,7 @@ final class coil3.request/ImageRequest { // coil3.request/ImageRequest|null[0]
final fun target(coil3.target/Target?): coil3.request/ImageRequest.Builder // coil3.request/ImageRequest.Builder.target|target(coil3.target.Target?){}[0]
final inline fun <#A2: reified kotlin/Any> fetcherFactory(coil3.fetch/Fetcher.Factory<#A2>): coil3.request/ImageRequest.Builder // coil3.request/ImageRequest.Builder.fetcherFactory|fetcherFactory(coil3.fetch.Fetcher.Factory<0:0>){0§<kotlin.Any>}[0]
final inline fun listener(crossinline kotlin/Function1<coil3.request/ImageRequest, kotlin/Unit> = ..., crossinline kotlin/Function1<coil3.request/ImageRequest, kotlin/Unit> = ..., crossinline kotlin/Function2<coil3.request/ImageRequest, coil3.request/ErrorResult, kotlin/Unit> = ..., crossinline kotlin/Function2<coil3.request/ImageRequest, coil3.request/SuccessResult, kotlin/Unit> = ...): coil3.request/ImageRequest.Builder // coil3.request/ImageRequest.Builder.listener|listener(kotlin.Function1<coil3.request.ImageRequest,kotlin.Unit>;kotlin.Function1<coil3.request.ImageRequest,kotlin.Unit>;kotlin.Function2<coil3.request.ImageRequest,coil3.request.ErrorResult,kotlin.Unit>;kotlin.Function2<coil3.request.ImageRequest,coil3.request.SuccessResult,kotlin.Unit>){}[0]
final inline fun target(crossinline kotlin/Function1<coil3/Image?, kotlin/Unit> = ..., crossinline kotlin/Function1<coil3/Image?, kotlin/Unit> = ..., crossinline kotlin/Function1<coil3/Image, kotlin/Unit> = ...): coil3.request/ImageRequest.Builder // coil3.request/ImageRequest.Builder.target|target(kotlin.Function1<coil3.Image?,kotlin.Unit>;kotlin.Function1<coil3.Image?,kotlin.Unit>;kotlin.Function1<coil3.Image,kotlin.Unit>){}[0]
final inline fun target(crossinline kotlin/Function2<coil3/Image?, kotlin/Boolean, kotlin/Unit> = ..., crossinline kotlin/Function1<coil3/Image?, kotlin/Unit> = ..., crossinline kotlin/Function1<coil3/Image, kotlin/Unit> = ...): coil3.request/ImageRequest.Builder // coil3.request/ImageRequest.Builder.target|target(kotlin.Function2<coil3.Image?,kotlin.Boolean,kotlin.Unit>;kotlin.Function1<coil3.Image?,kotlin.Unit>;kotlin.Function1<coil3.Image,kotlin.Unit>){}[0]
}

final class Defaults { // coil3.request/ImageRequest.Defaults|null[0]
Expand Down Expand Up @@ -1010,6 +1010,10 @@ final val coil3.request/allowConversionToBitmap // coil3.request/allowConversion
final fun (coil3.request/ImageRequest).<get-allowConversionToBitmap>(): kotlin/Boolean // coil3.request/allowConversionToBitmap.<get-allowConversionToBitmap>|<get-allowConversionToBitmap>@coil3.request.ImageRequest(){}[0]
final val coil3.request/allowConversionToBitmap // coil3.request/allowConversionToBitmap|@coil3.request.Options{}allowConversionToBitmap[0]
final fun (coil3.request/Options).<get-allowConversionToBitmap>(): kotlin/Boolean // coil3.request/allowConversionToBitmap.<get-allowConversionToBitmap>|<get-allowConversionToBitmap>@coil3.request.Options(){}[0]
final val coil3.request/crossfadeBetweenImages // coil3.request/crossfadeBetweenImages|@coil3.Extras.Key.Companion{}crossfadeBetweenImages[0]
final fun (coil3/Extras.Key.Companion).<get-crossfadeBetweenImages>(): coil3/Extras.Key<kotlin/Boolean> // coil3.request/crossfadeBetweenImages.<get-crossfadeBetweenImages>|<get-crossfadeBetweenImages>@coil3.Extras.Key.Companion(){}[0]
final val coil3.request/crossfadeBetweenImages // coil3.request/crossfadeBetweenImages|@coil3.request.ImageRequest{}crossfadeBetweenImages[0]
final fun (coil3.request/ImageRequest).<get-crossfadeBetweenImages>(): kotlin/Boolean // coil3.request/crossfadeBetweenImages.<get-crossfadeBetweenImages>|<get-crossfadeBetweenImages>@coil3.request.ImageRequest(){}[0]
final val coil3.request/crossfadeMillis // coil3.request/crossfadeMillis|@coil3.request.ImageRequest{}crossfadeMillis[0]
final fun (coil3.request/ImageRequest).<get-crossfadeMillis>(): kotlin/Int // coil3.request/crossfadeMillis.<get-crossfadeMillis>|<get-crossfadeMillis>@coil3.request.ImageRequest(){}[0]
final val coil3.request/maxBitmapSize // coil3.request/maxBitmapSize|@coil3.Extras.Key.Companion{}maxBitmapSize[0]
Expand All @@ -1035,6 +1039,7 @@ final fun (coil3.request/ImageRequest.Builder).coil3.request/addLastModifiedToFi
final fun (coil3.request/ImageRequest.Builder).coil3.request/allowConversionToBitmap(kotlin/Boolean): coil3.request/ImageRequest.Builder // coil3.request/allowConversionToBitmap|allowConversionToBitmap@coil3.request.ImageRequest.Builder(kotlin.Boolean){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/crossfade(kotlin/Boolean): coil3.request/ImageRequest.Builder // coil3.request/crossfade|crossfade@coil3.request.ImageRequest.Builder(kotlin.Boolean){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/crossfade(kotlin/Int): coil3.request/ImageRequest.Builder // coil3.request/crossfade|crossfade@coil3.request.ImageRequest.Builder(kotlin.Int){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/crossfadeBetweenImages(kotlin/Boolean): coil3.request/ImageRequest.Builder // coil3.request/crossfadeBetweenImages|crossfadeBetweenImages@coil3.request.ImageRequest.Builder(kotlin.Boolean){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/maxBitmapSize(coil3.size/Size): coil3.request/ImageRequest.Builder // coil3.request/maxBitmapSize|maxBitmapSize@coil3.request.ImageRequest.Builder(coil3.size.Size){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/transformations(kotlin.collections/List<coil3.transform/Transformation>): coil3.request/ImageRequest.Builder // coil3.request/transformations|transformations@coil3.request.ImageRequest.Builder(kotlin.collections.List<coil3.transform.Transformation>){}[0]
final fun (coil3.request/ImageRequest.Builder).coil3.request/transformations(kotlin/Array<out coil3.transform/Transformation>...): coil3.request/ImageRequest.Builder // coil3.request/transformations|transformations@coil3.request.ImageRequest.Builder(kotlin.Array<out|coil3.transform.Transformation>...){}[0]
Expand All @@ -1047,6 +1052,7 @@ final fun (coil3/ImageLoader.Builder).coil3.request/addLastModifiedToFileCacheKe
final fun (coil3/ImageLoader.Builder).coil3.request/allowConversionToBitmap(kotlin/Boolean): coil3/ImageLoader.Builder // coil3.request/allowConversionToBitmap|allowConversionToBitmap@coil3.ImageLoader.Builder(kotlin.Boolean){}[0]
final fun (coil3/ImageLoader.Builder).coil3.request/crossfade(kotlin/Boolean): coil3/ImageLoader.Builder // coil3.request/crossfade|crossfade@coil3.ImageLoader.Builder(kotlin.Boolean){}[0]
final fun (coil3/ImageLoader.Builder).coil3.request/crossfade(kotlin/Int): coil3/ImageLoader.Builder // coil3.request/crossfade|crossfade@coil3.ImageLoader.Builder(kotlin.Int){}[0]
final fun (coil3/ImageLoader.Builder).coil3.request/crossfadeBetweenImages(kotlin/Boolean): coil3/ImageLoader.Builder // coil3.request/crossfadeBetweenImages|crossfadeBetweenImages@coil3.ImageLoader.Builder(kotlin.Boolean){}[0]
final fun (coil3/ImageLoader.Builder).coil3.request/maxBitmapSize(coil3.size/Size): coil3/ImageLoader.Builder // coil3.request/maxBitmapSize|maxBitmapSize@coil3.ImageLoader.Builder(coil3.size.Size){}[0]
final fun (coil3/ImageLoader.Builder).coil3/serviceLoaderEnabled(kotlin/Boolean): coil3/ImageLoader.Builder // coil3/serviceLoaderEnabled|serviceLoaderEnabled@coil3.ImageLoader.Builder(kotlin.Boolean){}[0]
final fun (kotlin/String).coil3/toUri(kotlin/String = ...): coil3/Uri // coil3/toUri|toUri@kotlin.String(kotlin.String){}[0]
Expand Down
11 changes: 8 additions & 3 deletions coil-core/api/jvm/coil-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,8 @@ public final class coil3/request/ImageRequest$Builder {
public final fun size (Lcoil3/size/Size;)Lcoil3/request/ImageRequest$Builder;
public final fun size (Lcoil3/size/SizeResolver;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lcoil3/target/Target;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcoil3/request/ImageRequest$Builder;
public static synthetic fun target$default (Lcoil3/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcoil3/request/ImageRequest$Builder;
public final fun target (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lcoil3/request/ImageRequest$Builder;
public static synthetic fun target$default (Lcoil3/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lcoil3/request/ImageRequest$Builder;
}

public final class coil3/request/ImageRequest$Defaults {
Expand Down Expand Up @@ -681,12 +681,16 @@ public final class coil3/request/ImageRequestsKt {
public static final fun allowConversionToBitmap (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun crossfade (Lcoil3/ImageLoader$Builder;Z)Lcoil3/ImageLoader$Builder;
public static final fun crossfade (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun crossfadeBetweenImages (Lcoil3/ImageLoader$Builder;Z)Lcoil3/ImageLoader$Builder;
public static final fun crossfadeBetweenImages (Lcoil3/request/ImageRequest$Builder;Z)Lcoil3/request/ImageRequest$Builder;
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/request/ImageRequest;)Z
public static final fun getAddLastModifiedToFileCacheKey (Lcoil3/request/Options;)Z
public static final fun getAllowConversionToBitmap (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getAllowConversionToBitmap (Lcoil3/request/ImageRequest;)Z
public static final fun getAllowConversionToBitmap (Lcoil3/request/Options;)Z
public static final fun getCrossfadeBetweenImages (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getCrossfadeBetweenImages (Lcoil3/request/ImageRequest;)Z
public static final fun getMaxBitmapSize (Lcoil3/Extras$Key$Companion;)Lcoil3/Extras$Key;
public static final fun getMaxBitmapSize (Lcoil3/request/ImageRequest;)Lcoil3/size/Size;
public static final fun getMaxBitmapSize (Lcoil3/request/Options;)Lcoil3/size/Size;
Expand Down Expand Up @@ -843,7 +847,8 @@ public final class coil3/size/SizeResolverKt {

public abstract interface class coil3/target/Target {
public fun onError (Lcoil3/Image;)V
public fun onStart (Lcoil3/Image;)V
public fun onStart (Lcoil3/Image;Z)V
public static synthetic fun onStart$default (Lcoil3/target/Target;Lcoil3/Image;ZILjava/lang/Object;)V
public fun onSuccess (Lcoil3/Image;)V
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class RealImageLoaderAndroidTest {
.error(error)
.fallback(fallback)
.target(
onStart = { throw IllegalStateException() },
onStart = { _, _ -> throw IllegalStateException() },
onError = { drawable ->
check(drawable === fallback)
hasCalledTargetOnError = true
Expand Down Expand Up @@ -271,9 +271,9 @@ class RealImageLoaderAndroidTest {
.allowHardware(true)
.coroutineContext(EmptyCoroutineContext)
.target(
onStart = {
onStart = { placeholder, _ ->
// The drawable in the memory cache should be returned here.
assertEquals(bitmap, (it as BitmapImage).bitmap)
assertEquals(bitmap, (placeholder as BitmapImage).bitmap)
},
onSuccess = {
// The same drawable should be returned since the drawable is valid for this request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ abstract class GenericViewTarget<T : View> : ViewTarget<T>, TransitionTarget, De
*/
abstract override var drawable: Drawable?

override fun onStart(placeholder: Image?) = updateImage(placeholder)
override fun onStart(placeholder: Image?, crossfadeBetweenImages: Boolean) = updateImage(placeholder, crossfadeBetweenImages)

override fun onError(error: Image?) = updateImage(error)

Expand All @@ -43,8 +43,12 @@ abstract class GenericViewTarget<T : View> : ViewTarget<T>, TransitionTarget, De
}

/** Replace the [ImageView]'s current image with [image]. */
protected fun updateImage(image: Image?) {
val drawable = image?.asDrawable(view.resources)
protected fun updateImage(image: Image?, crossfadeBetweenImages: Boolean = false) {
var drawable = image?.asDrawable(view.resources)
if (drawable == null && crossfadeBetweenImages) {
drawable = this.drawable
}

(this.drawable as? Animatable)?.stop()
this.drawable = drawable
updateAnimation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ class CrossfadeTransitionTest : RobolectricTest() {

private inline fun createTransitionTarget(
imageView: ImageView = ImageView(context),
crossinline onStart: (placeholder: Image?) -> Unit = { fail() },
crossinline onStart: (placeholder: Image?, crossfadeBetweenImages: Boolean) -> Unit = { _, _ -> fail() },
crossinline onError: (error: Image?) -> Unit = { fail() },
crossinline onSuccess: (result: Image) -> Unit = { fail() }
crossinline onSuccess: (result: Image) -> Unit = { fail() },
) = object : TransitionTarget {
override val view = imageView
override val drawable: Drawable? get() = imageView.drawable
override fun onStart(placeholder: Image?) = onStart(placeholder)
override fun onStart(placeholder: Image?, crossfadeBetweenImages: Boolean) = onStart(placeholder, crossfadeBetweenImages)
override fun onError(error: Image?) = onError(error)
override fun onSuccess(result: Image) = onSuccess(result)
}
Expand Down
6 changes: 5 additions & 1 deletion coil-core/src/commonMain/kotlin/coil3/RealImageLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import coil3.request.NullRequestData
import coil3.request.NullRequestDataException
import coil3.request.RequestService
import coil3.request.SuccessResult
import coil3.request.crossfadeBetweenImages
import coil3.target.Target
import coil3.util.ErrorResult
import coil3.util.FetcherServiceLoaderTarget
Expand Down Expand Up @@ -119,7 +120,10 @@ internal class RealImageLoader(

// Set the placeholder on the target.
val cachedPlaceholder = request.placeholderMemoryCacheKey?.let { memoryCache?.get(it)?.image }
request.target?.onStart(placeholder = cachedPlaceholder ?: request.placeholder())
request.target?.onStart(
placeholder = cachedPlaceholder ?: request.placeholder(),
crossfadeBetweenImages = request.crossfadeBetweenImages,
)
eventListener.onStart(request)
request.listener?.onStart(request)

Expand Down
Loading
Loading