MangaCoverFetcher: Small cleanups

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Secozzi 2024-07-04 13:56:23 +02:00
parent 3eb3f01646
commit f258614e9b
No known key found for this signature in database
GPG key ID: 71E9C97D8DDC2662
3 changed files with 26 additions and 72 deletions

View file

@ -18,8 +18,6 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import coil3.ImageLoader import coil3.ImageLoader
import coil3.SingletonImageLoader import coil3.SingletonImageLoader
import coil3.disk.DiskCache
import coil3.disk.directory
import coil3.network.okhttp.OkHttpNetworkFetcherFactory import coil3.network.okhttp.OkHttpNetworkFetcherFactory
import coil3.request.allowRgb565 import coil3.request.allowRgb565
import coil3.request.crossfade import coil3.request.crossfade
@ -178,20 +176,18 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
override fun newImageLoader(context: Context): ImageLoader { override fun newImageLoader(context: Context): ImageLoader {
return ImageLoader.Builder(this).apply { return ImageLoader.Builder(this).apply {
val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().client } val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().client }
val diskCacheLazy = lazy { CoilDiskCache.get(this@App) }
components { components {
add(OkHttpNetworkFetcherFactory(callFactoryLazy::value)) add(OkHttpNetworkFetcherFactory(callFactoryLazy::value))
add(TachiyomiImageDecoder.Factory()) add(TachiyomiImageDecoder.Factory())
add(MangaCoverFetcher.MangaFactory(callFactoryLazy, diskCacheLazy)) add(MangaCoverFetcher.MangaFactory(callFactoryLazy))
add(AnimeCoverFetcher.AnimeFactory(callFactoryLazy, diskCacheLazy)) add(AnimeCoverFetcher.AnimeFactory(callFactoryLazy))
add(AnimeCoverFetcher.AnimeCoverFactory(callFactoryLazy, diskCacheLazy)) add(AnimeCoverFetcher.AnimeCoverFactory(callFactoryLazy))
add(AnimeKeyer()) add(AnimeKeyer())
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy, diskCacheLazy)) add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy))
add(MangaKeyer()) add(MangaKeyer())
add(AnimeCoverKeyer()) add(AnimeCoverKeyer())
add(MangaCoverKeyer()) add(MangaCoverKeyer())
} }
diskCache(diskCacheLazy::value)
crossfade((300 * this@App.animatorDurationScale).toInt()) crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(DeviceUtil.isLowRamDevice(this@App)) allowRgb565(DeviceUtil.isLowRamDevice(this@App))
if (networkPreferences.verboseLogging().get()) logger(DebugLogger()) if (networkPreferences.verboseLogging().get()) logger(DebugLogger())
@ -291,45 +287,3 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
} }
private const val ACTION_DISABLE_INCOGNITO_MODE = "tachi.action.DISABLE_INCOGNITO_MODE" private const val ACTION_DISABLE_INCOGNITO_MODE = "tachi.action.DISABLE_INCOGNITO_MODE"
/**
* Direct copy of Coil's internal SingletonDiskCache so that [MangaCoverFetcher] can access it.
*/
private object CoilDiskCache {
private const val FOLDER_NAME = "image_cache"
private var instance: DiskCache? = null
@Synchronized
fun get(context: Context): DiskCache {
return instance ?: run {
val safeCacheDir = context.cacheDir.apply { mkdirs() }
// Create the singleton disk cache instance.
DiskCache.Builder()
.directory(safeCacheDir.resolve(FOLDER_NAME))
.build()
.also { instance = it }
}
}
}
/**
* Direct copy of Coil's internal SingletonDiskCache so that [MangaCoverFetcher] can access it.
*/
internal object CoilDiskCacheAnime {
private const val FOLDER_NAME = "anime_image_cache"
private var instance: DiskCache? = null
@Synchronized
fun get(context: Context): DiskCache {
return instance ?: run {
val safeCacheDir = context.cacheDir.apply { mkdirs() }
// Create the singleton disk cache instance.
DiskCache.Builder()
.directory(safeCacheDir.resolve(FOLDER_NAME))
.build()
.also { instance = it }
}
}
}

View file

