Skip to content

Commit

Permalink
Generate test screenshots for coil3
Browse files Browse the repository at this point in the history
Resolves #103
  • Loading branch information
saket committed Nov 6, 2024
1 parent d7ddb78 commit 65e8668
Show file tree
Hide file tree
Showing 21 changed files with 94 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import coil3.asImage
import coil3.gif.AnimatedImageDecoder
import coil3.imageLoader
import coil3.memory.MemoryCache
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
import coil3.request.CachePolicy
import coil3.request.ImageRequest
import coil3.request.SuccessResult
Expand All @@ -51,6 +52,7 @@ import coil3.request.bitmapConfig
import coil3.request.colorSpace
import coil3.request.crossfade
import coil3.request.error
import coil3.serviceLoaderEnabled
import coil3.size.Dimension
import coil3.svg.SvgDecoder
import coil3.test.FakeImageLoaderEngine
Expand Down Expand Up @@ -222,7 +224,9 @@ class Coil3ImageSourceTest {
assertThat(delegate.source.preview).isNotNull()
assertThat(delegate.imageOptions).isEqualTo(
ImageBitmapOptions(
config = ImageBitmapConfig.Rgb565,
// TODO: https://github.com/coil-kt/coil/discussions/2641
//config = ImageBitmapConfig.Rgb565,
config = ImageBitmapConfig.Argb8888,
colorSpace = ColorSpaces.Srgb,
)
)
Expand Down Expand Up @@ -335,11 +339,17 @@ class Coil3ImageSourceTest {
SvgRequestDataParam.RemoteUrl -> serverRule.server.url("emoji.svg").toString()
else -> requestData.data(context)
}

SingletonImageLoader.setUnsafe(
ImageLoader.Builder(context)
// Prevent Coil from auto-adding SvgDecoder because it's present on the classpath.
.serviceLoaderEnabled(false)
.components {
when (decodingState) {
SvgDecodingEnabled -> add(SvgDecoder.Factory())
SvgDecodingEnabled -> {
add(OkHttpNetworkFetcherFactory())
add(SvgDecoder.Factory())
}
SvgDecodingDisabled -> Unit
}
}
Expand Down Expand Up @@ -430,8 +440,11 @@ class Coil3ImageSourceTest {
) = runTest {
SingletonImageLoader.setUnsafe(
ImageLoader.Builder(context)
.components { add(AnimatedImageDecoder.Factory()) } // For GIFs.
.build()
.also { builder ->
// Coil will auto-add AnimatedImageDecoder because it exists on the classpath.
check(builder.components.decoderFactories.any { it is AnimatedImageDecoder.Factory })
}
)

resolve {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import coil3.request.transitionFactory
import coil3.size.Dimension
import coil3.size.Precision
import coil3.size.SizeResolver
import coil3.toAndroidUri
import coil3.transition.CrossfadeTransition
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -160,7 +161,9 @@ internal class Resolver(
}

private sealed interface ImageSourceCreationResult {
data class EligibleForSubSampling(val source: SubSamplingImageSource) : ImageSourceCreationResult
data class EligibleForSubSampling(
val source: SubSamplingImageSource
) : ImageSourceCreationResult

/** Image was deleted from the disk cache, but is still present in the memory cache. */
data object ImageDeletedOnlyFromDiskCache : ImageSourceCreationResult
Expand All @@ -176,7 +179,7 @@ internal class Resolver(
// it is significantly faster than reading from their input streams.
result.diskCacheKey != null -> {
val diskCache = imageLoader.diskCache!!
val snapshot = withContext(Dispatchers.IO) { // IO because openSnapshot() can delete files.
val snapshot = withContext(Dispatchers.IO) { // IO because openSnapshot can delete files.
diskCache.openSnapshot(result.diskCacheKey!!)
}
if (snapshot == null) {
Expand Down Expand Up @@ -211,7 +214,11 @@ internal class Resolver(
} else {
return null
}
return if (source?.canBeSubSampled(request.context) == true) EligibleForSubSampling(source) else null
return if (source?.canBeSubSampled(request.context) == true) {
EligibleForSubSampling(source)
} else {
null
}
}

private fun ImageResult.crossfadeDuration(): Duration {
Expand All @@ -227,10 +234,11 @@ internal class Resolver(
}

private fun ImageRequest.mapRequestDataToUriOrNull(): Uri? {
val dummyOptions = Options(request.context) // Good enough for mappers that only use the context.
val dummyOptions = Options(request.context) // Good enough for mappers that only use Context.
return when (val mapped = imageLoader.components.map(data, dummyOptions)) {
is Uri -> mapped
is File -> Uri.parse(mapped.path)
is coil3.Uri -> mapped.toAndroidUri()
else -> null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import coil3.annotation.ExperimentalCoilApi
import coil3.compose.AsyncImageModelEqualityDelegate
import coil3.compose.LocalAsyncImageModelEqualityDelegate
import coil3.imageLoader
import coil3.request.ImageRequest
import me.saket.telephoto.zoomable.DoubleClickToZoomListener
import me.saket.telephoto.zoomable.ZoomableImage
import me.saket.telephoto.zoomable.ZoomableImageSource
Expand Down Expand Up @@ -126,8 +127,18 @@ private class StableModel(
private val equalityDelegate: AsyncImageModelEqualityDelegate,
) {
override fun equals(other: Any?): Boolean =
equalityDelegate.equals(model, (other as? StableModel)?.model)
equalityDelegate.equalsCompat(model, (other as? StableModel)?.model)

override fun hashCode(): Int =
equalityDelegate.hashCode(model)
}

// TODO: https://github.com/coil-kt/coil/issues/2640
@ExperimentalCoilApi
private fun AsyncImageModelEqualityDelegate.equalsCompat(self: Any?, other: Any?): Boolean {
return if (self !is ImageRequest || other !is ImageRequest) {
self == other
} else {
this.equals(self, other)
}
}

0 comments on commit 65e8668

Please sign in to comment.