Improve page loading progress displaying
This commit is contained in:
@@ -4,7 +4,10 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.ResponseBody
|
||||
import org.koitharu.kotatsu.utils.progress.ProgressResponseBody
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -25,3 +28,7 @@ suspend fun InputStream.copyToSuspending(
|
||||
}
|
||||
bytesCopied
|
||||
}
|
||||
|
||||
fun ResponseBody.withProgress(progressState: MutableStateFlow<Float>): ResponseBody {
|
||||
return ProgressResponseBody(this, progressState)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.koitharu.kotatsu.utils.progress
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.ResponseBody
|
||||
import okio.Buffer
|
||||
import okio.BufferedSource
|
||||
import okio.ForwardingSource
|
||||
import okio.Source
|
||||
import okio.buffer
|
||||
|
||||
class ProgressResponseBody(
|
||||
private val delegate: ResponseBody,
|
||||
private val progressState: MutableStateFlow<Float>,
|
||||
) : ResponseBody() {
|
||||
|
||||
private var bufferedSource: BufferedSource? = null
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
delegate.close()
|
||||
}
|
||||
|
||||
override fun contentLength(): Long = delegate.contentLength()
|
||||
|
||||
override fun contentType(): MediaType? = delegate.contentType()
|
||||
|
||||
override fun source(): BufferedSource {
|
||||
return bufferedSource ?: ProgressSource(delegate.source(), contentLength(), progressState).buffer().also {
|
||||
bufferedSource = it
|
||||
}
|
||||
}
|
||||
|
||||
private class ProgressSource(
|
||||
delegate: Source,
|
||||
private val contentLength: Long,
|
||||
private val progressState: MutableStateFlow<Float>,
|
||||
) : ForwardingSource(delegate) {
|
||||
|
||||
private var totalBytesRead = 0L
|
||||
|
||||
override fun read(sink: Buffer, byteCount: Long): Long {
|
||||
val bytesRead = super.read(sink, byteCount)
|
||||
if (contentLength > 0) {
|
||||
totalBytesRead += if (bytesRead != -1L) bytesRead else 0
|
||||
progressState.value = (totalBytesRead.toDouble() / contentLength.toDouble()).toFloat()
|
||||
}
|
||||
return bytesRead
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user