1 package expo.modules.image 2 3 import com.bumptech.glide.Glide 4 import com.bumptech.glide.load.model.GlideUrl 5 import com.bumptech.glide.request.FutureTarget 6 import com.facebook.react.bridge.Promise 7 import com.facebook.react.bridge.ReactApplicationContext 8 import com.facebook.react.bridge.ReactContextBaseJavaModule 9 import com.facebook.react.bridge.ReactMethod 10 import kotlinx.coroutines.CoroutineScope 11 import kotlinx.coroutines.Dispatchers 12 import kotlinx.coroutines.launch 13 import kotlinx.coroutines.runInterruptible 14 import java.lang.Exception 15 16 /** 17 * We need to convert blocking java.util.concurrent.Future result 18 * into non-blocking suspend function. We use extension function for that 19 */ 20 suspend fun <T> FutureTarget<T>.awaitGet() = runInterruptible(Dispatchers.IO) { get() } 21 22 class ExpoImageModule(val context: ReactApplicationContext) : ReactContextBaseJavaModule(context) { 23 private val moduleCoroutineScope = CoroutineScope(Dispatchers.IO) 24 override fun getName() = "ExpoImageModule" 25 26 @ReactMethod 27 fun prefetch(url: String, promise: Promise) { 28 moduleCoroutineScope.launch { 29 try { 30 val glideUrl = GlideUrl(url) 31 val result = Glide.with(context) 32 .download(glideUrl) 33 .submit() 34 .awaitGet() 35 if (result != null) { 36 promise.resolve(null) 37 } else { 38 promise.reject("ERR_IMAGE_PREFETCH_FAILURE", "Failed to prefetch the image: ${url}.") 39 } 40 } catch (e: Exception) { 41 promise.reject("ERR_IMAGE_PREFETCH_FAILURE", "Failed to prefetch the image: ${e.message}", e) 42 } 43 } 44 } 45 } 46