refactor(cover): Data class for manga cover

This commit is contained in:
Ahmad Ansori Palembani 2024-08-18 18:38:39 +07:00
parent 8ad123956c
commit 839f762fa7
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
20 changed files with 191 additions and 80 deletions

View file

@ -39,6 +39,7 @@ import eu.kanade.tachiyomi.core.preference.PreferenceStore
import eu.kanade.tachiyomi.data.coil.BufferedSourceFetcher
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.PreferencesHelper
@ -243,8 +244,10 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
add(TachiyomiImageDecoder.Factory())
// Fetcher.Factory
add(BufferedSourceFetcher.Factory())
add(MangaCoverFetcher.Factory(callFactoryLazy))
add(MangaCoverFetcher.MangaFactory(callFactoryLazy))
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy))
// Keyer
add(MangaKeyer())
add(MangaCoverKeyer())
}
crossfade(true)

View file

@ -37,10 +37,12 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchIO
import java.util.Calendar
import java.util.Date
import kotlin.math.min
import kotlinx.coroutines.MainScope
import uy.kohesive.injekt.injectLazy
import java.util.*
import kotlin.math.min
import yokai.domain.manga.models.cover
class UpdatesGridGlanceWidget : GlanceAppWidget() {
private val app: Application by injectLazy()
@ -97,7 +99,7 @@ class UpdatesGridGlanceWidget : GlanceAppWidget() {
.map { it.first }
.map { updatesView ->
val request = ImageRequest.Builder(app)
.data(updatesView)
.data(updatesView.cover())
.memoryCachePolicy(CachePolicy.DISABLED)
.precision(Precision.EXACT)
.size(widthPx, heightPx)

View file

@ -11,8 +11,6 @@ import androidx.glance.layout.ContentScale
import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.size
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import eu.kanade.tachiyomi.appwidget.util.appWidgetInnerRadius
val CoverWidth = 58.dp

View file

@ -158,8 +158,10 @@ class CoverCache(val context: Context) {
* @param manga the manga.
* @return cover image.
*/
fun getCustomCoverFile(manga: Manga): File {
return File(customCoverCacheDir, DiskUtil.hashKeyForDisk(manga.id.toString()))
fun getCustomCoverFile(manga: Manga): File = getCustomCoverFile(manga.id)
fun getCustomCoverFile(mangaId: Long?): File {
return File(customCoverCacheDir, DiskUtil.hashKeyForDisk(mangaId.toString()))
}
/**

View file

@ -11,29 +11,29 @@ import coil3.request.ImageRequest
import coil3.target.ImageViewTarget
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.updateCoverLastModified
import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.util.system.launchIO
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.models.MangaCover
class LibraryMangaImageTarget(
override val view: ImageView,
val manga: Manga,
val cover: MangaCover,
) : ImageViewTarget(view) {
private val coverCache: CoverCache by injectLazy()
override fun onError(error: Image?) {
super.onError(error)
if (manga.favorite) {
if (cover.inLibrary) {
launchIO {
val file = coverCache.getCoverFile(manga.thumbnail_url, false)
val file = coverCache.getCoverFile(cover.url, false)
// if the file exists and the there was still an error then the file is corrupted
if (file != null && file.exists()) {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(file.path, options)
if (options.outWidth == -1 || options.outHeight == -1) {
manga.updateCoverLastModified()
cover.updateCoverLastModified()
file.delete()
}
}
@ -44,13 +44,13 @@ class LibraryMangaImageTarget(
@JvmSynthetic
inline fun ImageView.loadManga(
manga: Manga,
cover: MangaCover,
imageLoader: ImageLoader = context.imageLoader,
builder: ImageRequest.Builder.() -> Unit = {},
): Disposable {
val request = ImageRequest.Builder(context)
.data(manga)
.target(LibraryMangaImageTarget(this, manga))
.data(cover)
.target(LibraryMangaImageTarget(this, cover))
.apply(builder)
.build()
return imageLoader.enqueue(request)

View file

@ -39,9 +39,12 @@ import okio.buffer
import okio.sink
import okio.source
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.models.MangaCover
class MangaCoverFetcher(
private val manga: Manga,
private val mangaId: Long?,
private val url: String?,
private val isInLibrary: Boolean,
private val sourceLazy: Lazy<HttpSource?>,
private val options: Options,
private val callFactoryLazy: Lazy<Call.Factory>,
@ -53,7 +56,6 @@ class MangaCoverFetcher(
private val diskCacheKey: String
get() = diskCacheKeyLazy.value
private lateinit var url: String
private val fileScope = CoroutineScope(Job() + Dispatchers.IO)
@ -61,21 +63,21 @@ class MangaCoverFetcher(
if (options.extras.getOrDefault(USE_CUSTOM_COVER_KEY)) {
val customCoverFile = customCoverFileLazy.value
if (customCoverFile.exists()) {
setRatioAndColorsInScope(manga, UniFile.fromFile(customCoverFile))
setRatioAndColorsInScope(mangaId, url, isInLibrary, UniFile.fromFile(customCoverFile))
return fileLoader(customCoverFile)
}
}
url = manga.thumbnail_url ?: error("No cover specified")
if (url == null) error("No cover specified")
return when (getResourceType(url)) {
Type.URL -> httpLoader()
Type.File -> {
val file = File(url.substringAfter("file://"))
setRatioAndColorsInScope(manga, UniFile.fromFile(file))
setRatioAndColorsInScope(mangaId, url, isInLibrary, UniFile.fromFile(file))
fileLoader(file)
}
Type.URI -> {
setRatioAndColorsInScope(manga, UniFile.fromUri(options.context, url.toUri()))
setRatioAndColorsInScope(mangaId, url, isInLibrary, UniFile.fromUri(options.context, url.toUri()))
fileUriLoader(url)
}
null -> error("Invalid image")
@ -109,10 +111,10 @@ class MangaCoverFetcher(
private suspend fun httpLoader(): FetchResult {
val coverFile = coverFileLazy.value
if (coverFile?.exists() == true && options.diskCachePolicy.readEnabled) {
if (!manga.favorite) {
if (!isInLibrary) {
coverFile.setLastModified(Date().time)
}
setRatioAndColorsInScope(manga, UniFile.fromFile(coverFile))
setRatioAndColorsInScope(mangaId, url, isInLibrary, UniFile.fromFile(coverFile))
return fileLoader(coverFile)
}
@ -123,12 +125,12 @@ class MangaCoverFetcher(
val snapshotCoverCache = moveSnapshotToCoverCache(snapshot, coverFile)
if (snapshotCoverCache != null) {
// Read from cover cache after added to library
setRatioAndColorsInScope(manga, UniFile.fromFile(snapshotCoverCache))
setRatioAndColorsInScope(mangaId, url, isInLibrary, UniFile.fromFile(snapshotCoverCache))
return fileLoader(snapshotCoverCache)
}
// Read from snapshot
setRatioAndColorsInScope(manga)
setRatioAndColorsInScope(mangaId, url, isInLibrary)
return SourceFetchResult(
source = snapshot.toImageSource(),
mimeType = "image/*",
@ -142,7 +144,7 @@ class MangaCoverFetcher(
try {
// Read from cover cache after library manga cover updated
val responseCoverCache = writeResponseToCoverCache(response, coverFile)
setRatioAndColorsInScope(manga)
setRatioAndColorsInScope(mangaId, url, isInLibrary)
if (responseCoverCache != null) {
return fileLoader(responseCoverCache)
}
@ -185,7 +187,7 @@ class MangaCoverFetcher(
private fun newRequest(): Request {
val request = Request.Builder().apply {
url(url)
url(url!!)
val sourceHeaders = sourceLazy.value?.headers
if (sourceHeaders != null)
@ -293,9 +295,9 @@ class MangaCoverFetcher(
)
}
private fun setRatioAndColorsInScope(manga: Manga, ogFile: UniFile? = null, force: Boolean = false) {
private fun setRatioAndColorsInScope(mangaId: Long?, mangaThumbnailUrl: String?, isInLibrary: Boolean, ogFile: UniFile? = null, force: Boolean = false) {
fileScope.launch {
MangaCoverMetadata.setRatioAndColors(manga, ogFile, force)
MangaCoverMetadata.setRatioAndColors(mangaId, mangaThumbnailUrl, isInLibrary, ogFile, force)
}
}
@ -324,7 +326,7 @@ class MangaCoverFetcher(
}
}
class Factory(
class MangaFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
) : Fetcher.Factory<Manga> {
@ -333,7 +335,9 @@ class MangaCoverFetcher(
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
manga = data,
mangaId = data.id,
url = data.thumbnail_url,
isInLibrary = data.favorite,
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
options = options,
callFactoryLazy = callFactoryLazy,
@ -345,6 +349,29 @@ class MangaCoverFetcher(
}
}
class MangaCoverFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
) : 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(
mangaId = data.mangaId,
url = data.url,
isInLibrary = data.inLibrary,
sourceLazy = lazy { sourceManager.get(data.sourceId) as? HttpSource },
options = options,
callFactoryLazy = callFactoryLazy,
diskCacheKeyLazy = lazy { imageLoader.components.key(data, options)!! },
coverFileLazy = lazy { coverCache.getCoverFile(data.url, !data.inLibrary) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.mangaId) },
imageLoader = imageLoader,
)
}
}
private enum class Type {
File, URL, URI;
}

View file

@ -2,11 +2,15 @@ package eu.kanade.tachiyomi.data.coil
import coil3.key.Keyer
import coil3.request.Options
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.hasCustomCover
import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.util.storage.DiskUtil
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.manga.models.MangaCover
class MangaCoverKeyer : Keyer<Manga> {
class MangaKeyer : Keyer<Manga> {
override fun key(data: Manga, options: Options): String {
val key = when {
data.hasCustomCover() -> data.id
@ -17,3 +21,15 @@ class MangaCoverKeyer : Keyer<Manga> {
return "${key};${data.cover_last_modified}"
}
}
class MangaCoverKeyer(private val coverCache: CoverCache = Injekt.get()) : Keyer<MangaCover> {
override fun key(data: MangaCover, options: Options): String {
val key = when {
coverCache.getCustomCoverFile(data.mangaId).exists() -> data.mangaId
data.inLibrary -> DiskUtil.hashKeyForDisk(data.url)
else -> data.url
}
return "${key};${data.lastModified}"
}
}

View file

@ -23,6 +23,7 @@ import uy.kohesive.injekt.injectLazy
import yokai.data.updateStrategyAdapter
import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.MangaCover
import yokai.domain.manga.models.MangaUpdate
import yokai.i18n.MR
import yokai.util.lang.getString
@ -175,6 +176,12 @@ var Manga.dominantCoverColors: Pair<Int, Int>?
MangaCoverMetadata.addCoverColor(this, value.first, value.second)
}
var Manga.vibrantCoverColor: Int?
get() = MangaCoverMetadata.getVibrantColor(id)
set(value) {
id?.let { MangaCoverMetadata.setVibrantColor(it, value) }
}
fun Manga.Companion.create(source: Long) = MangaImpl().apply {
this.source = source
}
@ -269,3 +276,7 @@ suspend fun Manga.updateCoverLastModified(updateManga: UpdateManga = Injekt.get(
cover_last_modified = System.currentTimeMillis()
updateManga.await(MangaUpdate(id = id!!, coverLastModified = cover_last_modified))
}
suspend fun MangaCover.updateCoverLastModified(updateManga: UpdateManga = Injekt.get()) {
updateManga.await(MangaUpdate(id = mangaId!!, coverLastModified = System.currentTimeMillis()))
}

View file

@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.backgroundColor
import eu.kanade.tachiyomi.util.view.setCards
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import yokai.domain.manga.models.cover
/**
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
@ -125,7 +126,7 @@ class LibraryGridHolder(
private fun setCover(manga: Manga) {
if ((adapter.recyclerView.context as? Activity)?.isDestroyed == true) return
binding.coverThumbnail.loadManga(manga) {
binding.coverThumbnail.loadManga(manga.cover()) {
val hasRatio = binding.coverThumbnail.layoutParams.height != ViewGroup.LayoutParams.WRAP_CONTENT
if (!fixedSize && !hasRatio) {
precision(Precision.INEXACT)

View file

@ -5,15 +5,14 @@ import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import coil3.dispose
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.databinding.MangaListItemBinding
import eu.kanade.tachiyomi.util.lang.highlightText
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.setCards
import yokai.domain.manga.models.cover
import yokai.i18n.MR
import yokai.util.lang.getString
/**
* Class used to hold the displayed data of a manga in the library, like the cover or the binding.title.
@ -97,7 +96,7 @@ class LibraryListHolder(
// Update the cover.
binding.coverThumbnail.dispose()
binding.coverThumbnail.loadManga(item.manga)
binding.coverThumbnail.loadManga(item.manga.cover())
}
override fun onActionStateChanged(position: Int, actionState: Int) {

View file

@ -1633,7 +1633,7 @@ class LibraryPresenter(
) {
val libraryManga = getManga.awaitFavorites()
libraryManga.forEach { manga ->
try { withUIContext { MangaCoverMetadata.setRatioAndColors(manga) } } catch (_: Exception) { }
try { withUIContext { MangaCoverMetadata.setRatioAndColors(manga.id, manga.thumbnail_url, manga.favorite) } } catch (_: Exception) { }
}
MangaCoverMetadata.savePrefs()
}

View file

@ -41,6 +41,7 @@ import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.models.cover
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
@ -98,7 +99,7 @@ class EditMangaDialog : DialogController {
fun onViewCreated() {
val context = binding.root.context
binding.mangaCover.loadManga(manga)
binding.mangaCover.loadManga(manga.cover())
val isLocal = manga.isLocal()
binding.mangaLang.isVisible = isLocal

View file

@ -61,6 +61,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.seriesType
import eu.kanade.tachiyomi.data.database.models.vibrantCoverColor
import eu.kanade.tachiyomi.data.download.DownloadJob
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.notification.NotificationReceiver

View file

@ -47,6 +47,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.isInNightMode
import eu.kanade.tachiyomi.util.system.isLTR
import eu.kanade.tachiyomi.util.view.resetStrokeColor
import yokai.domain.manga.models.cover
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
@ -671,7 +672,7 @@ class MangaHeaderHolder(
if (!manga.initialized) return
val drawable = adapter.controller.binding.mangaCoverFull.drawable
binding.mangaCover.loadManga(
manga,
manga.cover(),
builder = {
placeholder(drawable)
error(drawable)
@ -680,7 +681,7 @@ class MangaHeaderHolder(
},
)
binding.backdrop.loadManga(
manga,
manga.cover(),
builder = {
placeholder(drawable)
error(drawable)

View file

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.databinding.MangaListItemBinding
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.view.setCards
import yokai.domain.manga.models.cover
class MangaHolder(
view: View,
@ -29,6 +30,6 @@ class MangaHolder(
// Update the cover.
binding.coverThumbnail.dispose()
binding.coverThumbnail.loadManga(item.manga)
binding.coverThumbnail.loadManga(item.manga.cover())
}
}

View file

@ -16,9 +16,6 @@ import androidx.core.view.updatePaddingRelative
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.ChapterHistory
@ -37,6 +34,9 @@ import eu.kanade.tachiyomi.util.view.setAnimVectorCompat
import eu.kanade.tachiyomi.util.view.setCards
import java.util.*
import java.util.concurrent.*
import yokai.domain.manga.models.cover
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
class RecentMangaHolder(
@ -213,7 +213,7 @@ class RecentMangaHolder(
else -> context.timeSpanFromNow(MR.strings.read_, item.mch.history.last_read)
}
if ((context as? Activity)?.isDestroyed != true) {
binding.coverThumbnail.loadManga(item.mch.manga)
binding.coverThumbnail.loadManga(item.mch.manga.cover())
}
if (!item.mch.manga.isLocal()) {
notifyStatus(

View file

@ -6,7 +6,6 @@ import androidx.palette.graphics.Palette
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.coil.getBestColor
import eu.kanade.tachiyomi.data.database.models.dominantCoverColors
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.domain.manga.models.Manga
import java.util.concurrent.ConcurrentHashMap
@ -16,6 +15,7 @@ import uy.kohesive.injekt.injectLazy
object MangaCoverMetadata {
private var coverRatioMap = ConcurrentHashMap<Long, Float>()
private var coverColorMap = ConcurrentHashMap<Long, Pair<Int, Int>>()
private var vibrantCoverColorMap = ConcurrentHashMap<Long, Int>()
private val preferences by injectLazy<PreferencesHelper>()
private val coverCache by injectLazy<CoverCache>()
@ -49,19 +49,19 @@ object MangaCoverMetadata {
)
}
fun setRatioAndColors(manga: Manga, ogFile: UniFile? = null, force: Boolean = false) {
if (!manga.favorite) {
remove(manga)
fun setRatioAndColors(mangaId: Long?, mangaThumbnailUrl: String?, isInLibrary: Boolean, ogFile: UniFile? = null, force: Boolean = false) {
if (!isInLibrary) {
remove(mangaId)
}
if (manga.vibrantCoverColor != null && !manga.favorite) return
if (getVibrantColor(mangaId) != null && !isInLibrary) return
val file = ogFile
?: UniFile.fromFile(coverCache.getCustomCoverFile(manga))?.takeIf { it.exists() }
?: UniFile.fromFile(coverCache.getCoverFile(manga.thumbnail_url, !manga.favorite))
?: UniFile.fromFile(coverCache.getCustomCoverFile(mangaId))?.takeIf { it.exists() }
?: UniFile.fromFile(coverCache.getCoverFile(mangaThumbnailUrl, !isInLibrary))
// if the file exists and the there was still an error then the file is corrupted
if (file?.exists() == true) {
val options = BitmapFactory.Options()
val hasVibrantColor = if (manga.favorite) manga.vibrantCoverColor != null else true
if (manga.dominantCoverColors != null && hasVibrantColor && !force) {
val hasVibrantColor = if (isInLibrary) vibrantCoverColorMap[mangaId] != null else true
if (getColors(mangaId) != null && hasVibrantColor && !force) {
options.inJustDecodeBounds = true
} else {
options.inSampleSize = 4
@ -70,45 +70,74 @@ object MangaCoverMetadata {
if (bitmap != null) {
Palette.from(bitmap).generate {
if (it == null) return@generate
if (manga.favorite) {
if (isInLibrary) {
it.dominantSwatch?.let { swatch ->
manga.dominantCoverColors = swatch.rgb to swatch.titleTextColor
addCoverColor(mangaId, swatch.rgb, swatch.titleTextColor)
}
}
val color = it.getBestColor() ?: return@generate
manga.vibrantCoverColor = color
setVibrantColor(mangaId, color)
}
}
if (manga.favorite && !(options.outWidth == -1 || options.outHeight == -1)) {
addCoverRatio(manga, options.outWidth / options.outHeight.toFloat())
if (isInLibrary && !(options.outWidth == -1 || options.outHeight == -1)) {
addCoverRatio(mangaId, options.outWidth / options.outHeight.toFloat())
}
}
}
fun remove(manga: Manga) {
val id = manga.id ?: return
coverRatioMap.remove(id)
coverColorMap.remove(id)
remove(manga.id)
}
fun remove(mangaId: Long?) {
mangaId ?: return
coverRatioMap.remove(mangaId)
coverColorMap.remove(mangaId)
}
fun addCoverRatio(manga: Manga, ratio: Float) {
val id = manga.id ?: return
coverRatioMap[id] = ratio
addCoverRatio(manga.id, ratio)
}
fun addCoverRatio(mangaId: Long?, ratio: Float) {
mangaId ?: return
coverRatioMap[mangaId] = ratio
}
fun addCoverColor(manga: Manga, @ColorInt color: Int, @ColorInt textColor: Int) {
val id = manga.id ?: return
coverColorMap[id] = color to textColor
addCoverColor(manga.id, color, textColor)
}
fun getColors(manga: Manga): Pair<Int, Int>? {
return coverColorMap[manga.id]
fun addCoverColor(mangaId: Long?, @ColorInt color: Int, @ColorInt textColor: Int) {
mangaId ?: return
coverColorMap[mangaId] = color to textColor
}
fun getColors(manga: Manga): Pair<Int, Int>? = getColors(manga.id)
fun getColors(mangaId: Long?): Pair<Int, Int>? {
return coverColorMap[mangaId]
}
fun getRatio(manga: Manga): Float? {
return coverRatioMap[manga.id]
}
fun setVibrantColor(mangaId: Long?, @ColorInt color: Int?) {
mangaId ?: return
if (color == null) {
vibrantCoverColorMap.remove(mangaId)
return
}
vibrantCoverColorMap[mangaId] = color
}
fun getVibrantColor(mangaId: Long?): Int? {
return vibrantCoverColorMap[mangaId]
}
fun savePrefs() {
val mapCopy = coverRatioMap.toMap()
preferences.coverRatios().set(mapCopy.map { "${it.key}|${it.value}" }.toSet())

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.domain.manga.models
import eu.kanade.tachiyomi.source.model.SManga
import java.util.Locale
import kotlin.collections.set
import yokai.domain.manga.models.MangaUpdate
// TODO: Transform into data class
@ -197,12 +196,6 @@ interface Manga : SManga {
get() = chapter_flags and CHAPTER_SORTING_MASK
set(sort) = setChapterFlags(sort, CHAPTER_SORTING_MASK)
var vibrantCoverColor: Int?
get() = vibrantCoverColorMap[id]
set(value) {
id?.let { vibrantCoverColorMap[it] = value }
}
fun toMangaUpdate(): MangaUpdate {
return MangaUpdate(
id = id!!,
@ -268,7 +261,5 @@ interface Manga : SManga {
const val TYPE_MANHUA = 3
const val TYPE_COMIC = 4
const val TYPE_WEBTOON = 5
private val vibrantCoverColorMap: HashMap<Long, Int?> = hashMapOf()
}
}

View file

@ -23,4 +23,5 @@ data class Manga(
var chapterFlags: Int,
var hideTitle: Boolean,
var filteredScanlators: String?,
var coverLastModified: Long,
): Serializable

View file

@ -0,0 +1,27 @@
package yokai.domain.manga.models
import eu.kanade.tachiyomi.domain.manga.models.Manga as TachiManga
data class MangaCover(
val mangaId: Long?,
val sourceId: Long,
val url: String,
val lastModified: Long,
val inLibrary: Boolean,
)
fun TachiManga.cover() = MangaCover(
mangaId = id,
sourceId = source,
url = thumbnail_url ?: "",
lastModified = cover_last_modified,
inLibrary = favorite,
)
fun Manga.cover() = MangaCover(
mangaId = id,
sourceId = source,
url = thumbnailUrl ?: "",
lastModified = coverLastModified,
inLibrary = favorite,
)