Fix cover fetching in compose views (#7315)

Make sure it passed thru the custom fetcher
This commit is contained in:
Ivan Iskandar 2022-06-18 09:21:29 +07:00 committed by GitHub
parent 02eb3cb6b5
commit 1b804e61cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 147 additions and 9 deletions

View file

@ -2,6 +2,7 @@ package eu.kanade.data.history
import eu.kanade.domain.history.model.History
import eu.kanade.domain.history.model.HistoryWithRelations
import eu.kanade.domain.manga.model.MangaCover
import java.util.Date
val historyMapper: (Long, Long, Date?, Long) -> History = { id, chapterId, readAt, readDuration ->
@ -13,16 +14,22 @@ val historyMapper: (Long, Long, Date?, Long) -> History = { id, chapterId, readA
)
}
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Float, Date?, Long) -> HistoryWithRelations = {
historyId, mangaId, chapterId, title, thumbnailUrl, chapterNumber, readAt, readDuration ->
val historyWithRelationsMapper: (Long, Long, Long, String, String?, Long, Boolean, Long, Float, Date?, Long) -> HistoryWithRelations = {
historyId, mangaId, chapterId, title, thumbnailUrl, sourceId, isFavorite, coverLastModified, chapterNumber, readAt, readDuration ->
HistoryWithRelations(
id = historyId,
chapterId = chapterId,
mangaId = mangaId,
title = title,
thumbnailUrl = thumbnailUrl ?: "",
chapterNumber = chapterNumber,
readAt = readAt,
readDuration = readDuration,
coverData = MangaCover(
mangaId = mangaId,
sourceId = sourceId,
isMangaFavorite = isFavorite,
url = thumbnailUrl,
lastModified = coverLastModified,
),
)
}

View file

@ -1,5 +1,6 @@
package eu.kanade.domain.history.model
import eu.kanade.domain.manga.model.MangaCover
import java.util.Date
data class HistoryWithRelations(
@ -7,8 +8,8 @@ data class HistoryWithRelations(
val chapterId: Long,
val mangaId: Long,
val title: String,
val thumbnailUrl: String,
val chapterNumber: Float,
val readAt: Date?,
val readDuration: Long,
val coverData: MangaCover,
)

View file

@ -0,0 +1,12 @@
package eu.kanade.domain.manga.model
/**
* Contains the required data for MangaCoverFetcher
*/
data class MangaCover(
val mangaId: Long,
val sourceId: Long,
val isMangaFavorite: Boolean,
val url: String?,
val lastModified: Long,
)

View file

@ -21,7 +21,7 @@ enum class MangaCover(private val ratio: Float) {
@Composable
operator fun invoke(
modifier: Modifier = Modifier,
data: String?,
data: Any?,
contentDescription: String? = null,
shape: Shape? = null,
) {

View file

@ -191,7 +191,7 @@ fun HistoryItem(
modifier = Modifier
.fillMaxHeight()
.clickable(onClick = onClickCover),
data = history.thumbnailUrl,
data = history.coverData,
)
Column(
modifier = Modifier

View file

@ -47,7 +47,7 @@ private val defaultCover: @Composable RowScope.(Manga, () -> Unit) -> Unit = { m
.padding(vertical = 8.dp)
.clickable(onClick = onClick)
.fillMaxHeight(),
data = manga.thumbnailUrl,
data = manga,
)
}

View file

@ -25,8 +25,10 @@ import coil.decode.ImageDecoderDecoder
import coil.disk.DiskCache
import coil.util.DebugLogger
import eu.kanade.domain.DomainModule
import eu.kanade.tachiyomi.data.coil.DomainMangaKeyer
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
import eu.kanade.tachiyomi.data.coil.MangaKeyer
import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferenceValues
@ -139,6 +141,10 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
}
add(TachiyomiImageDecoder.Factory())
add(MangaCoverFetcher.Factory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaCoverFetcher.DomainMangaFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaCoverFetcher.MangaCoverFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaKeyer())
add(DomainMangaKeyer())
add(MangaCoverKeyer())
}
callFactory(callFactoryInit)

View file

@ -10,6 +10,7 @@ import coil.fetch.SourceResult
import coil.network.HttpException
import coil.request.Options
import coil.request.Parameters
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER
import eu.kanade.tachiyomi.data.database.models.Manga
@ -30,6 +31,7 @@ import okio.sink
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.net.HttpURLConnection
import eu.kanade.domain.manga.model.Manga as DomainManga
/**
* A [Fetcher] that fetches cover image for [Manga] object.
@ -290,7 +292,7 @@ class MangaCoverFetcher(
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnail_url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { MangaCoverKeyer().key(data, options) },
diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy,
@ -298,6 +300,52 @@ class MangaCoverFetcher(
}
}
class DomainMangaFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<DomainManga> {
private val coverCache: CoverCache by injectLazy()
private val sourceManager: SourceManager by injectLazy()
override fun create(data: DomainManga, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
url = data.thumbnailUrl,
isLibraryManga = data.favorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { DomainMangaKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy,
)
}
}
class MangaCoverFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<MangaCover> {
private val coverCache: CoverCache by injectLazy()
private val sourceManager: SourceManager by injectLazy()
override fun create(data: MangaCover, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
url = data.url,
isLibraryManga = data.isMangaFavorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.mangaId) },
diskCacheKeyLazy = lazy { MangaCoverKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.sourceId) as? HttpSource },
callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy,
)
}
}
companion object {
const val USE_CUSTOM_COVER = "use_custom_cover"

View file

@ -2,10 +2,16 @@ package eu.kanade.tachiyomi.data.coil
import coil.key.Keyer
import coil.request.Options
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.hasCustomCover
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import eu.kanade.domain.manga.model.Manga as DomainManga
class MangaCoverKeyer : Keyer<Manga> {
class MangaKeyer : Keyer<Manga> {
override fun key(data: Manga, options: Options): String {
return if (data.hasCustomCover()) {
"${data.id};${data.cover_last_modified}"
@ -14,3 +20,23 @@ class MangaCoverKeyer : Keyer<Manga> {
}
}
}
class DomainMangaKeyer : Keyer<DomainManga> {
override fun key(data: DomainManga, options: Options): String {
return if (data.hasCustomCover()) {
"${data.id};${data.coverLastModified}"
} else {
"${data.thumbnailUrl};${data.coverLastModified}"
}
}
}
class MangaCoverKeyer : Keyer<MangaCover> {
override fun key(data: MangaCover, options: Options): String {
return if (Injekt.get<CoverCache>().getCustomCoverFile(data.mangaId).exists()) {
"${data.mangaId};${data.lastModified}"
} else {
"${data.url};${data.lastModified}"
}
}
}

View file

@ -0,0 +1,29 @@
DROP VIEW IF EXISTS historyView;
CREATE VIEW historyView AS
SELECT
history._id AS id,
mangas._id AS mangaId,
chapters._id AS chapterId,
mangas.title,
mangas.thumbnail_url AS thumbnailUrl,
mangas.source,
mangas.favorite,
mangas.cover_last_modified,
chapters.chapter_number AS chapterNumber,
history.last_read AS readAt,
history.time_read AS readDuration,
max_last_read.last_read AS maxReadAt,
max_last_read.chapter_id AS maxReadAtChapterId
FROM mangas
JOIN chapters
ON mangas._id = chapters.manga_id
JOIN history
ON chapters._id = history.chapter_id
JOIN (
SELECT chapters.manga_id,chapters._id AS chapter_id, MAX(history.last_read) AS last_read
FROM chapters JOIN history
ON chapters._id = history.chapter_id
GROUP BY chapters.manga_id
) AS max_last_read
ON chapters.manga_id = max_last_read.manga_id;

View file

@ -5,6 +5,9 @@ SELECT
chapters._id AS chapterId,
mangas.title,
mangas.thumbnail_url AS thumbnailUrl,
mangas.source,
mangas.favorite,
mangas.cover_last_modified,
chapters.chapter_number AS chapterNumber,
history.last_read AS readAt,
history.time_read AS readDuration,
@ -37,6 +40,9 @@ mangaId,
chapterId,
title,
thumbnailUrl,
source,
favorite,
cover_last_modified,
chapterNumber,
readAt,
readDuration
@ -54,6 +60,9 @@ mangaId,
chapterId,
title,
thumbnailUrl,
source,
favorite,
cover_last_modified,
chapterNumber,
readAt,
readDuration