package expo.modules.divkit import android.content.Context import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri import android.os.Handler import android.os.Looper import android.widget.ImageView import com.squareup.picasso.OkHttp3Downloader import com.squareup.picasso.Picasso import com.squareup.picasso.Target import com.yandex.div.core.images.* class ExpoDivImageLoader( context: Context ) : DivImageLoader { private val appContext = context.applicationContext private val mainHandler = Handler(Looper.getMainLooper()) private val picasso by lazy { createPicasso() } private fun createPicasso(): Picasso { return Picasso.Builder(appContext) .downloader(OkHttp3Downloader(appContext, DISK_CACHE_SIZE)) .build() } override fun loadImage(imageUrl: String, callback: DivImageDownloadCallback): LoadReference { val imageUri = Uri.parse(imageUrl) val target = DownloadCallbackAdapter(imageUri, callback) // Picasso requires starting download on the main thread mainHandler.post { picasso.load(imageUri).into(target) } return LoadReference { picasso.cancelRequest(target) } } override fun loadImage(imageUrl: String, imageView: ImageView): LoadReference { val target = ImageViewAdapter(imageView) picasso.load(Uri.parse(imageUrl)).into(target) return LoadReference { picasso.cancelRequest(target) } } override fun loadImageBytes(imageUrl: String, callback: DivImageDownloadCallback): LoadReference { return loadImage(imageUrl, callback) } private companion object { const val DISK_CACHE_SIZE = 16_777_216L } private inner class DownloadCallbackAdapter( private val imageUri: Uri, private val callback: DivImageDownloadCallback ) : Target { override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { callback.onSuccess(CachedBitmap(bitmap, imageUri, from.toBitmapSource())) } override fun onBitmapFailed(e: Exception, errorDrawable: Drawable?) { callback.onError() } override fun onPrepareLoad(placeHolderDrawable: Drawable?) = Unit } private inner class ImageViewAdapter( private val imageView: ImageView ) : Target { override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) { imageView.setImageBitmap(bitmap) } override fun onBitmapFailed(e: Exception, errorDrawable: Drawable?) = Unit override fun onPrepareLoad(placeHolderDrawable: Drawable?) = Unit } } private fun Picasso.LoadedFrom.toBitmapSource(): BitmapSource { return when (this) { Picasso.LoadedFrom.MEMORY -> BitmapSource.MEMORY Picasso.LoadedFrom.DISK -> BitmapSource.DISK Picasso.LoadedFrom.NETWORK -> BitmapSource.NETWORK } }