MangaCoverFetcher: Handle moving cover cache after adding to library (#6885)

Move cover cache to separate cache dir after the parent manga is added to library

(cherry picked from commit ac980a4dbfa3400af4a18e975ca3f8937bb4a336)
This commit is contained in:
Ivan Iskandar 2022-04-08 23:10:06 +07:00 committed by Jobobby04
parent b25da34b64
commit 3f7302c4eb

View File

@ -16,12 +16,15 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
import okhttp3.CacheControl
import okhttp3.Call
import okhttp3.Request
import okhttp3.Response
import okhttp3.internal.closeQuietly
import okio.Path.Companion.toOkioPath
import okio.Source
import okio.buffer
import okio.sink
import uy.kohesive.injekt.injectLazy
@ -78,19 +81,26 @@ class MangaCoverFetcher(
private suspend fun httpLoader(): FetchResult {
// Only cache separately if it's a library item
val coverCacheFile = if (manga.favorite) {
val libraryCoverCacheFile = if (manga.favorite) {
coverCache.getCoverFile(manga) ?: error("No cover specified")
} else {
null
}
if (coverCacheFile?.exists() == true && options.diskCachePolicy.readEnabled) {
return fileLoader(coverCacheFile)
if (libraryCoverCacheFile?.exists() == true && options.diskCachePolicy.readEnabled) {
return fileLoader(libraryCoverCacheFile)
}
var snapshot = readFromDiskCache()
try {
// Fetch from disk cache
if (snapshot != null) {
val snapshotCoverCache = moveSnapshotToCoverCache(snapshot, libraryCoverCacheFile)
if (snapshotCoverCache != null) {
// Read from cover cache after added to library
return fileLoader(snapshotCoverCache)
}
// Read from snapshot
return SourceResult(
source = snapshot.toImageSource(),
mimeType = "image/*",
@ -102,13 +112,14 @@ class MangaCoverFetcher(
val response = executeNetworkRequest()
val responseBody = checkNotNull(response.body) { "Null response source" }
try {
snapshot = writeToDiskCache(snapshot, response)
if (coverCacheFile != null) {
writeToCoverCache(coverCacheFile, response)
// Read from cover cache after library manga cover updated
val responseCoverCache = writeResponseToCoverCache(response, libraryCoverCacheFile)
if (responseCoverCache != null) {
return fileLoader(responseCoverCache)
}
// Read from disk cache
snapshot = writeToDiskCache(snapshot, response)
if (snapshot != null) {
return SourceResult(
source = snapshot.toImageSource(),
@ -133,21 +144,6 @@ class MangaCoverFetcher(
}
}
private fun writeToCoverCache(cacheFile: File, response: Response) {
if (!options.diskCachePolicy.writeEnabled) return
try {
response.body!!.source().use { input ->
cacheFile.parentFile?.mkdirs()
if (cacheFile.exists()) {
cacheFile.delete()
}
cacheFile.sink().buffer().use { output ->
output.writeAll(input)
}
}
} catch (_: Exception) {}
}
private suspend fun executeNetworkRequest(): Response {
val client = sourceLazy.value?.client ?: callFactoryLazy.value
val response = client.newCall(newRequest()).await()
@ -185,6 +181,48 @@ class MangaCoverFetcher(
return request.build()
}
private fun moveSnapshotToCoverCache(snapshot: DiskCache.Snapshot, cacheFile: File?): File? {
if (cacheFile == null) return null
return try {
diskCacheLazy.value.run {
fileSystem.source(snapshot.data).use { input ->
writeSourceToCoverCache(input, cacheFile)
}
remove(diskCacheKey!!)
}
cacheFile.takeIf { it.exists() }
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to cover cache ${cacheFile.name}" }
null
}
}
private fun writeResponseToCoverCache(response: Response, cacheFile: File?): File? {
if (cacheFile == null || !options.diskCachePolicy.writeEnabled) return null
return try {
response.peekBody(Long.MAX_VALUE).source().use { input ->
writeSourceToCoverCache(input, cacheFile)
}
cacheFile.takeIf { it.exists() }
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to write response data to cover cache ${cacheFile.name}" }
null
}
}
private fun writeSourceToCoverCache(input: Source, cacheFile: File) {
cacheFile.parentFile?.mkdirs()
cacheFile.delete()
try {
cacheFile.sink().buffer().use { output ->
output.writeAll(input)
}
} catch (e: Exception) {
cacheFile.delete()
throw e
}
}
private fun readFromDiskCache(): DiskCache.Snapshot? {
return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey!!] else null
}