Improve page loading progress displaying

This commit is contained in:
Koitharu
2022-11-12 10:28:47 +02:00
parent b599cb33ff
commit c896ac72e8
5 changed files with 62 additions and 41 deletions

View File

@@ -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)
}

View File

@@ -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
}
}
}