mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-24 13:48:55 +03:00
Change cover memory key (#7276)
Use different key for custom cover and add last modified time for updating cover without clearing the whole memory cache
This commit is contained in:
parent
20c14a0a00
commit
59837bbb90
8 changed files with 42 additions and 36 deletions
|
@ -1,7 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.data.cache
|
package eu.kanade.tachiyomi.data.cache
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import coil.imageLoader
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -100,13 +99,6 @@ class CoverCache(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear coil's memory cache.
|
|
||||||
*/
|
|
||||||
fun clearMemoryCache() {
|
|
||||||
context.imageLoader.memoryCache?.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCacheDir(dir: String): File {
|
private fun getCacheDir(dir: String): File {
|
||||||
return context.getExternalFilesDir(dir)
|
return context.getExternalFilesDir(dir)
|
||||||
?: File(context.filesDir, dir).also { it.mkdirs() }
|
?: File(context.filesDir, dir).also { it.mkdirs() }
|
||||||
|
|
|
@ -42,28 +42,32 @@ import java.net.HttpURLConnection
|
||||||
* - [USE_CUSTOM_COVER]: Use custom cover if set by user, default is true
|
* - [USE_CUSTOM_COVER]: Use custom cover if set by user, default is true
|
||||||
*/
|
*/
|
||||||
class MangaCoverFetcher(
|
class MangaCoverFetcher(
|
||||||
private val manga: Manga,
|
private val url: String?,
|
||||||
private val sourceLazy: Lazy<HttpSource?>,
|
private val isLibraryManga: Boolean,
|
||||||
private val options: Options,
|
private val options: Options,
|
||||||
private val coverCache: CoverCache,
|
private val coverFileLazy: Lazy<File?>,
|
||||||
|
private val customCoverFileLazy: Lazy<File>,
|
||||||
|
private val diskCacheKeyLazy: Lazy<String>,
|
||||||
|
private val sourceLazy: Lazy<HttpSource?>,
|
||||||
private val callFactoryLazy: Lazy<Call.Factory>,
|
private val callFactoryLazy: Lazy<Call.Factory>,
|
||||||
private val diskCacheLazy: Lazy<DiskCache>,
|
private val diskCacheLazy: Lazy<DiskCache>,
|
||||||
) : Fetcher {
|
) : Fetcher {
|
||||||
|
|
||||||
// For non-custom cover
|
private val diskCacheKey: String
|
||||||
private val diskCacheKey: String? by lazy { MangaCoverKeyer().key(manga, options) }
|
get() = diskCacheKeyLazy.value
|
||||||
private lateinit var url: String
|
|
||||||
|
|
||||||
override suspend fun fetch(): FetchResult {
|
override suspend fun fetch(): FetchResult {
|
||||||
// Use custom cover if exists
|
// Use custom cover if exists
|
||||||
val useCustomCover = options.parameters.value(USE_CUSTOM_COVER) ?: true
|
val useCustomCover = options.parameters.value(USE_CUSTOM_COVER) ?: true
|
||||||
val customCoverFile = coverCache.getCustomCoverFile(manga.id)
|
if (useCustomCover) {
|
||||||
if (useCustomCover && customCoverFile.exists()) {
|
val customCoverFile = customCoverFileLazy.value
|
||||||
return fileLoader(customCoverFile)
|
if (customCoverFile.exists()) {
|
||||||
|
return fileLoader(customCoverFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// diskCacheKey is thumbnail_url
|
// diskCacheKey is thumbnail_url
|
||||||
url = diskCacheKey ?: error("No cover specified")
|
if (url == null) error("No cover specified")
|
||||||
return when (getResourceType(url)) {
|
return when (getResourceType(url)) {
|
||||||
Type.URL -> httpLoader()
|
Type.URL -> httpLoader()
|
||||||
Type.File -> fileLoader(File(url.substringAfter("file://")))
|
Type.File -> fileLoader(File(url.substringAfter("file://")))
|
||||||
|
@ -81,8 +85,8 @@ class MangaCoverFetcher(
|
||||||
|
|
||||||
private suspend fun httpLoader(): FetchResult {
|
private suspend fun httpLoader(): FetchResult {
|
||||||
// Only cache separately if it's a library item
|
// Only cache separately if it's a library item
|
||||||
val libraryCoverCacheFile = if (manga.favorite) {
|
val libraryCoverCacheFile = if (isLibraryManga) {
|
||||||
coverCache.getCoverFile(manga.thumbnail_url) ?: error("No cover specified")
|
coverFileLazy.value ?: error("No cover specified")
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -156,7 +160,7 @@ class MangaCoverFetcher(
|
||||||
|
|
||||||
private fun newRequest(): Request {
|
private fun newRequest(): Request {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(url)
|
.url(url!!)
|
||||||
.headers(sourceLazy.value?.headers ?: options.headers)
|
.headers(sourceLazy.value?.headers ?: options.headers)
|
||||||
// Support attaching custom data to the network request.
|
// Support attaching custom data to the network request.
|
||||||
.tag(Parameters::class.java, options.parameters)
|
.tag(Parameters::class.java, options.parameters)
|
||||||
|
@ -188,7 +192,7 @@ class MangaCoverFetcher(
|
||||||
fileSystem.source(snapshot.data).use { input ->
|
fileSystem.source(snapshot.data).use { input ->
|
||||||
writeSourceToCoverCache(input, cacheFile)
|
writeSourceToCoverCache(input, cacheFile)
|
||||||
}
|
}
|
||||||
remove(diskCacheKey!!)
|
remove(diskCacheKey)
|
||||||
}
|
}
|
||||||
cacheFile.takeIf { it.exists() }
|
cacheFile.takeIf { it.exists() }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -224,7 +228,7 @@ class MangaCoverFetcher(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readFromDiskCache(): DiskCache.Snapshot? {
|
private fun readFromDiskCache(): DiskCache.Snapshot? {
|
||||||
return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey!!] else null
|
return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey] else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun writeToDiskCache(
|
private fun writeToDiskCache(
|
||||||
|
@ -238,7 +242,7 @@ class MangaCoverFetcher(
|
||||||
val editor = if (snapshot != null) {
|
val editor = if (snapshot != null) {
|
||||||
snapshot.closeAndEdit()
|
snapshot.closeAndEdit()
|
||||||
} else {
|
} else {
|
||||||
diskCacheLazy.value.edit(diskCacheKey!!)
|
diskCacheLazy.value.edit(diskCacheKey)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
try {
|
try {
|
||||||
diskCacheLazy.value.fileSystem.write(editor.data) {
|
diskCacheLazy.value.fileSystem.write(editor.data) {
|
||||||
|
@ -280,8 +284,17 @@ class MangaCoverFetcher(
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
|
|
||||||
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
|
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
|
||||||
val source = lazy { sourceManager.get(data.source) as? HttpSource }
|
return MangaCoverFetcher(
|
||||||
return MangaCoverFetcher(data, source, options, coverCache, callFactoryLazy, diskCacheLazy)
|
url = data.thumbnail_url,
|
||||||
|
isLibraryManga = data.favorite,
|
||||||
|
options = options,
|
||||||
|
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnail_url) },
|
||||||
|
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
|
||||||
|
diskCacheKeyLazy = lazy { MangaCoverKeyer().key(data, options) },
|
||||||
|
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
|
||||||
|
callFactoryLazy = callFactoryLazy,
|
||||||
|
diskCacheLazy = diskCacheLazy,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,14 @@ package eu.kanade.tachiyomi.data.coil
|
||||||
import coil.key.Keyer
|
import coil.key.Keyer
|
||||||
import coil.request.Options
|
import coil.request.Options
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.util.hasCustomCover
|
||||||
|
|
||||||
class MangaCoverKeyer : Keyer<Manga> {
|
class MangaCoverKeyer : Keyer<Manga> {
|
||||||
override fun key(data: Manga, options: Options): String? {
|
override fun key(data: Manga, options: Options): String {
|
||||||
return data.thumbnail_url?.takeIf { it.isNotBlank() }
|
return if (data.hasCustomCover()) {
|
||||||
|
"${data.id};${data.cover_last_modified}"
|
||||||
|
} else {
|
||||||
|
"${data.thumbnail_url};${data.cover_last_modified}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -473,7 +473,6 @@ class LibraryUpdateService(
|
||||||
.awaitAll()
|
.awaitAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
notifier.cancelProgressNotification()
|
notifier.cancelProgressNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,6 @@ class LocalSource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.also { coverCache.clearMemoryCache() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Format {
|
sealed class Format {
|
||||||
|
|
|
@ -316,12 +316,11 @@ class MangaPresenter(
|
||||||
LocalSource.updateCover(context, manga, it)
|
LocalSource.updateCover(context, manga, it)
|
||||||
manga.updateCoverLastModified(db)
|
manga.updateCoverLastModified(db)
|
||||||
db.insertManga(manga).executeAsBlocking()
|
db.insertManga(manga).executeAsBlocking()
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
} else if (manga.favorite) {
|
} else if (manga.favorite) {
|
||||||
coverCache.setCustomCoverToCache(manga, it)
|
coverCache.setCustomCoverToCache(manga, it)
|
||||||
manga.updateCoverLastModified(db)
|
manga.updateCoverLastModified(db)
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
}
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -337,7 +336,6 @@ class MangaPresenter(
|
||||||
.fromCallable {
|
.fromCallable {
|
||||||
coverCache.deleteCustomCover(manga.id)
|
coverCache.deleteCustomCover(manga.id)
|
||||||
manga.updateCoverLastModified(db)
|
manga.updateCoverLastModified(db)
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
|
|
@ -704,13 +704,11 @@ class ReaderPresenter(
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
LocalSource.updateCover(context, manga, it)
|
LocalSource.updateCover(context, manga, it)
|
||||||
manga.updateCoverLastModified(db)
|
manga.updateCoverLastModified(db)
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
SetAsCoverResult.Success
|
SetAsCoverResult.Success
|
||||||
} else {
|
} else {
|
||||||
if (manga.favorite) {
|
if (manga.favorite) {
|
||||||
coverCache.setCustomCoverToCache(manga, it)
|
coverCache.setCustomCoverToCache(manga, it)
|
||||||
manga.updateCoverLastModified(db)
|
manga.updateCoverLastModified(db)
|
||||||
coverCache.clearMemoryCache()
|
|
||||||
SetAsCoverResult.Success
|
SetAsCoverResult.Success
|
||||||
} else {
|
} else {
|
||||||
SetAsCoverResult.AddToLibraryFirst
|
SetAsCoverResult.AddToLibraryFirst
|
||||||
|
|
|
@ -6,6 +6,8 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
fun Manga.isLocal() = source == LocalSource.ID
|
fun Manga.isLocal() = source == LocalSource.ID
|
||||||
|
@ -36,7 +38,7 @@ fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Manga.hasCustomCover(coverCache: CoverCache): Boolean {
|
fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean {
|
||||||
return coverCache.getCustomCoverFile(id).exists()
|
return coverCache.getCustomCoverFile(id).exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue