fix custom manga covers

This commit is contained in:
jmir1 2022-12-13 23:24:24 +01:00
parent 343ae404ea
commit 5dffac458d
19 changed files with 102 additions and 65 deletions

View file

@ -1,8 +1,8 @@
package eu.kanade.data.animehistory
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.animehistory.model.AnimeHistory
import eu.kanade.domain.animehistory.model.AnimeHistoryWithRelations
import eu.kanade.domain.manga.model.MangaCover
import java.util.Date
val animehistoryMapper: (Long, Long, Date?) -> AnimeHistory = { id, episodeId, seenAt ->
@ -22,10 +22,10 @@ val animehistoryWithRelationsMapper: (Long, Long, Long, String, String?, Long, B
title = title,
episodeNumber = episodeNumber,
seenAt = seenAt,
coverData = MangaCover(
mangaId = animeId,
coverData = AnimeCover(
animeId = animeId,
sourceId = sourceId,
isMangaFavorite = isFavorite,
isAnimeFavorite = isFavorite,
url = thumbnailUrl,
lastModified = coverLastModified,
),

View file

@ -1,7 +1,7 @@
package eu.kanade.data.animeupdates
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.animeupdates.model.AnimeUpdatesWithRelations
import eu.kanade.domain.manga.model.MangaCover
val updateWithRelationMapper: (Long, String, Long, String, String?, Boolean, Boolean, Long, Boolean, String?, Long, Long, Long) -> AnimeUpdatesWithRelations = {
animeId, animeTitle, episodeId, episodeName, scanlator, seen, bookmark, sourceId, favorite, thumbnailUrl, coverLastModified, _, dateFetch ->
@ -15,10 +15,10 @@ val updateWithRelationMapper: (Long, String, Long, String, String?, Boolean, Boo
bookmark = bookmark,
sourceId = sourceId,
dateFetch = dateFetch,
coverData = MangaCover(
mangaId = animeId,
coverData = AnimeCover(
animeId = animeId,
sourceId = sourceId,
isMangaFavorite = favorite,
isAnimeFavorite = favorite,
url = thumbnailUrl,
lastModified = coverLastModified,
),

View file

@ -0,0 +1,12 @@
package eu.kanade.domain.anime.model
/**
* Contains the required data for AnimeCoverFetcher
*/
data class AnimeCover(
val animeId: Long,
val sourceId: Long,
val isAnimeFavorite: Boolean,
val url: String?,
val lastModified: Long,
) : eu.kanade.domain.manga.model.CommonCover

View file

@ -1,6 +1,6 @@
package eu.kanade.domain.animehistory.model
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
import java.util.Date
data class AnimeHistoryWithRelations(
@ -10,5 +10,5 @@ data class AnimeHistoryWithRelations(
val title: String,
val episodeNumber: Float,
val seenAt: Date?,
val coverData: MangaCover,
val coverData: AnimeCover,
)

View file

@ -1,6 +1,6 @@
package eu.kanade.domain.animeupdates.model
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
data class AnimeUpdatesWithRelations(
val animeId: Long,
@ -12,5 +12,5 @@ data class AnimeUpdatesWithRelations(
val bookmark: Boolean,
val sourceId: Long,
val dateFetch: Long,
val coverData: MangaCover,
val coverData: AnimeCover,
)

View file

@ -0,0 +1,3 @@
package eu.kanade.domain.manga.model
interface CommonCover

View file

@ -9,4 +9,4 @@ data class MangaCover(
val isMangaFavorite: Boolean,
val url: String?,
val lastModified: Long,
)
) : CommonCover

View file

@ -13,7 +13,7 @@ import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import eu.kanade.domain.anime.model.Anime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.presentation.browse.components.BrowseSourceLoadingItem
import eu.kanade.presentation.components.Badge
import eu.kanade.presentation.components.CommonMangaItemDefaults
@ -68,10 +68,10 @@ fun BrowseAnimeSourceComfortableGridItem(
) {
MangaComfortableGridItem(
title = anime.title,
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -13,7 +13,7 @@ import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import eu.kanade.domain.anime.model.Anime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.presentation.browse.components.BrowseSourceLoadingItem
import eu.kanade.presentation.components.Badge
import eu.kanade.presentation.components.CommonMangaItemDefaults
@ -68,10 +68,10 @@ private fun BrowseAnimeSourceCompactGridItem(
) {
MangaCompactGridItem(
title = anime.title,
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -10,7 +10,7 @@ import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items
import eu.kanade.domain.anime.model.Anime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.presentation.browse.components.BrowseSourceLoadingItem
import eu.kanade.presentation.components.Badge
import eu.kanade.presentation.components.CommonMangaItemDefaults
@ -62,10 +62,10 @@ fun BrowseAnimeSourceListItem(
) {
MangaListItem(
title = anime.title,
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -6,8 +6,8 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.util.fastAny
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.animelib.model.AnimelibAnime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.presentation.components.MangaComfortableGridItem
import eu.kanade.presentation.library.components.LazyLibraryGrid
import eu.kanade.presentation.library.components.globalSearchItem
@ -45,10 +45,10 @@ fun AnimelibComfortableGrid(
MangaComfortableGridItem(
isSelected = selection.fastAny { it.id == animelibItem.animelibAnime.id },
title = anime.title,
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -6,8 +6,8 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.util.fastAny
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.animelib.model.AnimelibAnime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.presentation.components.MangaCompactGridItem
import eu.kanade.presentation.library.components.LazyLibraryGrid
import eu.kanade.presentation.library.components.globalSearchItem
@ -46,10 +46,10 @@ fun AnimelibCompactGrid(
MangaCompactGridItem(
isSelected = selection.fastAny { it.id == animelibItem.animelibAnime.id },
title = anime.title.takeIf { showTitle },
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -11,8 +11,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.zIndex
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.animelib.model.AnimelibAnime
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.presentation.components.FastScrollLazyColumn
import eu.kanade.presentation.components.MangaListItem
import eu.kanade.presentation.util.plus
@ -58,10 +58,10 @@ fun AnimelibList(
MangaListItem(
isSelected = selection.fastAny { it.id == animelibItem.animelibAnime.id },
title = anime.title,
coverData = MangaCover(
mangaId = anime.id,
coverData = AnimeCover(
animeId = anime.id,
sourceId = anime.source,
isMangaFavorite = anime.favorite,
isAnimeFavorite = anime.favorite,
url = anime.thumbnailUrl,
lastModified = anime.coverLastModified,
),

View file

@ -59,7 +59,7 @@ private const val GridSelectedCoverAlpha = 0.76f
fun MangaCompactGridItem(
isSelected: Boolean = false,
title: String? = null,
coverData: eu.kanade.domain.manga.model.MangaCover,
coverData: eu.kanade.domain.manga.model.CommonCover,
coverAlpha: Float = 1f,
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
@ -142,7 +142,7 @@ private fun BoxScope.CoverTextOverlay(
fun MangaComfortableGridItem(
isSelected: Boolean = false,
title: String,
coverData: eu.kanade.domain.manga.model.MangaCover,
coverData: eu.kanade.domain.manga.model.CommonCover,
coverAlpha: Float = 1f,
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
@ -308,7 +308,7 @@ private fun Modifier.selectedOutline(
fun MangaListItem(
isSelected: Boolean = false,
title: String,
coverData: eu.kanade.domain.manga.model.MangaCover,
coverData: eu.kanade.domain.manga.model.CommonCover,
coverAlpha: Float = 1f,
badge: @Composable RowScope.() -> Unit,
showContinueReadingButton: Boolean = false,

View file

@ -183,6 +183,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
}
callFactory(callFactoryInit)
diskCache(diskCacheInit)
diskCache(diskCacheInit)
crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice)
if (networkPreferences.verboseLogging().get()) logger(DebugLogger())
@ -275,3 +276,24 @@ internal object CoilDiskCache {
}
}
}
/**
* 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

@ -10,7 +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.domain.anime.model.AnimeCover
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
@ -310,18 +310,18 @@ class AnimeCoverFetcher(
class AnimeCoverFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<MangaCover> {
) : Fetcher.Factory<AnimeCover> {
private val coverCache: AnimeCoverCache by injectLazy()
private val sourceManager: AnimeSourceManager by injectLazy()
override fun create(data: MangaCover, options: Options, imageLoader: ImageLoader): Fetcher {
override fun create(data: AnimeCover, options: Options, imageLoader: ImageLoader): Fetcher {
return AnimeCoverFetcher(
url = data.url,
isLibraryAnime = data.isMangaFavorite,
isLibraryAnime = data.isAnimeFavorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.mangaId) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.animeId) },
diskCacheKeyLazy = lazy { AnimeCoverKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.sourceId) as? AnimeHttpSource },
callFactoryLazy = callFactoryLazy,

View file

@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.data.coil
import coil.key.Keyer
import coil.request.Options
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.domain.anime.model.hasCustomCover
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.toDomainAnime
@ -14,9 +14,9 @@ import eu.kanade.domain.anime.model.Anime as DomainAnime
class AnimeKeyer : Keyer<Anime> {
override fun key(data: Anime, options: Options): String {
return if (data.toDomainAnime()!!.hasCustomCover()) {
"${data.id};${data.cover_last_modified}"
"anime;${data.id};${data.cover_last_modified}"
} else {
"${data.thumbnail_url};${data.cover_last_modified}"
"anime;${data.thumbnail_url};${data.cover_last_modified}"
}
}
}
@ -24,19 +24,19 @@ class AnimeKeyer : Keyer<Anime> {
class DomainAnimeKeyer : Keyer<DomainAnime> {
override fun key(data: DomainAnime, options: Options): String {
return if (data.hasCustomCover()) {
"${data.id};${data.coverLastModified}"
"anime;${data.id};${data.coverLastModified}"
} else {
"${data.thumbnailUrl};${data.coverLastModified}"
"anime;${data.thumbnailUrl};${data.coverLastModified}"
}
}
}
class AnimeCoverKeyer : Keyer<MangaCover> {
override fun key(data: MangaCover, options: Options): String {
return if (Injekt.get<AnimeCoverCache>().getCustomCoverFile(data.mangaId).exists()) {
"${data.mangaId};${data.lastModified}"
class AnimeCoverKeyer : Keyer<AnimeCover> {
override fun key(data: AnimeCover, options: Options): String {
return if (Injekt.get<AnimeCoverCache>().getCustomCoverFile(data.animeId).exists()) {
"anime;${data.animeId};${data.lastModified}"
} else {
"${data.url};${data.lastModified}"
"anime;${data.url};${data.lastModified}"
}
}
}

View file

@ -14,9 +14,9 @@ import eu.kanade.domain.manga.model.Manga as DomainManga
class MangaKeyer : Keyer<Manga> {
override fun key(data: Manga, options: Options): String {
return if (data.toDomainManga()!!.hasCustomCover()) {
"${data.id};${data.cover_last_modified}"
"manga;${data.id};${data.cover_last_modified}"
} else {
"${data.thumbnail_url};${data.cover_last_modified}"
"manga;${data.thumbnail_url};${data.cover_last_modified}"
}
}
}
@ -24,9 +24,9 @@ class MangaKeyer : Keyer<Manga> {
class DomainMangaKeyer : Keyer<DomainManga> {
override fun key(data: DomainManga, options: Options): String {
return if (data.hasCustomCover()) {
"${data.id};${data.coverLastModified}"
"manga;${data.id};${data.coverLastModified}"
} else {
"${data.thumbnailUrl};${data.coverLastModified}"
"manga;${data.thumbnailUrl};${data.coverLastModified}"
}
}
}
@ -34,9 +34,9 @@ class DomainMangaKeyer : Keyer<DomainManga> {
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}"
"manga;${data.mangaId};${data.lastModified}"
} else {
"${data.url};${data.lastModified}"
"manga;${data.url};${data.lastModified}"
}
}
}

View file

@ -44,7 +44,7 @@ import coil.size.Precision
import coil.size.Scale
import coil.transform.RoundedCornersTransformation
import eu.kanade.data.AnimeDatabaseHandler
import eu.kanade.domain.manga.model.MangaCover
import eu.kanade.domain.anime.model.AnimeCover
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.ui.anime.AnimeController
@ -223,10 +223,10 @@ class AnimeUpdatesGridGlanceWidget : GlanceAppWidget() {
.map { animeupdatesView ->
val request = ImageRequest.Builder(app)
.data(
MangaCover(
mangaId = animeupdatesView.animeId,
AnimeCover(
animeId = animeupdatesView.animeId,
sourceId = animeupdatesView.source,
isMangaFavorite = animeupdatesView.favorite,
isAnimeFavorite = animeupdatesView.favorite,
url = animeupdatesView.thumbnailUrl,
lastModified = animeupdatesView.coverLastModified,
),