@@ -7,14 +7,19 @@ import cloud.mindbox.mobile_sdk.R
77import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppImageLoader
88import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppImageSizeStorage
99import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppContentFetchingError
10- import cloud.mindbox.mobile_sdk.logger.mindboxLogD
1110import cloud.mindbox.mobile_sdk.logger.mindboxLogE
11+ import cloud.mindbox.mobile_sdk.logger.mindboxLogI
12+ import cloud.mindbox.mobile_sdk.maxScreenDimension
1213import com.bumptech.glide.Glide
1314import com.bumptech.glide.load.DataSource
15+ import com.bumptech.glide.load.engine.DiskCacheStrategy
1416import com.bumptech.glide.load.engine.GlideException
1517import com.bumptech.glide.request.RequestListener
1618import com.bumptech.glide.request.target.Target
19+ import kotlinx.coroutines.CancellableContinuation
20+ import kotlinx.coroutines.TimeoutCancellationException
1721import kotlinx.coroutines.suspendCancellableCoroutine
22+ import kotlinx.coroutines.withTimeout
1823import kotlin.coroutines.resume
1924import kotlin.coroutines.resumeWithException
2025
@@ -26,53 +31,73 @@ internal class InAppGlideImageLoaderImpl(
2631 private val requests = HashMap <String , Target <Drawable >>()
2732
2833 override suspend fun loadImage (inAppId : String , url : String ): Boolean {
29- mindboxLogD(" loading image for inapp with id $inAppId started" )
30- return suspendCancellableCoroutine { cancellableContinuation ->
31- val target = Glide .with (context).load(url)
32- .timeout(context.getString(R .string.mindbox_inapp_fetching_timeout).toInt())
33- .listener(object :
34- RequestListener <Drawable > {
35- override fun onLoadFailed (
36- e : GlideException ? ,
37- model : Any? ,
38- target : Target <Drawable >? ,
39- isFirstResource : Boolean
40- ): Boolean {
41- return runCatching {
42- mindboxLogD(" loading image with url = $url for inapp with id $inAppId failed" )
43- cancellableContinuation.resumeWithException(InAppContentFetchingError (e))
44- true
45- }.getOrElse {
46- mindboxLogE(
47- " Unknown error when loading image from network failed" ,
48- exception = it
49- )
50- true
51- }
52- }
34+ mindboxLogI(" Loading image for inapp with id $inAppId started" )
35+ val timeoutMs = context.getString(R .string.mindbox_inapp_fetching_timeout).toLong()
36+ val maxDim = context.maxScreenDimension()
37+ return try {
38+ withTimeout(timeoutMs) {
39+ suspendCancellableCoroutine { continuation ->
40+ requests[inAppId] = startPreload(inAppId, url, maxDim, timeoutMs.toInt(), continuation)
41+ continuation.invokeOnCancellation { cancelLoading(inAppId) }
42+ }
43+ }
44+ } catch (e: TimeoutCancellationException ) {
45+ mindboxLogE(" Image loading timed out after ${timeoutMs} ms for inapp $inAppId " , e)
46+ throw InAppContentFetchingError (null )
47+ }
48+ }
49+
50+ private fun startPreload (
51+ inAppId : String ,
52+ url : String ,
53+ maxDim : Int ,
54+ timeoutMs : Int ,
55+ continuation : CancellableContinuation <Boolean >,
56+ ): Target <Drawable > = Glide .with (context)
57+ .load(url)
58+ .timeout(timeoutMs)
59+ .diskCacheStrategy(DiskCacheStrategy .RESOURCE )
60+ .override (maxDim, maxDim)
61+ .centerInside()
62+ .listener(buildRequestListener(inAppId, url, continuation))
63+ .preload(maxDim, maxDim)
64+
65+ private fun buildRequestListener (
66+ inAppId : String ,
67+ url : String ,
68+ continuation : CancellableContinuation <Boolean >,
69+ ): RequestListener <Drawable > = object : RequestListener <Drawable > {
70+
71+ override fun onLoadFailed (
72+ e : GlideException ? ,
73+ model : Any? ,
74+ target : Target <Drawable >? ,
75+ isFirstResource : Boolean ,
76+ ): Boolean {
77+ mindboxLogI(" Image loading failed for inapp $inAppId , url = $url " )
78+ if (continuation.isActive) {
79+ continuation.resumeWithException(InAppContentFetchingError (e))
80+ }
81+ return true
82+ }
5383
54- override fun onResourceReady (
55- resource : Drawable ,
56- model : Any? ,
57- target : Target <Drawable >? ,
58- dataSource : DataSource ? ,
59- isFirstResource : Boolean
60- ): Boolean {
61- return runCatching {
62- mindboxLogD(" loading image with url = $url for inapp with id $inAppId succeeded" )
63- inAppImageSizeStorage.addSize(inAppId, url, resource.toBitmap().width, resource.toBitmap().height)
64- cancellableContinuation.resume(true )
65- true
66- }.getOrElse {
67- mindboxLogE(
68- " Unknown error when loading image from network failed" ,
69- exception = it
70- )
71- true
72- }
73- }
74- }).preload()
75- requests[inAppId] = target
84+ override fun onResourceReady (
85+ resource : Drawable ,
86+ model : Any? ,
87+ target : Target <Drawable >? ,
88+ dataSource : DataSource ? ,
89+ isFirstResource : Boolean ,
90+ ): Boolean {
91+ mindboxLogI(" Image loading succeeded for inapp $inAppId , url = $url " )
92+ if (! continuation.isActive) return true
93+ return runCatching {
94+ val bitmap = resource.toBitmap()
95+ inAppImageSizeStorage.addSize(inAppId, url, bitmap.width, bitmap.height)
96+ continuation.resume(true )
97+ }.onFailure { e ->
98+ mindboxLogE(" Failed to process loaded image for inapp $inAppId " , e)
99+ continuation.resumeWithException(InAppContentFetchingError (null ))
100+ }.isSuccess
76101 }
77102 }
78103
0 commit comments