Retry thumbnails loading after network state changed
This commit is contained in:
@@ -7,6 +7,7 @@ import androidx.annotation.AttrRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil3.ImageLoader
|
||||
import coil3.asImage
|
||||
import coil3.request.Disposable
|
||||
@@ -25,10 +26,14 @@ import coil3.size.ViewSizeResolver
|
||||
import coil3.util.CoilUtils
|
||||
import com.google.android.material.imageview.ShapeableImageView
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.util.ext.decodeRegion
|
||||
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
import org.koitharu.kotatsu.core.util.ext.isNetworkError
|
||||
import java.util.LinkedList
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -42,6 +47,9 @@ open class CoilImageView @JvmOverloads constructor(
|
||||
@Inject
|
||||
lateinit var coil: ImageLoader
|
||||
|
||||
@Inject
|
||||
lateinit var networkState: NetworkState
|
||||
|
||||
var allowRgb565: Boolean = false
|
||||
var useExistingDrawable: Boolean = false
|
||||
var decodeRegion: Boolean = false
|
||||
@@ -54,9 +62,13 @@ open class CoilImageView @JvmOverloads constructor(
|
||||
|
||||
private var currentRequest: Disposable? = null
|
||||
private var currentImageData: Any = NullRequestData
|
||||
private var networkWaitingJob: Job? = null
|
||||
|
||||
private var listeners: MutableList<ImageRequest.Listener>? = null
|
||||
|
||||
val isFailed: Boolean
|
||||
get() = CoilUtils.result(this) is ErrorResult
|
||||
|
||||
init {
|
||||
context.withStyledAttributes(attrs, R.styleable.CoilImageView, defStyleAttr) {
|
||||
allowRgb565 = getBoolean(R.styleable.CoilImageView_allowRgb565, allowRgb565)
|
||||
@@ -81,6 +93,9 @@ open class CoilImageView @JvmOverloads constructor(
|
||||
override fun onError(request: ImageRequest, result: ErrorResult) {
|
||||
super.onError(request, result)
|
||||
listeners?.forEach { it.onError(request, result) }
|
||||
if (result.throwable.isNetworkError()) {
|
||||
waitForNetwork()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart(request: ImageRequest) {
|
||||
@@ -115,17 +130,27 @@ open class CoilImageView @JvmOverloads constructor(
|
||||
)
|
||||
|
||||
fun disposeImage() {
|
||||
networkWaitingJob?.cancel()
|
||||
networkWaitingJob = null
|
||||
CoilUtils.dispose(this)
|
||||
currentRequest = null
|
||||
currentImageData = NullRequestData
|
||||
setImageDrawable(null)
|
||||
}
|
||||
|
||||
protected fun enqueueRequest(request: ImageRequest): Disposable {
|
||||
fun reload() {
|
||||
CoilUtils.result(this)?.let { result ->
|
||||
enqueueRequest(result.request, force = true)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun enqueueRequest(request: ImageRequest, force: Boolean = false): Disposable {
|
||||
val previous = currentRequest
|
||||
if (currentImageData == request.data && previous?.job?.isCancelled == false) {
|
||||
if (!force && currentImageData == request.data && previous?.job?.isCancelled == false && !isFailed) {
|
||||
return previous
|
||||
}
|
||||
networkWaitingJob?.cancel()
|
||||
networkWaitingJob = null
|
||||
currentImageData = request.data
|
||||
return coil.enqueue(request).also { currentRequest = it }
|
||||
}
|
||||
@@ -175,4 +200,17 @@ open class CoilImageView @JvmOverloads constructor(
|
||||
} else {
|
||||
Scale.FIT
|
||||
}
|
||||
|
||||
private fun waitForNetwork() {
|
||||
if (networkWaitingJob?.isActive == true || networkState.isOnline()) {
|
||||
return
|
||||
}
|
||||
networkWaitingJob?.cancel()
|
||||
networkWaitingJob = findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
|
||||
networkState.awaitForConnection()
|
||||
if (isFailed) {
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
|
||||
import org.koitharu.kotatsu.scrobbling.common.domain.ScrobblerAuthRequiredException
|
||||
import java.io.File
|
||||
import java.net.ConnectException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.NoRouteToHostException
|
||||
import java.net.SocketException
|
||||
import java.net.SocketTimeoutException
|
||||
@@ -216,6 +217,7 @@ fun Throwable.isNetworkError(): Boolean {
|
||||
|| this is SocketTimeoutException
|
||||
|| this is StreamResetException
|
||||
|| this is SocketException
|
||||
|| this is HttpException && response.code == HttpURLConnection.HTTP_GATEWAY_TIMEOUT
|
||||
}
|
||||
|
||||
fun Throwable.report(silent: Boolean = false) {
|
||||
|
||||
Reference in New Issue
Block a user