Fixing logic for fetching updated manga covers

And for shortcut images
This commit is contained in:
Jays2Kings 2021-04-08 15:40:41 -04:00
parent 93d2145c43
commit d5710bfd10
5 changed files with 83 additions and 56 deletions

View File

@ -33,6 +33,8 @@ class MangaFetcher : Fetcher<Manga> {
companion object { companion object {
const val realCover = "real_cover" const val realCover = "real_cover"
const val onlyCache = "only_cache"
const val onlyFetchRemotely = "only_fetch_remotely"
} }
private val coverCache: CoverCache by injectLazy() private val coverCache: CoverCache by injectLazy()
@ -58,24 +60,29 @@ class MangaFetcher : Fetcher<Manga> {
} }
private suspend fun httpLoader(manga: Manga, options: Options): FetchResult { private suspend fun httpLoader(manga: Manga, options: Options): FetchResult {
val onlyCache = options.parameters.value(onlyCache) == true
val shouldFetchRemotely = options.parameters.value(onlyFetchRemotely) == true && !onlyCache
if (!shouldFetchRemotely) {
val customCoverFile = coverCache.getCustomCoverFile(manga) val customCoverFile = coverCache.getCustomCoverFile(manga)
if (customCoverFile.exists() && options.parameters.value(realCover) != true) { if (customCoverFile.exists() && options.parameters.value(realCover) != true) {
return fileLoader(customCoverFile) return fileLoader(customCoverFile)
} }
}
val coverFile = coverCache.getCoverFile(manga) val coverFile = coverCache.getCoverFile(manga)
if (coverFile.exists() && options.diskCachePolicy.readEnabled) { if (!shouldFetchRemotely && coverFile.exists() && options.diskCachePolicy.readEnabled) {
if (!manga.favorite) { if (!manga.favorite) {
coverFile.setLastModified(Date().time) coverFile.setLastModified(Date().time)
} }
return fileLoader(coverFile) return fileLoader(coverFile)
} }
val (_, body) = awaitGetCall( val (response, body) = awaitGetCall(
manga, manga,
if (manga.favorite) { if (manga.favorite) {
!options.networkCachePolicy.readEnabled onlyCache
} else { } else {
false false
} },
shouldFetchRemotely
) )
val tmpFile = File(coverFile.absolutePath + "_tmp") val tmpFile = File(coverFile.absolutePath + "_tmp")
@ -85,20 +92,46 @@ class MangaFetcher : Fetcher<Manga> {
} }
} }
if (response.isSuccessful || !coverFile.exists()) {
if (coverFile.exists()) {
coverFile.delete()
}
tmpFile.renameTo(coverFile) tmpFile.renameTo(coverFile)
}
if (manga.favorite) { if (manga.favorite) {
coverCache.deleteCachedCovers() coverCache.deleteCachedCovers()
} }
return fileLoader(coverFile) return fileLoader(coverFile)
} }
private suspend fun awaitGetCall(manga: Manga, onlyCache: Boolean = false): Pair<Response, private suspend fun awaitGetCall(manga: Manga, onlyCache: Boolean = false, forceNetwork: Boolean): Pair<Response,
ResponseBody> { ResponseBody> {
val call = getCall(manga, onlyCache) val call = getCall(manga, onlyCache, forceNetwork)
val response = call.await() val response = call.await()
return response to checkNotNull(response.body) { "Null response source" } return response to checkNotNull(response.body) { "Null response source" }
} }
private fun getCall(manga: Manga, onlyCache: Boolean, forceNetwork: Boolean): Call {
val source = sourceManager.get(manga.source) as? HttpSource
val client = source?.client ?: defaultClient
val newClient = client.newBuilder().build()
val request = Request.Builder().url(manga.thumbnail_url!!).also {
if (source != null) {
it.headers(source.headers)
}
if (forceNetwork) {
it.cacheControl(CacheControl.FORCE_NETWORK)
} else if (onlyCache) {
it.cacheControl(CacheControl.FORCE_CACHE)
}
}.build()
return newClient.newCall(request)
}
/** /**
* "text/plain" is often used as a default/fallback MIME type. * "text/plain" is often used as a default/fallback MIME type.
* Attempt to guess a better MIME type from the file extension. * Attempt to guess a better MIME type from the file extension.
@ -139,24 +172,6 @@ class MangaFetcher : Fetcher<Manga> {
) )
} }
private fun getCall(manga: Manga, onlyCache: Boolean): Call {
val source = sourceManager.get(manga.source) as? HttpSource
val client = source?.client ?: defaultClient
val newClient = client.newBuilder().build()
val request = Request.Builder().url(manga.thumbnail_url!!).also {
if (source != null) {
it.headers(source.headers)
}
if (onlyCache) {
it.cacheControl(CacheControl.FORCE_CACHE)
}
}.build()
return newClient.newCall(request)
}
private fun getResourceType(cover: String?): Type? { private fun getResourceType(cover: String?): Type? {
return when { return when {
cover.isNullOrEmpty() -> null cover.isNullOrEmpty() -> null

View File

@ -13,11 +13,13 @@ import androidx.core.content.ContextCompat
import coil.Coil import coil.Coil
import coil.request.CachePolicy import coil.request.CachePolicy
import coil.request.GetRequest import coil.request.GetRequest
import coil.request.Parameters
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.image.coil.MangaFetcher
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -137,7 +139,8 @@ class LibraryUpdateNotifier(private val context: Context) {
setSmallIcon(R.drawable.ic_tachi) setSmallIcon(R.drawable.ic_tachi)
try { try {
val request = GetRequest.Builder(context).data(manga) val request = GetRequest.Builder(context).data(manga)
.networkCachePolicy(CachePolicy.DISABLED) .parameters(Parameters.Builder().set(MangaFetcher.onlyCache, true).build())
.networkCachePolicy(CachePolicy.READ_ONLY)
.transformations(CircleCropTransformation()) .transformations(CircleCropTransformation())
.size(width = ICON_SIZE, height = ICON_SIZE).build() .size(width = ICON_SIZE, height = ICON_SIZE).build()

View File

@ -9,6 +9,7 @@ import android.os.PowerManager
import coil.Coil import coil.Coil
import coil.request.CachePolicy import coil.request.CachePolicy
import coil.request.LoadRequest import coil.request.LoadRequest
import coil.request.Parameters
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -17,6 +18,7 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.image.coil.MangaFetcher
import eu.kanade.tachiyomi.data.library.LibraryUpdateRanker.rankingScheme import eu.kanade.tachiyomi.data.library.LibraryUpdateRanker.rankingScheme
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
@ -475,7 +477,12 @@ class LibraryUpdateService(
.memoryCachePolicy(CachePolicy.DISABLED).build() .memoryCachePolicy(CachePolicy.DISABLED).build()
Coil.imageLoader(this@LibraryUpdateService).execute(request) Coil.imageLoader(this@LibraryUpdateService).execute(request)
} else { } else {
coverCache.deleteFromCache(manga, false) val request =
LoadRequest.Builder(this@LibraryUpdateService).data(manga)
.memoryCachePolicy(CachePolicy.DISABLED)
.parameters(Parameters.Builder().set(MangaFetcher.onlyFetchRemotely, true).build())
.build()
Coil.imageLoader(this@LibraryUpdateService).execute(request)
} }
db.insertManga(manga).executeAsBlocking() db.insertManga(manga).executeAsBlocking()
} }

View File

@ -4,6 +4,11 @@ import android.app.Application
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
import coil.Coil
import coil.request.CachePolicy
import coil.request.GetRequest
import coil.request.Parameters
import coil.request.SuccessResult
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -15,6 +20,7 @@ import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.data.download.model.DownloadQueue
import eu.kanade.tachiyomi.data.image.coil.MangaFetcher
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.data.library.LibraryServiceListener import eu.kanade.tachiyomi.data.library.LibraryServiceListener
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
@ -39,6 +45,7 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.manga.MangaShortcutManager import eu.kanade.tachiyomi.util.manga.MangaShortcutManager
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.launchIO
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -341,13 +348,25 @@ class MangaDetailsPresenter(
if (thumbnailUrl != networkManga.thumbnail_url) { if (thumbnailUrl != networkManga.thumbnail_url) {
coverCache.deleteFromCache(thumbnailUrl) coverCache.deleteFromCache(thumbnailUrl)
} else {
coverCache.deleteFromCache(manga, false)
} }
db.insertManga(manga).executeAsBlocking()
launchIO {
val request =
GetRequest.Builder(preferences.context).data(manga)
.memoryCachePolicy(CachePolicy.DISABLED)
.parameters(
Parameters.Builder().set(MangaFetcher.onlyFetchRemotely, true)
.build()
)
.build()
if (Coil.imageLoader(preferences.context).execute(request) is SuccessResult) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
controller.setPaletteColor() controller.setPaletteColor()
} }
db.insertManga(manga).executeAsBlocking() }
}
} }
val finChapters = chapters.await() val finChapters = chapters.await()
if (finChapters.isNotEmpty()) { if (finChapters.isNotEmpty()) {

View File

@ -5,9 +5,10 @@ import android.content.Intent
import android.content.pm.ShortcutInfo import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager import android.content.pm.ShortcutManager
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import coil.Coil
import coil.request.GetRequest
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -26,7 +27,6 @@ import kotlinx.coroutines.GlobalScope
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date
import kotlin.math.min import kotlin.math.min
class MangaShortcutManager( class MangaShortcutManager(
@ -71,25 +71,8 @@ class MangaShortcutManager(
val shortcuts = recents.mapNotNull { item -> val shortcuts = recents.mapNotNull { item ->
when (item) { when (item) {
is Manga -> { is Manga -> {
val customCoverFile = coverCache.getCustomCoverFile(item) val request = GetRequest.Builder(context).data(item).build()
val coverFile = if (customCoverFile.exists()) { val bitmap = (Coil.imageLoader(context).execute(request).drawable as? BitmapDrawable)?.bitmap
customCoverFile
} else {
val coverFile = coverCache.getCoverFile(item)
if (coverFile.exists()) {
if (!item.favorite) {
coverFile.setLastModified(Date().time)
}
coverFile
} else {
null
}
}
val bitmap = if (coverFile != null) {
BitmapFactory.decodeFile(coverFile.path)
} else {
null
}
ShortcutInfo.Builder( ShortcutInfo.Builder(
context, context,