@ -46,6 +46,7 @@ import java.net.HttpURLConnection.HTTP_NOT_MODIFIED
* Available request parameter: * Available request parameter:
* - [USE_CUSTOM_COVER_KEY]: Use custom cover if set by user, default is true * - [USE_CUSTOM_COVER_KEY]: Use custom cover if set by user, default is true
*/ */
@Suppress("LongParameterList")
class AnimeCoverFetcher( class AnimeCoverFetcher(
private val url: String?, private val url: String?,
private val isLibraryAnime: Boolean, private val isLibraryAnime: Boolean,
@ -55,7 +56,7 @@ class AnimeCoverFetcher(
private val diskCacheKeyLazy: Lazy<String>, private val diskCacheKeyLazy: Lazy<String>,
private val sourceLazy: Lazy<AnimeHttpSource?>, private val sourceLazy: Lazy<AnimeHttpSource?>,
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>, private val imageLoader: ImageLoader,
) : Fetcher { ) : Fetcher {
private val diskCacheKey: String private val diskCacheKey: String
@ -205,7 +206,7 @@ class AnimeCoverFetcher(
private fun moveSnapshotToCoverCache(snapshot: DiskCache.Snapshot, cacheFile: File?): File? { private fun moveSnapshotToCoverCache(snapshot: DiskCache.Snapshot, cacheFile: File?): File? {
if (cacheFile == null) return null if (cacheFile == null) return null
return try { return try {
diskCacheLazy.value.run { imageLoader.diskCache?.run {
fileSystem.source(snapshot.data).use { input -> fileSystem.source(snapshot.data).use { input ->
writeSourceToCoverCache(input, cacheFile) writeSourceToCoverCache(input, cacheFile)
} }
@ -246,7 +247,7 @@ class AnimeCoverFetcher(
private fun readFromDiskCache(): DiskCache.Snapshot? { private fun readFromDiskCache(): DiskCache.Snapshot? {
return if (options.diskCachePolicy.readEnabled) { return if (options.diskCachePolicy.readEnabled) {
diskCacheLazy.value.openSnapshot(diskCacheKey) imageLoader.diskCache?.openSnapshot(diskCacheKey)
} else { } else {
null null
} }
@ -255,9 +256,10 @@ class AnimeCoverFetcher(
private fun writeToDiskCache( private fun writeToDiskCache(
response: Response, response: Response,
): DiskCache.Snapshot? { ): DiskCache.Snapshot? {
val editor = diskCacheLazy.value.openEditor(diskCacheKey) ?: return null val diskCache = imageLoader.diskCache
val editor = diskCache?.openEditor(diskCacheKey) ?: return null
try { try {
diskCacheLazy.value.fileSystem.write(editor.data) { diskCache.fileSystem.write(editor.data) {
response.body.source().readAll(this) response.body.source().readAll(this)
} }
return editor.commitAndOpenSnapshot() return editor.commitAndOpenSnapshot()
@ -295,7 +297,6 @@ class AnimeCoverFetcher(
class AnimeFactory( class AnimeFactory(
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<Anime> { ) : Fetcher.Factory<Anime> {
private val coverCache: AnimeCoverCache by injectLazy() private val coverCache: AnimeCoverCache by injectLazy()
@ -308,17 +309,16 @@ class AnimeCoverFetcher(
options = options, options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) }, coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) }, customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { AnimeKeyer().key(data, options) }, diskCacheKeyLazy = lazy { imageLoader.components.key(data, options)!! },
sourceLazy = lazy { sourceManager.get(data.source) as? AnimeHttpSource }, sourceLazy = lazy { sourceManager.get(data.source) as? AnimeHttpSource },
callFactoryLazy = callFactoryLazy, callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy, imageLoader = imageLoader,
) )
} }
} }
class AnimeCoverFactory( class AnimeCoverFactory(
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<AnimeCover> { ) : Fetcher.Factory<AnimeCover> {
private val coverCache: AnimeCoverCache by injectLazy() private val coverCache: AnimeCoverCache by injectLazy()
@ -331,10 +331,10 @@ class AnimeCoverFetcher(
options = options, options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.url) }, coverFileLazy = lazy { coverCache.getCoverFile(data.url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.animeId) }, customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.animeId) },
diskCacheKeyLazy = lazy { AnimeCoverKeyer().key(data, options) }, diskCacheKeyLazy = lazy { imageLoader.components.key(data, options)!! },
sourceLazy = lazy { sourceManager.get(data.sourceId) as? AnimeHttpSource }, sourceLazy = lazy { sourceManager.get(data.sourceId) as? AnimeHttpSource },
callFactoryLazy = callFactoryLazy, callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy, imageLoader = imageLoader,
) )
} }
} }

View file

@ -46,6 +46,7 @@ import java.net.HttpURLConnection.HTTP_NOT_MODIFIED
* Available request parameter: * Available request parameter:
* - [USE_CUSTOM_COVER_KEY]: Use custom cover if set by user, default is true * - [USE_CUSTOM_COVER_KEY]: Use custom cover if set by user, default is true
*/ */
@Suppress("LongParameterList")
class MangaCoverFetcher( class MangaCoverFetcher(
private val url: String?, private val url: String?,
private val isLibraryManga: Boolean, private val isLibraryManga: Boolean,
@ -55,7 +56,7 @@ class MangaCoverFetcher(
private val diskCacheKeyLazy: Lazy<String>, private val diskCacheKeyLazy: Lazy<String>,
private val sourceLazy: Lazy<HttpSource?>, private val sourceLazy: Lazy<HttpSource?>,
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>, private val imageLoader: ImageLoader,
) : Fetcher { ) : Fetcher {
private val diskCacheKey: String private val diskCacheKey: String
@ -205,7 +206,7 @@ class MangaCoverFetcher(
private fun moveSnapshotToCoverCache(snapshot: DiskCache.Snapshot, cacheFile: File?): File? { private fun moveSnapshotToCoverCache(snapshot: DiskCache.Snapshot, cacheFile: File?): File? {
if (cacheFile == null) return null if (cacheFile == null) return null
return try { return try {
diskCacheLazy.value.run { imageLoader.diskCache?.run {
fileSystem.source(snapshot.data).use { input -> fileSystem.source(snapshot.data).use { input ->
writeSourceToCoverCache(input, cacheFile) writeSourceToCoverCache(input, cacheFile)
} }
@ -246,7 +247,7 @@ class MangaCoverFetcher(
private fun readFromDiskCache(): DiskCache.Snapshot? { private fun readFromDiskCache(): DiskCache.Snapshot? {
return if (options.diskCachePolicy.readEnabled) { return if (options.diskCachePolicy.readEnabled) {
diskCacheLazy.value.openSnapshot(diskCacheKey) imageLoader.diskCache?.openSnapshot(diskCacheKey)
} else { } else {
null null
} }
@ -255,9 +256,10 @@ class MangaCoverFetcher(
private fun writeToDiskCache( private fun writeToDiskCache(
response: Response, response: Response,
): DiskCache.Snapshot? { ): DiskCache.Snapshot? {
val editor = diskCacheLazy.value.openEditor(diskCacheKey) ?: return null val diskCache = imageLoader.diskCache
val editor = diskCache?.openEditor(diskCacheKey) ?: return null
try { try {
diskCacheLazy.value.fileSystem.write(editor.data) { diskCache.fileSystem.write(editor.data) {
response.body.source().readAll(this) response.body.source().readAll(this)
} }
return editor.commitAndOpenSnapshot() return editor.commitAndOpenSnapshot()
@ -295,7 +297,6 @@ class MangaCoverFetcher(
class MangaFactory( class MangaFactory(
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<Manga> { ) : Fetcher.Factory<Manga> {
private val coverCache: MangaCoverCache by injectLazy() private val coverCache: MangaCoverCache by injectLazy()
@ -308,17 +309,16 @@ class MangaCoverFetcher(
options = options, options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) }, coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) }, customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) }, diskCacheKeyLazy = lazy { imageLoader.components.key(data, options)!! },
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource }, sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
callFactoryLazy = callFactoryLazy, callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy, imageLoader = imageLoader,
) )
} }
} }
class MangaCoverFactory( class MangaCoverFactory(
private val callFactoryLazy: Lazy<Call.Factory>, private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<MangaCover> { ) : Fetcher.Factory<MangaCover> {
private val coverCache: MangaCoverCache by injectLazy() private val coverCache: MangaCoverCache by injectLazy()
@ -331,10 +331,10 @@ class MangaCoverFetcher(
options = options, options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.url) }, coverFileLazy = lazy { coverCache.getCoverFile(data.url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.mangaId) }, customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.mangaId) },
diskCacheKeyLazy = lazy { MangaCoverKeyer().key(data, options) }, diskCacheKeyLazy = lazy { imageLoader.components.key(data, options)!! },
sourceLazy = lazy { sourceManager.get(data.sourceId) as? HttpSource }, sourceLazy = lazy { sourceManager.get(data.sourceId) as? HttpSource },
callFactoryLazy = callFactoryLazy, callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy, imageLoader = imageLoader,
) )
} }
} }