/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.react.views.image import androidx.annotation.IntDef import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap import com.facebook.react.uimanager.common.ViewUtil import com.facebook.react.uimanager.events.Event public class ImageLoadEvent private constructor( surfaceId: Int, viewId: Int, @param:ImageEventType private val eventType: Int, private val errorMessage: String? = null, private val sourceUri: String? = null, private val width: Int = 0, private val height: Int = 0, private val loaded: Int = 0, private val total: Int = 0, ) : Event(surfaceId, viewId) { @IntDef(ON_ERROR, ON_LOAD, ON_LOAD_END, ON_LOAD_START, ON_PROGRESS) @Retention(AnnotationRetention.SOURCE) internal annotation class ImageEventType override fun getEventName(): String = eventNameForType(eventType) // Intentionally casting eventType because it is guaranteed to be a short // enough to fit into short. override fun getCoalescingKey(): Short = eventType.toShort() override fun getEventData(): WritableMap = Arguments.createMap().apply { when (eventType) { ON_PROGRESS -> { putInt("loaded", loaded) putInt("total", total) putDouble("progress", loaded / total.toDouble()) } ON_LOAD -> putMap("source", createEventDataSource()) ON_ERROR -> putString("error", errorMessage) } } private fun createEventDataSource(): WritableMap = Arguments.createMap().apply { putString("uri", sourceUri) putDouble("width", width.toDouble()) putDouble("height", height.toDouble()) } public companion object { public const val ON_ERROR: Int = 1 public const val ON_LOAD: Int = 2 public const val ON_LOAD_END: Int = 3 public const val ON_LOAD_START: Int = 4 public const val ON_PROGRESS: Int = 5 @Deprecated( "Use the createLoadStartEvent version that explicitly takes surfaceId as an argument", ReplaceWith("createLoadStartEvent(surfaceId, viewId)"), ) @JvmStatic public fun createLoadStartEvent(viewId: Int): ImageLoadEvent = createLoadStartEvent(ViewUtil.NO_SURFACE_ID, viewId) @Deprecated( "Use the createProgressEvent version that explicitly takes surfaceId as an argument", ReplaceWith("createProgressEvent(surfaceId, viewId, imageUri, loaded, total)"), ) @JvmStatic public fun createProgressEvent( viewId: Int, imageUri: String?, loaded: Int, total: Int, ): ImageLoadEvent = createProgressEvent(ViewUtil.NO_SURFACE_ID, viewId, imageUri, loaded, total) @Deprecated( "Use the createLoadEvent version that explicitly takes surfaceId as an argument", ReplaceWith("createLoadEvent(surfaceId, viewId, imageUri, width, height)"), ) @JvmStatic public fun createLoadEvent( viewId: Int, imageUri: String?, width: Int, height: Int, ): ImageLoadEvent = createLoadEvent(ViewUtil.NO_SURFACE_ID, viewId, imageUri, width, height) @Deprecated( "Use the createErrorEvent version that explicitly takes surfaceId as an argument", ReplaceWith("createErrorEvent(surfaceId, viewId, throwable)"), ) @JvmStatic public fun createErrorEvent(viewId: Int, throwable: Throwable): ImageLoadEvent = createErrorEvent(ViewUtil.NO_SURFACE_ID, viewId, throwable) @Deprecated( "Use the createLoadEndEvent version that explicitly takes surfaceId as an argument", ReplaceWith("createLoadEndEvent(surfaceId, viewId)"), ) @JvmStatic public fun createLoadEndEvent(viewId: Int): ImageLoadEvent = createLoadEndEvent(ViewUtil.NO_SURFACE_ID, viewId) @JvmStatic public fun createLoadStartEvent(surfaceId: Int, viewId: Int): ImageLoadEvent = ImageLoadEvent(surfaceId, viewId, ON_LOAD_START) /** * @param loaded Amount of the image that has been loaded. It should be number of bytes, but * Fresco does not currently provides that information. * @param total Amount that `loaded` will be when the image is fully loaded. */ @JvmStatic public fun createProgressEvent( surfaceId: Int, viewId: Int, imageUri: String?, loaded: Int, total: Int, ): ImageLoadEvent = ImageLoadEvent(surfaceId, viewId, ON_PROGRESS, null, imageUri, 0, 0, loaded, total) @JvmStatic public fun createLoadEvent( surfaceId: Int, viewId: Int, imageUri: String?, width: Int, height: Int, ): ImageLoadEvent = ImageLoadEvent(surfaceId, viewId, ON_LOAD, null, imageUri, width, height, 0, 0) @JvmStatic public fun createErrorEvent(surfaceId: Int, viewId: Int, throwable: Throwable): ImageLoadEvent = ImageLoadEvent(surfaceId, viewId, ON_ERROR, throwable.message, null, 0, 0, 0, 0) @JvmStatic public fun createLoadEndEvent(surfaceId: Int, viewId: Int): ImageLoadEvent = ImageLoadEvent(surfaceId, viewId, ON_LOAD_END) @JvmStatic public fun eventNameForType(@ImageEventType eventType: Int): String = when (eventType) { ON_ERROR -> "topError" ON_LOAD -> "topLoad" ON_LOAD_END -> "topLoadEnd" ON_LOAD_START -> "topLoadStart" ON_PROGRESS -> "topProgress" else -> error("Invalid image event: $eventType") } } }