-
Notifications
You must be signed in to change notification settings - Fork 23
/
ImageLoading.kt
96 lines (90 loc) · 3.21 KB
/
ImageLoading.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package io.kamel.core
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import io.kamel.core.cache.Cache
import io.kamel.core.config.KamelConfig
import io.kamel.core.config.ResourceConfig
import io.kamel.core.decoder.Decoder
import io.kamel.core.fetcher.Fetcher
import io.kamel.core.mapper.Mapper
import io.kamel.core.utils.findDecoderFor
import io.kamel.core.utils.findFetcherFor
import io.kamel.core.utils.mapInput
import kotlinx.coroutines.flow.*
import kotlin.reflect.KClass
/**
* Loads an [ImageBitmap]. This includes mapping, fetching, decoding and caching the image resource.
* @see Fetcher
* @see Decoder
* @see Mapper
* @see Cache
*/
public fun <I : Any> KamelConfig.loadImageBitmapResource(
data: I,
resourceConfig: ResourceConfig,
dataKClass: KClass<*> = data::class,
): Flow<Resource<ImageBitmap>> = loadResource(data, dataKClass, resourceConfig, imageBitmapCache)
/**
* Loads an [ImageVector]. This includes mapping, fetching, decoding and caching the image resource.
* @see Fetcher
* @see Decoder
* @see Mapper
* @see Cache
*/
public fun KamelConfig.loadImageVectorResource(
data: Any,
resourceConfig: ResourceConfig,
dataKClass: KClass<*> = data::class
): Flow<Resource<ImageVector>> = loadResource(data, dataKClass, resourceConfig, imageVectorCache)
/**
* Loads SVG [Painter]. This includes mapping, fetching, decoding and caching the image resource.
* @see Fetcher
* @see Decoder
* @see Mapper
* @see Cache
*/
public fun KamelConfig.loadSvgResource(
data: Any,
resourceConfig: ResourceConfig,
dataKClass: KClass<*> = data::class
): Flow<Resource<Painter>> = loadResource(data, dataKClass, resourceConfig, svgCache)
private inline fun <reified T : Any> KamelConfig.loadResource(
data: Any,
dataKClass: KClass<*>,
resourceConfig: ResourceConfig,
cache: Cache<Any, T>,
): Flow<Resource<T>> = flow {
val output = mapInput(data, dataKClass)
val cachedData = cache[output]
if (cachedData != null) {
val resource = Resource.Success(cachedData, DataSource.Memory)
emit(resource)
} else {
val fetcher = findFetcherFor(output)
val decoder = findDecoderFor<T>()
val bytesFlow = fetcher.fetch(output, resourceConfig)
val dataFlow = bytesFlow.map { resource ->
resource.map { channel ->
decoder.decode(channel, resourceConfig).also {
cache[output] = it
}
}
}
emitAll(dataFlow)
}
}.catch { emit(Resource.Failure(it)) }
/**
* Loads a cached [ImageBitmap], [ImageVector], or SVG [Painter] from memory. This includes mapping and loading the
* cached image resource. If no resource has been cached for the provided data, `null` is returned.
* @see Mapper
* @see Cache
*/
public fun <T : Any> KamelConfig.loadCachedResourceOrNull(
data: Any,
cache: Cache<Any, T>,
dataKClass: KClass<*> = data::class,
): Resource<T>? {
val output = mapInput(data, dataKClass)
return cache[output]?.let { Resource.Success(it, DataSource.Memory) }
}