Check if page file valid before page display

This commit is contained in:
Koitharu
2023-06-04 16:50:09 +03:00
parent 12d8d3e2d1
commit 02d5dfb375
4 changed files with 36 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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