refactor: Replace more Manga class usage

This commit is contained in:
Ahmad Ansori Palembani 2024-06-29 19:06:29 +07:00
parent 5ddc44dcd7
commit 690ece36ef
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
15 changed files with 168 additions and 167 deletions

View file

@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
import eu.kanade.tachiyomi.data.backup.models.BackupSource
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.manga.models.Manga
class SourcesBackupCreator(
private val sourceManager: SourceManager = Injekt.get(),

View file

@ -11,9 +11,9 @@ import coil3.request.Disposable
import coil3.request.ImageRequest
import coil3.target.ImageViewTarget
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.system.launchIO
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.models.Manga
class LibraryMangaImageTarget(
override val view: ImageView,

View file

@ -15,7 +15,6 @@ import coil3.getOrDefault
import coil3.request.Options
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
@ -36,6 +35,7 @@ import okio.buffer
import okio.sink
import okio.source
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.models.Manga
import java.io.File
import java.net.HttpURLConnection
import java.util.*
@ -57,7 +57,7 @@ class MangaCoverFetcher(
override suspend fun fetch(): FetchResult {
// diskCacheKey is thumbnail_url
url = manga.thumbnail_url ?: error("No cover specified")
url = manga.thumbnailUrl ?: error("No cover specified")
return when (getResourceType(url)) {
Type.URL -> httpLoader()
Type.File -> {

View file

@ -2,16 +2,16 @@ package eu.kanade.tachiyomi.data.coil
import coil3.key.Keyer
import coil3.request.Options
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.storage.DiskUtil
import yokai.domain.manga.models.Manga
class MangaCoverKeyer : Keyer<Manga> {
override fun key(data: Manga, options: Options): String? {
if (data.thumbnail_url.isNullOrBlank()) return null
if (data.thumbnailUrl.isNullOrBlank()) return null
return if (!data.favorite) {
data.thumbnail_url!!
data.thumbnailUrl!!
} else {
DiskUtil.hashKeyForDisk(data.thumbnail_url!!)
DiskUtil.hashKeyForDisk(data.thumbnailUrl!!)
}
}
}

View file

@ -1,3 +1,5 @@
package eu.kanade.tachiyomi.data.database.models
import yokai.domain.manga.models.Manga
class MangaChapter(val manga: Manga, val chapter: Chapter)

View file

@ -1,5 +1,8 @@
package eu.kanade.tachiyomi.data.database.models
import yokai.domain.history.models.History
import yokai.domain.manga.models.Manga
/**
* Object containing manga, chapter and history
*
@ -10,7 +13,11 @@ package eu.kanade.tachiyomi.data.database.models
data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History, var extraChapters: List<ChapterHistory> = emptyList()) {
companion object {
fun createBlank() = MangaChapterHistory(MangaImpl(), ChapterImpl(), HistoryImpl())
fun createBlank() = MangaChapterHistory(
Manga(-1L, url = "", ogTitle = ""),
ChapterImpl(),
History(chapterId = -1L),
)
}
}

View file

@ -5,10 +5,6 @@ import android.view.HapticFeedbackConstants
import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
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.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -21,6 +17,8 @@ import eu.kanade.tachiyomi.util.system.withDefContext
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.injectLazy
import yokai.domain.ui.UiPreferences
import yokai.i18n.MR
import yokai.util.lang.getString
import java.util.*
/**
@ -118,7 +116,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
fun indexOf(manga: Manga): Int {
return currentItems.indexOfFirst {
if (it is LibraryItem) {
it.manga.id == manga.id
it.library.id == manga.id
} else {
false
}
@ -142,7 +140,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
*/
fun allIndexOf(manga: Manga): List<Int> {
return currentItems.mapIndexedNotNull { index, it ->
if (it is LibraryItem && it.manga.id == manga.id) {
if (it is LibraryItem && it.library.id == manga.id) {
index
} else {
null
@ -164,7 +162,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
} else {
val filteredManga = withDefContext { mangas.filter { it.filter(s) } }
if (filteredManga.isEmpty() && controller?.presenter?.showAllCategories == false) {
val catId = mangas.firstOrNull()?.let { it.header?.catId ?: it.manga.category }
val catId = mangas.firstOrNull()?.let { it.header?.catId ?: it.library.category }
val blankItem = catId?.let { controller.presenter.blankItem(it) }
updateDataSet(blankItem ?: emptyList())
} else {
@ -201,16 +199,16 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
item.category.name
}
is LibraryItem -> {
val text = if (item.manga.isBlank()) {
val text = if (item.library.isBlank()) {
return item.header?.category?.name.orEmpty()
} else {
when (getSort(position)) {
LibrarySort.DragAndDrop -> {
if (item.header.category.isDynamic) {
val category = db.getCategoriesForManga(item.manga).executeAsBlocking().firstOrNull()?.name
val category = db.getCategoriesForManga(item.library).executeAsBlocking().firstOrNull()?.name
category ?: context.getString(MR.strings.default_value)
} else {
val title = item.manga.title
val title = item.library.title
if (preferences.removeArticles().get()) {
title.removeArticles().chop(15)
} else {
@ -219,19 +217,19 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
}
}
LibrarySort.DateFetched -> {
val id = item.manga.id ?: return ""
val id = item.library.id ?: return ""
val history = db.getChapters(id).executeAsBlocking()
val last = history.maxOfOrNull { it.date_fetch }
context.timeSpanFromNow(MR.strings.fetched_, last ?: 0)
}
LibrarySort.LastRead -> {
val id = item.manga.id ?: return ""
val id = item.library.id ?: return ""
val history = db.getHistoryByMangaId(id).executeAsBlocking()
val last = history.maxOfOrNull { it.last_read }
context.timeSpanFromNow(MR.strings.read_, last ?: 0)
}
LibrarySort.Unread -> {
val unread = item.manga.unread
val unread = item.library.unread
if (unread > 0) {
context.getString(MR.strings._unread, unread)
} else {
@ -239,7 +237,7 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
}
}
LibrarySort.TotalChapters -> {
val total = item.manga.totalChapters
val total = item.library.totalChapters
if (total > 0) {
recyclerView.context.getString(
MR.plurals.chapters_plural,
@ -251,16 +249,16 @@ class LibraryCategoryAdapter(val controller: LibraryController?) :
}
}
LibrarySort.LatestChapter -> {
context.timeSpanFromNow(MR.strings.updated_, item.manga.last_update)
context.timeSpanFromNow(MR.strings.updated_, item.library.last_update)
}
LibrarySort.DateAdded -> {
context.timeSpanFromNow(MR.strings.added_, item.manga.date_added)
context.timeSpanFromNow(MR.strings.added_, item.library.date_added)
}
LibrarySort.Title -> {
val title = if (preferences.removeArticles().get()) {
item.manga.title.removeArticles()
item.library.title.removeArticles()
} else {
item.manga.title
item.library.title
}
getFirstLetter(title)
}

View file

@ -60,7 +60,6 @@ import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.core.preference.Preference
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadJob
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
@ -135,6 +134,7 @@ import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.manga.models.LibraryManga
import yokai.domain.manga.models.Manga
import yokai.domain.ui.UiPreferences
import yokai.i18n.MR
import yokai.util.lang.getString
@ -196,7 +196,7 @@ open class LibraryController(
/**
* Currently selected mangas.
*/
private val selectedMangas = mutableSetOf<Manga>()
private val selectedMangas = mutableSetOf<LibraryManga>()
private var mAdapter: LibraryCategoryAdapter? = null
private val adapter: LibraryCategoryAdapter
@ -519,10 +519,12 @@ open class LibraryController(
}
private fun openRandomManga() {
val items = adapter.currentItems.filter { (it is LibraryItem && !it.manga.isBlank() && !it.manga.isHidden() && (!it.manga.initialized || it.manga.unread > 0)) }
val items = adapter.currentItems.filter {
(it is LibraryItem && !it.library.isBlank() && !it.library.isHidden() && it.library.manga != null && (!it.library.manga.initialized || it.library.unread > 0))
}
if (items.isNotEmpty()) {
val item = items.random() as LibraryItem
openManga(item.manga)
openManga(item.library.manga!!)
}
}
@ -997,7 +999,7 @@ open class LibraryController(
override fun getSpanSize(position: Int): Int {
if (libraryLayout == LibraryItem.LAYOUT_LIST) return managerSpanCount
val item = this@LibraryController.mAdapter?.getItem(position)
return if (item is LibraryHeaderItem || item is SearchGlobalItem || (item is LibraryItem && item.manga.isBlank())) {
return if (item is LibraryHeaderItem || item is SearchGlobalItem || (item is LibraryItem && item.library.isBlank())) {
managerSpanCount
} else {
1
@ -1460,12 +1462,12 @@ open class LibraryController(
adapter.isLongPressDragEnabled = canDrag()
}
private fun setSelection(manga: Manga, selected: Boolean) {
private fun setSelection(manga: LibraryManga, selected: Boolean) {
if (manga.isBlank()) return
val currentMode = adapter.mode
if (selected) {
if (selectedMangas.add(manga)) {
val positions = adapter.allIndexOf(manga)
val positions = adapter.allIndexOf(manga.manga)
if (adapter.mode != SelectableAdapter.Mode.MULTI) {
adapter.mode = SelectableAdapter.Mode.MULTI
}
@ -1480,7 +1482,7 @@ open class LibraryController(
}
} else {
if (selectedMangas.remove(manga)) {
val positions = adapter.allIndexOf(manga)
val positions = adapter.allIndexOf(manga.manga)
lastClickPosition = -1
if (selectedMangas.isEmpty()) {
adapter.mode = SelectableAdapter.Mode.SINGLE
@ -1511,16 +1513,16 @@ open class LibraryController(
toggleSelection(position)
return
}
val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return
val library = (adapter.getItem(position) as? LibraryItem)?.library ?: return
val activity = activity ?: return
val chapter = presenter.getFirstUnread(manga) ?: return
val chapter = presenter.getFirstUnread(library.manga) ?: return
activity.apply {
if (view != null) {
val (intent, bundle) = ReaderActivity
.newIntentWithTransitionOptions(activity, manga, chapter, view)
.newIntentWithTransitionOptions(activity, library.manga, chapter, view)
startActivity(intent, bundle)
} else {
startActivity(ReaderActivity.newIntent(activity, manga, chapter))
startActivity(ReaderActivity.newIntent(activity, library.manga, chapter))
}
}
destroyActionModeIfNeeded()
@ -1528,8 +1530,8 @@ open class LibraryController(
private fun toggleSelection(position: Int) {
val item = adapter.getItem(position) as? LibraryItem ?: return
if (item.manga.isBlank()) return
setSelection(item.manga, !adapter.isSelected(position))
if (item.library.isBlank()) return
setSelection(item.library, !adapter.isSelected(position))
invalidateActionMode()
}
@ -1552,7 +1554,7 @@ open class LibraryController(
toggleSelection(position)
false
} else {
openManga(item.manga)
openManga(item.library)
false
}
}
@ -1577,7 +1579,7 @@ open class LibraryController(
if (item !is LibraryItem) return
snack?.dismiss()
if (libraryLayout == LibraryItem.LAYOUT_COVER_ONLY_GRID && actionMode == null) {
snack = view?.snack(item.manga.title) {
snack = view?.snack(item.library.title) {
anchorView = activityBinding?.bottomNav
view.elevation = 15f.dpToPx
}
@ -1633,7 +1635,7 @@ open class LibraryController(
private fun setSelection(position: Int, selected: Boolean = true) {
val item = adapter.getItem(position) as? LibraryItem ?: return
setSelection(item.manga, selected)
setSelection(item.library, selected)
invalidateActionMode()
}
@ -1661,8 +1663,8 @@ open class LibraryController(
val newHeader = adapter.getSectionHeader(toPosition) as? LibraryHeaderItem
if (toPosition < 1) return false
return (adapter.getItem(toPosition) !is LibraryHeaderItem) && (
newHeader?.category?.id == item.manga.category || !presenter.mangaIsInCategory(
item.manga,
newHeader?.category?.id == item.library.category || !presenter.mangaIsInCategory(
item.library,
newHeader?.category?.id,
)
)
@ -1683,11 +1685,11 @@ open class LibraryController(
val newHeader = adapter.getSectionHeader(position) as? LibraryHeaderItem
val libraryItems = getSectionItems(adapter.getSectionHeader(position), item)
.filterIsInstance<LibraryItem>()
val mangaIds = libraryItems.mapNotNull { (it as? LibraryItem)?.manga?.id }
if (newHeader?.category?.id == item.manga.category) {
presenter.rearrangeCategory(item.manga.category, mangaIds)
val mangaIds = libraryItems.mapNotNull { (it as? LibraryItem)?.library?.id }
if (newHeader?.category?.id == item.library.category) {
presenter.rearrangeCategory(item.library.category, mangaIds)
} else {
if (presenter.mangaIsInCategory(item.manga, newHeader?.category?.id)) {
if (presenter.mangaIsInCategory(item.library, newHeader?.category?.id)) {
adapter.moveItem(position, lastItemPosition!!)
snack = view?.snack(MR.strings.already_in_category) {
anchorView = anchorView()
@ -1697,7 +1699,7 @@ open class LibraryController(
}
if (newHeader?.category != null) {
moveMangaToCategory(
item.manga,
item.library,
newHeader.category,
mangaIds,
)
@ -1816,7 +1818,7 @@ open class LibraryController(
val item = adapter.findCategoryHeader(catId) ?: return
val libraryItems = adapter.getSectionItems(item)
.filterIsInstance<LibraryItem>()
val mangaIds = libraryItems.mapNotNull { (it as? LibraryItem)?.manga?.id }
val mangaIds = libraryItems.mapNotNull { (it as? LibraryItem)?.library?.id }
presenter.rearrangeCategory(catId, mangaIds)
} else {
presenter.sortCategory(catId, sortBy)

View file

@ -14,11 +14,8 @@ import coil3.dispose
import coil3.size.Precision
import coil3.size.Scale
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.database.models.Manga
import eu.kanade.tachiyomi.data.coil.loadManga
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.MangaGridItemBinding
import eu.kanade.tachiyomi.util.lang.highlightText
import eu.kanade.tachiyomi.util.manga.MangaCoverMetadata
@ -70,20 +67,20 @@ class LibraryGridHolder(
// Update the title and subtitle of the manga.
setCards(adapter.showOutline, binding.card, binding.unreadDownloadBadge.root)
binding.playButton.transitionName = "library chapter $bindingAdapterPosition transition"
binding.constraintLayout.isVisible = !item.manga.isBlank()
binding.title.text = item.manga.title.highlightText(item.filter, color)
binding.behindTitle.text = item.manga.title
val mangaColor = item.manga.dominantCoverColors
binding.constraintLayout.isVisible = !item.library.isBlank()
binding.title.text = item.library.title.highlightText(item.filter, color)
binding.behindTitle.text = item.library.title
val mangaColor = item.library.dominantCoverColors
binding.coverConstraint.backgroundColor = mangaColor?.first ?: itemView.context.getResourceColor(R.attr.background)
binding.behindTitle.setTextColor(
mangaColor?.second ?: itemView.context.getResourceColor(R.attr.colorOnBackground),
)
val authorArtist = if (item.manga.author == item.manga.artist || item.manga.artist.isNullOrBlank()) {
item.manga.author?.trim() ?: ""
val authorArtist = if (item.library.author == item.library.artist || item.library.artist.isNullOrBlank()) {
item.library.author?.trim() ?: ""
} else {
listOfNotNull(
item.manga.author?.trim()?.takeIf { it.isNotBlank() },
item.manga.artist?.trim()?.takeIf { it.isNotBlank() },
item.library.author?.trim()?.takeIf { it.isNotBlank() },
item.library.artist?.trim()?.takeIf { it.isNotBlank() },
).joinToString(", ")
}
binding.subtitle.text = authorArtist.highlightText(item.filter, color)
@ -104,7 +101,7 @@ class LibraryGridHolder(
// Update the cover.
binding.coverThumbnail.dispose()
setCover(item.manga)
setCover(item.library)
}
override fun toggleActivation() {

View file

@ -5,9 +5,6 @@ import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import com.google.android.material.card.MaterialCardView
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.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.system.getResourceColor
@ -47,14 +44,14 @@ abstract class LibraryHolder(
val showTotal = item.header.category.sortingMode() == LibrarySort.TotalChapters
badge.setUnreadDownload(
when {
showTotal -> item.manga.totalChapters
item.unreadType == 2 -> item.manga.unread
item.unreadType == 1 -> if (item.manga.unread > 0) -1 else -2
showTotal -> item.library.totalChapters
item.unreadType == 2 -> item.library.unread
item.unreadType == 1 -> if (item.library.unread > 0) -1 else -2
else -> -2
},
when {
item.downloadCount == -1 -> -1
item.manga.isLocal() -> -2
item.library.isLocal() -> -2
else -> item.downloadCount
},
showTotal,
@ -65,7 +62,7 @@ abstract class LibraryHolder(
fun setReadingButton(item: LibraryItem) {
itemView.findViewById<View>(R.id.play_layout)?.isVisible =
item.manga.unread > 0 && !item.hideReadingButton
item.library.unread > 0 && !item.hideReadingButton
}
/**
@ -80,7 +77,7 @@ abstract class LibraryHolder(
override fun onLongClick(view: View?): Boolean {
return if (adapter.isLongPressDragEnabled) {
val manga = (adapter.getItem(flexibleAdapterPosition) as LibraryItem).manga
val manga = (adapter.getItem(flexibleAdapterPosition) as LibraryItem).library
if (!isDraggable && !manga.isBlank() && !manga.isHidden()) {
adapter.mItemLongClickListener.onItemLongClick(flexibleAdapterPosition)
toggleActivation()

View file

@ -29,7 +29,7 @@ import yokai.domain.manga.models.LibraryManga
import yokai.domain.ui.UiPreferences
class LibraryItem(
val manga: LibraryManga,
val library: LibraryManga,
header: LibraryHeaderItem,
private val context: Context?,
private val uiPreferences: UiPreferences = Injekt.get(),
@ -52,7 +52,7 @@ class LibraryItem(
get() = preferences.hideStartReadingButton().get()
override fun getLayoutRes(): Int {
return if (libraryLayout == LAYOUT_LIST || manga.isBlank()) {
return if (libraryLayout == LAYOUT_LIST || library.isBlank()) {
R.layout.manga_list_item
} else {
R.layout.manga_grid_item
@ -64,7 +64,7 @@ class LibraryItem(
return if (parent is AutofitRecyclerView) {
val libraryLayout = libraryLayout
val isFixedSize = uniformSize
if (libraryLayout == LAYOUT_LIST || manga.isBlank()) {
if (libraryLayout == LAYOUT_LIST || library.isBlank()) {
LibraryListHolder(view, adapter as LibraryCategoryAdapter)
} else {
view.apply {
@ -109,7 +109,7 @@ class LibraryItem(
isFixedSize,
)
if (!isFixedSize) {
gridHolder.setFreeformCoverRatio(manga, parent)
gridHolder.setFreeformCoverRatio(library, parent)
}
gridHolder
}
@ -125,14 +125,14 @@ class LibraryItem(
payloads: MutableList<Any?>?,
) {
if (holder is LibraryGridHolder && !holder.fixedSize) {
holder.setFreeformCoverRatio(manga, adapter.recyclerView as? AutofitRecyclerView)
holder.setFreeformCoverRatio(library, adapter.recyclerView as? AutofitRecyclerView)
}
holder.onSetValues(this)
(holder as? LibraryGridHolder)?.setSelected(adapter.isSelected(position))
val layoutParams = holder.itemView.layoutParams as? StaggeredGridLayoutManager.LayoutParams
layoutParams?.isFullSpan = manga.isBlank()
layoutParams?.isFullSpan = library.isBlank()
if (libraryLayout == LAYOUT_COVER_ONLY_GRID) {
holder.itemView.compatToolTipText = manga.title
holder.itemView.compatToolTipText = library.title
}
}
@ -140,15 +140,15 @@ class LibraryItem(
* Returns true if this item is draggable.
*/
override fun isDraggable(): Boolean {
return !manga.isBlank() && header.category.isDragAndDrop
return !library.isBlank() && header.category.isDragAndDrop
}
override fun isEnabled(): Boolean {
return !manga.isBlank()
return !library.isBlank()
}
override fun isSelectable(): Boolean {
return !manga.isBlank()
return !library.isBlank()
}
/**
@ -159,26 +159,26 @@ class LibraryItem(
*/
override fun filter(constraint: String): Boolean {
filter = constraint
if (manga.isBlank() && manga.title.isBlank()) {
if (library.isBlank() && library.title.isBlank()) {
return constraint.isEmpty()
}
val sourceName by lazy { sourceManager.getOrStub(manga.source).name }
return manga.title.contains(constraint, true) ||
(manga.author?.contains(constraint, true) ?: false) ||
(manga.artist?.contains(constraint, true) ?: false) ||
val sourceName by lazy { sourceManager.getOrStub(library.source).name }
return library.title.contains(constraint, true) ||
(library.author?.contains(constraint, true) ?: false) ||
(library.artist?.contains(constraint, true) ?: false) ||
sourceName.contains(constraint, true) ||
if (constraint.contains(",")) {
val genres = manga.genre?.split(", ")
val genres = library.genre?.split(", ")
constraint.split(",").all { containsGenre(it.trim(), genres) }
} else {
containsGenre(constraint, manga.genre?.split(", "))
containsGenre(constraint, library.genre?.split(", "))
}
}
private fun containsGenre(tag: String, genres: List<String>?): Boolean {
if (tag.trim().isEmpty()) return true
context ?: return false
val seriesType by lazy { manga.seriesType(context, sourceManager) }
val seriesType by lazy { library.seriesType(context, sourceManager) }
return if (tag.startsWith("-")) {
val realTag = tag.substringAfter("-")
genres?.find {
@ -193,13 +193,13 @@ class LibraryItem(
override fun equals(other: Any?): Boolean {
if (other is LibraryItem) {
return manga.id == other.manga.id && manga.category == other.manga.category
return library.id == other.library.id && library.category == other.library.category
}
return false
}
override fun hashCode(): Int {
var result = manga.id!!.hashCode()
var result = library.id!!.hashCode()
result = 31 * result + (header?.hashCode() ?: 0)
return result
}

View file

@ -5,15 +5,13 @@ 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.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.
@ -41,17 +39,17 @@ class LibraryListHolder(
setCards(adapter.showOutline, binding.card, binding.unreadDownloadBadge.root)
binding.title.isVisible = true
binding.constraintLayout.minHeight = 56.dpToPx
if (item.manga.isBlank()) {
if (item.library.isBlank()) {
binding.constraintLayout.minHeight = 0
binding.constraintLayout.updateLayoutParams<ViewGroup.MarginLayoutParams> {
height = ViewGroup.MarginLayoutParams.WRAP_CONTENT
}
if (item.manga.status == -1) {
if (item.library.status == -1) {
binding.title.text = null
binding.title.isVisible = false
} else {
binding.title.text = itemView.context.getString(
if (adapter.hasActiveFilters && item.manga.realMangaCount >= 1) {
if (adapter.hasActiveFilters && item.library.realMangaCount >= 1) {
MR.strings.no_matches_for_filters_short
} else {
MR.strings.category_is_empty
@ -73,16 +71,16 @@ class LibraryListHolder(
binding.title.textAlignment = View.TEXT_ALIGNMENT_TEXT_START
// Update the binding.title of the manga.
binding.title.text = item.manga.title.highlightText(item.filter, color)
binding.title.text = item.library.title.highlightText(item.filter, color)
setUnreadBadge(binding.unreadDownloadBadge.badgeView, item)
val authorArtist =
if (item.manga.author == item.manga.artist || item.manga.artist.isNullOrBlank()) {
item.manga.author?.trim() ?: ""
if (item.library.author == item.library.artist || item.library.artist.isNullOrBlank()) {
item.library.author?.trim() ?: ""
} else {
listOfNotNull(
item.manga.author?.trim()?.takeIf { it.isNotBlank() },
item.manga.artist?.trim()?.takeIf { it.isNotBlank() },
item.library.author?.trim()?.takeIf { it.isNotBlank() },
item.library.artist?.trim()?.takeIf { it.isNotBlank() },
).joinToString(", ")
}
@ -97,7 +95,7 @@ class LibraryListHolder(
// Update the cover.
binding.coverThumbnail.dispose()
binding.coverThumbnail.loadManga(item.manga)
binding.coverThumbnail.loadManga(item.library)
}
override fun onActionStateChanged(position: Int, actionState: Int) {

View file

@ -7,7 +7,6 @@ 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.Chapter.Companion.copy
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
@ -65,6 +64,7 @@ import yokai.domain.manga.interactor.GetLibraryManga
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.LibraryManga
import yokai.domain.manga.models.Manga
import yokai.domain.manga.models.MangaCategory
import yokai.domain.manga.models.MangaUpdate
import yokai.i18n.MR
@ -214,8 +214,8 @@ class LibraryPresenter(
fun getItemCountInCategories(categoryId: Int): Int {
val items = sectionedLibraryItems[categoryId]
return if (items?.firstOrNull()?.manga?.isHidden() == true || items?.firstOrNull()?.manga?.isBlank() == true) {
items.firstOrNull()?.manga?.read ?: 0
return if (items?.firstOrNull()?.library?.isHidden() == true || items?.firstOrNull()?.library?.isBlank() == true) {
items.firstOrNull()?.library?.read ?: 0
} else {
sectionedLibraryItems[categoryId]?.size ?: 0
}
@ -233,7 +233,7 @@ class LibraryPresenter(
}
val (library, _) = withIOContext { getLibraryFromDB() }
val hiddenItems = library.filter { it.manga.isHidden() }.mapNotNull { it.manga.items }.flatten()
val hiddenItems = library.filter { it.library.isHidden() }.mapNotNull { it.library.items }.flatten()
setDownloadCount(library)
setUnreadBadge(library)
setSourceLanguage(library)
@ -296,7 +296,7 @@ class LibraryPresenter(
fun getMangaInCategories(catId: Int?): List<LibraryManga>? {
catId ?: return null
return allLibraryItems.filter { it.header.category.id == catId }.map { it.manga }
return allLibraryItems.filter { it.header.category.id == catId }.map { it.library }
}
private suspend fun sectionLibrary(items: List<LibraryItem>, freshStart: Boolean = false) {
@ -347,12 +347,12 @@ class LibraryPresenter(
val realCount = mutableMapOf<Int, Int>()
val filteredItems = this.filter f@{ item ->
if (showEmptyCategoriesWhileFiltering) {
realCount[item.manga.category] = sectionedLibraryItems[item.manga.category]?.size ?: 0
realCount[item.library.category] = sectionedLibraryItems[item.library.category]?.size ?: 0
}
if (!showEmptyCategoriesWhileFiltering && item.manga.isHidden()) {
val subItems = sectionedLibraryItems[item.manga.category]?.takeUnless { it.size <= 1 }
?: hiddenLibraryItems.filter { it.manga.category == item.manga.category }
if (!showEmptyCategoriesWhileFiltering && item.library.isHidden()) {
val subItems = sectionedLibraryItems[item.library.category]?.takeUnless { it.size <= 1 }
?: hiddenLibraryItems.filter { it.library.category == item.library.category }
if (subItems.isEmpty()) {
return@f filtersOff
} else {
@ -364,8 +364,8 @@ class LibraryPresenter(
)
}
}
} else if (item.manga.isBlank() || item.manga.isHidden()) {
missingCategorySet.remove(item.manga.category)
} else if (item.library.isBlank() || item.library.isHidden()) {
missingCategorySet.remove(item.library.category)
return@f if (showAllCategories) {
filtersOff || showEmptyCategoriesWhileFiltering
} else {
@ -378,14 +378,14 @@ class LibraryPresenter(
filterTrackers,
)
if (matches) {
missingCategorySet.remove(item.manga.category)
missingCategorySet.remove(item.library.category)
}
matches
}.toMutableList()
if (showEmptyCategoriesWhileFiltering) {
missingCategorySet.forEach {
filteredItems.add(
blankItem(it).first().apply { manga.realMangaCount = realCount[it] ?: 0 }
blankItem(it).first().apply { library.realMangaCount = realCount[it] ?: 0 }
)
}
}
@ -401,21 +401,21 @@ class LibraryPresenter(
return matchesCustomFilters(item, it, filterTrackers)
}
if (filterPrefs.filterUnread == STATE_INCLUDE && item.manga.unread == 0) return false
if (filterPrefs.filterUnread == STATE_EXCLUDE && item.manga.unread > 0) return false
if (filterPrefs.filterUnread == STATE_INCLUDE && item.library.unread == 0) return false
if (filterPrefs.filterUnread == STATE_EXCLUDE && item.library.unread > 0) return false
// Filter for unread chapters
if (filterPrefs.filterUnread == 3 && !(item.manga.unread > 0 && !item.manga.hasRead)) return false
if (filterPrefs.filterUnread == 4 && !(item.manga.unread > 0 && item.manga.hasRead)) return false
if (filterPrefs.filterUnread == 3 && !(item.library.unread > 0 && !item.library.hasRead)) return false
if (filterPrefs.filterUnread == 4 && !(item.library.unread > 0 && item.library.hasRead)) return false
if (filterPrefs.filterBookmarked == STATE_INCLUDE && item.manga.bookmarkCount == 0) return false
if (filterPrefs.filterBookmarked == STATE_EXCLUDE && item.manga.bookmarkCount > 0) return false
if (filterPrefs.filterBookmarked == STATE_INCLUDE && item.library.bookmarkCount == 0) return false
if (filterPrefs.filterBookmarked == STATE_EXCLUDE && item.library.bookmarkCount > 0) return false
if (filterPrefs.filterMangaType > 0) {
if (if (filterPrefs.filterMangaType == Manga.TYPE_MANHWA) {
item.manga.seriesType(sourceManager = sourceManager) !in arrayOf(filterPrefs.filterMangaType, Manga.TYPE_WEBTOON)
item.library.seriesType(sourceManager = sourceManager) !in arrayOf(filterPrefs.filterMangaType, Manga.TYPE_WEBTOON)
} else {
filterPrefs.filterMangaType != item.manga.seriesType(sourceManager = sourceManager)
filterPrefs.filterMangaType != item.library.seriesType(sourceManager = sourceManager)
}
) {
return false
@ -423,24 +423,24 @@ class LibraryPresenter(
}
// Filter for completed status of manga
if (filterPrefs.filterCompleted == STATE_INCLUDE && item.manga.status != SManga.COMPLETED) return false
if (filterPrefs.filterCompleted == STATE_EXCLUDE && item.manga.status == SManga.COMPLETED) return false
if (filterPrefs.filterCompleted == STATE_INCLUDE && item.library.status != SManga.COMPLETED) return false
if (filterPrefs.filterCompleted == STATE_EXCLUDE && item.library.status == SManga.COMPLETED) return false
if (!matchesFilterTracking(item, filterPrefs.filterTracked, filterTrackers)) return false
// Filter for downloaded manga
if (filterPrefs.filterDownloaded != STATE_IGNORE) {
val isDownloaded = when {
item.manga.isLocal() -> true
item.library.isLocal() -> true
item.downloadCount != -1 -> item.downloadCount > 0
else -> downloadManager.getDownloadCount(item.manga) > 0
else -> downloadManager.getDownloadCount(item.library) > 0
}
return if (filterPrefs.filterDownloaded == STATE_INCLUDE) isDownloaded else !isDownloaded
}
// Filter for NSFW/SFW contents
if (filterPrefs.filterContentType == STATE_INCLUDE) return !item.manga.isLewd()
if (filterPrefs.filterContentType == STATE_EXCLUDE) return item.manga.isLewd()
if (filterPrefs.filterContentType == STATE_INCLUDE) return !item.library.isLewd()
if (filterPrefs.filterContentType == STATE_EXCLUDE) return item.library.isLewd()
return true
}
@ -451,23 +451,23 @@ class LibraryPresenter(
): Boolean {
val statuses = customFilters.filterStatus
if (statuses.isNotEmpty()) {
if (item.manga.status !in statuses) return false
if (item.library.status !in statuses) return false
}
val seriesTypes = customFilters.filterMangaType
if (seriesTypes.isNotEmpty()) {
if (item.manga.seriesType(sourceManager = sourceManager) !in seriesTypes) return false
if (item.library.seriesType(sourceManager = sourceManager) !in seriesTypes) return false
}
val languages = customFilters.filterLanguages
if (languages.isNotEmpty()) {
if (getLanguage(item.manga) !in languages) return false
if (getLanguage(item.library) !in languages) return false
}
val sources = customFilters.filterSources
if (sources.isNotEmpty()) {
if (item.manga.source !in sources) return false
if (item.library.source !in sources) return false
}
val trackingScore = customFilters.filterTrackingScore
if (trackingScore > 0 || trackingScore == -1) {
val tracks = db.getTracks(item.manga).executeAsBlocking()
val tracks = db.getTracks(item.library).executeAsBlocking()
val hasTrack = loggedServices.any { service ->
tracks.any { it.sync_id == service.id }
@ -479,20 +479,20 @@ class LibraryPresenter(
if (!matchesFilterTracking(item, customFilters.filterTracked, filterTrackers)) return false
val startingYear = customFilters.filterStartYear
if (startingYear > 0) {
val mangaStartingYear = item.manga.getStartYear()
val mangaStartingYear = item.library.getStartYear()
if (mangaStartingYear != startingYear) return false
}
val mangaLength = customFilters.filterLength
if (mangaLength != null) {
if (item.manga.totalChapters !in mangaLength) return false
if (item.library.totalChapters !in mangaLength) return false
}
val categories = customFilters.filterCategories
if (categories.isNotEmpty()) {
if (item.manga.category !in categories) return false
if (item.library.category !in categories) return false
}
val tags = customFilters.filterTags
if (tags.isNotEmpty()) {
val genres = item.manga.getGenres() ?: return false
val genres = item.library.getGenres() ?: return false
if (tags.none { tag -> genres.any { it.equals(tag, true) } }) return false
}
return true
@ -532,7 +532,7 @@ class LibraryPresenter(
): Boolean {
// Filter for tracked (or per tracked service)
if (filterTracked != STATE_IGNORE) {
val tracks = db.getTracks(item.manga).executeAsBlocking()
val tracks = db.getTracks(item.library).executeAsBlocking()
val hasTrack = loggedServices.any { service ->
tracks.any { it.sync_id == service.id }
@ -581,7 +581,7 @@ class LibraryPresenter(
}
for (item in itemList) {
item.downloadCount = downloadManager.getDownloadCount(item.manga)
item.downloadCount = downloadManager.getDownloadCount(item.library)
}
}
@ -595,7 +595,7 @@ class LibraryPresenter(
private fun setSourceLanguage(itemList: List<LibraryItem>) {
val showLanguageBadges = preferences.languageBadge().get()
for (item in itemList) {
item.sourceLanguage = if (showLanguageBadges) getLanguage(item.manga) else null
item.sourceLanguage = if (showLanguageBadges) getLanguage(item.library) else null
}
}
@ -627,30 +627,30 @@ class LibraryPresenter(
category.mangaSort != null -> {
var sort = when (category.sortingMode() ?: LibrarySort.Title) {
LibrarySort.Title -> sortAlphabetical(i1, i2)
LibrarySort.LatestChapter -> i2.manga.last_update.compareTo(i1.manga.last_update)
LibrarySort.LatestChapter -> i2.library.last_update.compareTo(i1.library.last_update)
LibrarySort.Unread -> when {
i1.manga.unread == i2.manga.unread -> 0
i1.manga.unread == 0 -> if (category.isAscending()) 1 else -1
i2.manga.unread == 0 -> if (category.isAscending()) -1 else 1
else -> i1.manga.unread.compareTo(i2.manga.unread)
i1.library.unread == i2.library.unread -> 0
i1.library.unread == 0 -> if (category.isAscending()) 1 else -1
i2.library.unread == 0 -> if (category.isAscending()) -1 else 1
else -> i1.library.unread.compareTo(i2.library.unread)
}
LibrarySort.LastRead -> {
i1.manga.lastRead.compareTo(i2.manga.lastRead)
i1.library.lastRead.compareTo(i2.library.lastRead)
}
LibrarySort.TotalChapters -> {
i1.manga.totalChapters.compareTo(i2.manga.totalChapters)
i1.library.totalChapters.compareTo(i2.library.totalChapters)
}
LibrarySort.DateFetched -> {
i1.manga.lastFetch.compareTo(i2.manga.lastFetch)
i1.library.lastFetch.compareTo(i2.library.lastFetch)
}
LibrarySort.DateAdded -> i2.manga.date_added.compareTo(i1.manga.date_added)
LibrarySort.DateAdded -> i2.library.date_added.compareTo(i1.library.date_added)
LibrarySort.DragAndDrop -> {
if (category.isDynamic) {
val category1 =
allCategories.find { i1.manga.category == it.id }?.order
allCategories.find { i1.library.category == it.id }?.order
?: 0
val category2 =
allCategories.find { i2.manga.category == it.id }?.order
allCategories.find { i2.library.category == it.id }?.order
?: 0
category1.compareTo(category2)
} else {
@ -663,8 +663,8 @@ class LibraryPresenter(
}
category.mangaOrder.isNotEmpty() -> {
val order = category.mangaOrder
val index1 = order.indexOf(i1.manga.id!!)
val index2 = order.indexOf(i2.manga.id!!)
val index1 = order.indexOf(i1.library.id!!)
val index2 = order.indexOf(i2.library.id!!)
when {
index1 == index2 -> 0
index1 == -1 -> -1
@ -707,9 +707,9 @@ class LibraryPresenter(
*/
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
return if (removeArticles) {
i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true)
i1.library.title.removeArticles().compareTo(i2.library.title.removeArticles(), true)
} else {
i1.manga.title.compareTo(i2.manga.title, true)
i1.library.title.compareTo(i2.library.title, true)
}
}
@ -749,7 +749,7 @@ class LibraryPresenter(
return@forEach // No hidden manga to be handled
}
val mergedTitle = manga.joinToString("-") {
it.manga.title + "-" + it.manga.author
it.library.title + "-" + it.library.author
}
this.add(
LibraryItem(
@ -1110,9 +1110,9 @@ class LibraryPresenter(
)
}
} else if (catId in categoriesHidden && showAll && categories.size > 1) {
val mangaToRemove = items.filter { it.manga.category == catId }
val mangaToRemove = items.filter { it.library.category == catId }
val mergedTitle = mangaToRemove.joinToString("-") {
it.manga.title + "-" + it.manga.author
it.library.title + "-" + it.library.author
}
sectionedLibraryItems[catId] = mangaToRemove
hiddenItems.addAll(mangaToRemove)
@ -1306,7 +1306,7 @@ class LibraryPresenter(
if (category.isHidden) {
val mangaToRemove = items.filter { it.header.catId == catId }
val mergedTitle = mangaToRemove.joinToString("-") {
it.manga.title + "-" + it.manga.author
it.library.title + "-" + it.library.author
}
sectionedLibraryItems[catId] = mangaToRemove
items.removeAll { it.header.catId == catId }

View file

@ -371,7 +371,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
checked = true
var types = mutableSetOf<StringResource>()
libraryManga.forEach {
when (it.manga.seriesType(sourceManager = sourceManager)) {
when (it.library.seriesType(sourceManager = sourceManager)) {
Manga.TYPE_MANHWA, Manga.TYPE_WEBTOON -> types.add(MR.strings.manhwa)
Manga.TYPE_MANHUA -> types.add(MR.strings.manhua)
Manga.TYPE_COMIC -> types.add(MR.strings.comic)

View file

@ -1,11 +1,11 @@
package eu.kanade.tachiyomi.util.chapter
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.manga.models.Manga
class ChapterSort(val manga: Manga, val chapterFilter: ChapterFilter = Injekt.get(), val preferences: PreferencesHelper = Injekt.get()) {