Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion android/src/main/java/com/turboimage/TurboImageListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import com.turboimage.events.FailureEvent
import com.turboimage.events.StartEvent
import com.turboimage.events.SuccessEvent

class TurboImageListener(private val view: TurboImageView) : ImageRequest.Listener {
class TurboImageListener(
private val view: TurboImageView,
private val loadSignature: String
) : ImageRequest.Listener {

override fun onStart(request: ImageRequest) {
super.onStart(request)
Expand All @@ -28,6 +31,7 @@ class TurboImageListener(private val view: TurboImageView) : ImageRequest.Listen

override fun onSuccess(request: ImageRequest, result: SuccessResult) {
super.onSuccess(request, result)
view.markLoadSuccess(loadSignature)

val reactContext = view.context as ReactContext
UIManagerHelper.getEventDispatcher(reactContext, view.id)?.let {
Expand All @@ -51,6 +55,7 @@ class TurboImageListener(private val view: TurboImageView) : ImageRequest.Listen

override fun onError(request: ImageRequest, result: ErrorResult) {
super.onError(request, result)
view.markLoadFailure(loadSignature)

val reactContext = view.context as ReactContext
UIManagerHelper.getEventDispatcher(reactContext, view.id)?.let {
Expand Down
59 changes: 59 additions & 0 deletions android/src/main/java/com/turboimage/TurboImageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,65 @@ class TurboImageView(private val reactContext: ThemedReactContext) :
}

var memoryCacheKey: String? = null
private var activeLoadSignature: String? = null
private var lastSuccessfulLoadSignature: String? = null

fun shouldSkipReload(loadSignature: String): Boolean {
return lastSuccessfulLoadSignature == loadSignature
}

fun markLoadStarted(loadSignature: String) {
activeLoadSignature = loadSignature
}

fun markLoadSuccess(loadSignature: String) {
if (activeLoadSignature == loadSignature) {
lastSuccessfulLoadSignature = loadSignature
activeLoadSignature = null
}
}

fun markLoadFailure(loadSignature: String) {
if (activeLoadSignature == loadSignature) {
lastSuccessfulLoadSignature = null
activeLoadSignature = null
}
}

fun resetLoadSignature() {
activeLoadSignature = null
lastSuccessfulLoadSignature = null
}

fun buildLoadSignature(defaultCrossfade: Int): String {
val headersSignature = headers?.names()?.sorted()?.joinToString(",") { name ->
"$name=${headers?.values(name)?.joinToString(";")}"
} ?: ""
val indicatorSignature = indicator.entries.sortedBy { it.key }.joinToString(",") { (key, value) ->
"$key=$value"
}
val viewSizeSignature = if (resize == null) "${width}x${height}" else ""
return listOf(
uri,
headersSignature,
cacheKey,
cachePolicy,
crossfade ?: defaultCrossfade,
blurhash,
thumbhash,
memoryCacheKey,
indicatorSignature,
showPlaceholderOnFailure,
resize,
viewSizeSignature,
rounded,
blur,
monochrome,
tint,
allowHardware,
format
).joinToString("|") { it?.toString() ?: "" }
}

val circleProgressDrawable: CircularProgressDrawable?
get() {
Expand Down
20 changes: 16 additions & 4 deletions android/src/main/java/com/turboimage/TurboImageViewManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,28 @@ class TurboImageViewManager : SimpleViewManager<TurboImageView>(), LifecycleEven

override fun onAfterUpdateTransaction(view: TurboImageView) {
super.onAfterUpdateTransaction(view)
reloadImage(view)
reloadImage(view, force = false)
}

override fun onDropViewInstance(view: TurboImageView) {
super.onDropViewInstance(view)
view.resetLoadSignature()
view.dispose()
}

private fun reloadImage(view: TurboImageView) {
private fun reloadImage(view: TurboImageView, force: Boolean) {
val defaultCrossfade = if (view.thumbhashDrawable != null || view.blurhashDrawable != null) {
0
} else {
CrossfadeDrawable.DEFAULT_DURATION
}
val loadSignature = view.buildLoadSignature(defaultCrossfade)

if (!force && view.shouldSkipReload(loadSignature)) {
return
}

view.markLoadStarted(loadSignature)

val okHttpClient = OkHttpClient.Builder()
.addInterceptor(ProgressInterceptor(object : ProgressListener {
Expand All @@ -86,6 +94,7 @@ class TurboImageViewManager : SimpleViewManager<TurboImageView>(), LifecycleEven
.build()

val imageLoader = Coil.imageLoader(view.context).newBuilder()
.networkObserverEnabled(false)
.respectCacheHeaders(view.cachePolicy == "urlCache")
.okHttpClient(okHttpClient)
.build()
Expand All @@ -97,7 +106,7 @@ class TurboImageViewManager : SimpleViewManager<TurboImageView>(), LifecycleEven
diskCacheKey(it)
}
view.allowHardware?.let { allowHardware(it) }
listener(TurboImageListener(view))
listener(TurboImageListener(view, loadSignature))
view.format?.let {
when (it) {
"svg" -> {
Expand Down Expand Up @@ -253,16 +262,19 @@ class TurboImageViewManager : SimpleViewManager<TurboImageView>(), LifecycleEven

override fun onHostResume() {
if (isInBackground) {
reloadImage(imageView)
reloadImage(imageView, force = true)
isInBackground = false
}
}

override fun onHostPause() {
imageView.resetLoadSignature()
imageView.dispose()
isInBackground = true
}

override fun onHostDestroy() {
imageView.resetLoadSignature()
imageView.dispose()
}
}
Loading