Check if page file valid before page display

pull/377/head
Koitharu 3 years ago
parent 12d8d3e2d1
commit 02d5dfb375
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -26,6 +26,8 @@ fun File.takeIfReadable() = takeIf { it.exists() && it.canRead() }
fun File.takeIfWriteable() = takeIf { it.exists() && it.canWrite() }
fun File.isNotEmpty() = length() != 0L
fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().use {
it.readText()
}

@ -87,3 +87,6 @@ fun Throwable.isWebViewUnavailable(): Boolean {
return (this is AndroidRuntimeException && message?.contains("WebView") == true) ||
cause?.isWebViewUnavailable() == true
}
@Suppress("FunctionName")
fun NoSpaceLeftException() = IOException(MSG_NO_SPACE_LEFT)

@ -1,6 +1,7 @@
package org.koitharu.kotatsu.local.data
import android.content.Context
import android.os.StatFs
import com.tomclaw.cache.DiskLruCache
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
@ -33,7 +34,8 @@ class PagesCache @Inject constructor(@ApplicationContext context: Context) {
}
private val lruCache = SuspendLazy {
val dir = cacheDir.get()
val size = FileSize.MEGABYTES.convert(200, FileSize.BYTES)
val availableSize = getAvailableSizeMb()
val size = SIZE_DEFAULT.coerceIn(SIZE_MIN, availableSize)
runCatchingCancellable {
DiskLruCache.create(dir, size)
}.recoverCatching { error ->
@ -63,4 +65,20 @@ class PagesCache @Inject constructor(@ApplicationContext context: Context) {
file.delete()
}
}
private suspend fun getAvailableSizeMb(): Long = runCatchingCancellable {
val statFs = StatFs(cacheDir.get().absolutePath)
FileSize.BYTES.convert(statFs.availableBytes, FileSize.MEGABYTES)
}.onFailure {
it.printStackTraceDebug()
}.getOrDefault(SIZE_DEFAULT)
private companion object {
val SIZE_MIN
get() = FileSize.MEGABYTES.convert(20, FileSize.BYTES)
val SIZE_DEFAULT
get() = FileSize.MEGABYTES.convert(200, FileSize.BYTES)
}
}

@ -12,6 +12,7 @@ import dagger.hilt.android.lifecycle.RetainedLifecycle
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
@ -32,6 +33,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope
import org.koitharu.kotatsu.core.util.ext.ensureSuccess
import org.koitharu.kotatsu.core.util.ext.isNotEmpty
import org.koitharu.kotatsu.core.util.ext.ramAvailable
import org.koitharu.kotatsu.core.util.ext.withProgress
import org.koitharu.kotatsu.core.util.progress.ProgressDeferred
@ -103,7 +105,7 @@ class PageLoader @Inject constructor(
}
fun loadPageAsync(page: MangaPage, force: Boolean): ProgressDeferred<File, Float> {
var task = tasks[page.id]
var task = tasks[page.id]?.takeIf { it.isValid() }
if (force) {
task?.cancel()
} else if (task?.isCancelled == false) {
@ -216,6 +218,15 @@ class PageLoader @Inject constructor(
return context.ramAvailable <= FileSize.MEGABYTES.convert(PREFETCH_MIN_RAM_MB, FileSize.BYTES)
}
private fun Deferred<File>.isValid(): Boolean {
return if (isCompleted) {
val file = getCompleted()
file.exists() && file.isNotEmpty()
} else {
true
}
}
private class InternalErrorHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler),
CoroutineExceptionHandler {

Loading…
Cancel
Save